Mon Apr 15 11:37:33 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / loader.c
index 5aae9ccd545d91d34d53cdcaf74f328585035b1e..42f9c2366eec4b05b8ac30be0062cd989723e64d 100644 (file)
@@ -33,7 +33,10 @@ static gboolean dummy_icall = TRUE;
 
 MonoDefaults mono_defaults;
 
-static char *dll_map[] = {
+#ifdef __CYGWIN__
+#define mono_map_dll(name) (name)
+#else
+static const char *dll_map[] = {
        "libc", "libc.so.6",
        "libm", "libm.so.6",
        "cygwin1.dll", "libc.so.6", 
@@ -53,108 +56,12 @@ mono_map_dll (const char *name)
 
        return name;
 }
-
-void
-mono_init (void)
-{
-       static gboolean initialized = FALSE;
-       MonoAssembly *ass;
-       enum MonoImageOpenStatus status = MONO_IMAGE_OK;
-
-       if (initialized)
-               return;
-
-       /* find the corlib */
-       ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
-       g_assert (status == MONO_IMAGE_OK);
-       g_assert (ass != NULL);
-       mono_defaults.corlib = ass->image;
-
-       mono_defaults.object_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Object");
-       g_assert (mono_defaults.object_class != 0);
-
-       mono_defaults.void_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Void");
-       g_assert (mono_defaults.void_class != 0);
-
-       mono_defaults.boolean_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Boolean");
-       g_assert (mono_defaults.boolean_class != 0);
-
-       mono_defaults.byte_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Byte");
-       g_assert (mono_defaults.byte_class != 0);
-
-       mono_defaults.sbyte_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "SByte");
-       g_assert (mono_defaults.sbyte_class != 0);
-
-       mono_defaults.int16_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Int16");
-       g_assert (mono_defaults.int16_class != 0);
-
-       mono_defaults.uint16_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "UInt16");
-       g_assert (mono_defaults.uint16_class != 0);
-
-       mono_defaults.int32_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Int32");
-       g_assert (mono_defaults.int32_class != 0);
-
-       mono_defaults.uint32_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "UInt32");
-       g_assert (mono_defaults.uint32_class != 0);
-
-       mono_defaults.uint_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "UIntPtr");
-       g_assert (mono_defaults.uint_class != 0);
-
-       mono_defaults.int_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "IntPtr");
-       g_assert (mono_defaults.int_class != 0);
-
-       mono_defaults.int64_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Int64");
-       g_assert (mono_defaults.int64_class != 0);
-
-       mono_defaults.uint64_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "UInt64");
-       g_assert (mono_defaults.uint64_class != 0);
-
-       mono_defaults.single_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Single");
-       g_assert (mono_defaults.single_class != 0);
-
-       mono_defaults.double_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Double");
-       g_assert (mono_defaults.double_class != 0);
-
-       mono_defaults.char_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Char");
-       g_assert (mono_defaults.char_class != 0);
-
-       mono_defaults.string_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "String");
-       g_assert (mono_defaults.string_class != 0);
-
-       mono_defaults.enum_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Enum");
-       g_assert (mono_defaults.enum_class != 0);
-
-       mono_defaults.array_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Array");
-       g_assert (mono_defaults.array_class != 0);
-
-       mono_defaults.delegate_class = mono_class_from_name (
-                mono_defaults.corlib, "System", "Delegate");
-       g_assert (mono_defaults.delegate_class != 0);
-}
+#endif
 
 static GHashTable *icall_hash = NULL;
 
 void
-mono_add_internal_call (const char *name, gpointer method)
+mono_add_internal_call (const char *name, gconstpointer method)
 {
        if (!icall_hash) {
                dummy_icall = FALSE;
@@ -165,7 +72,7 @@ mono_add_internal_call (const char *name, gpointer method)
 }
 
 static void
-ves_icall_dummy ()
+ves_icall_dummy (void)
 {
        g_warning ("the mono runtime is not initialized");
        g_assert_not_reached ();
@@ -186,14 +93,86 @@ mono_lookup_internal_call (const char *name)
 
        if (!(res = g_hash_table_lookup (icall_hash, name))) {
                g_warning ("cant resolve internal call to \"%s\"", name);
-               g_assert_not_reached ();
+               return NULL;
        }
 
        return res;
 }
 
+MonoClassField*
+mono_field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass)
+{
+       MonoImage *mimage;
+       MonoClass *klass;
+       MonoTableInfo *tables = image->tables;
+       guint32 cols[6];
+       guint32 nindex, class, i;
+       const char *fname, *name, *nspace;
+       const char *ptr;
+       guint32 idx = mono_metadata_token_index (token);
+
+       mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], idx-1, cols, MONO_MEMBERREF_SIZE);
+       nindex = cols [MONO_MEMBERREF_CLASS] >> MEMBERREF_PARENT_BITS;
+       class = cols [MONO_MEMBERREF_CLASS] & MEMBERREF_PARENT_MASK;
+
+       fname = mono_metadata_string_heap (image, cols [MONO_MEMBERREF_NAME]);
+       
+       ptr = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
+       mono_metadata_decode_blob_size (ptr, &ptr);
+       /* we may want to check the signature here... */
+
+       switch (class) {
+       case MEMBERREF_PARENT_TYPEREF: {
+               guint32 scopeindex, scopetable;
+
+               mono_metadata_decode_row (&tables [MONO_TABLE_TYPEREF], nindex-1, cols, MONO_TYPEREF_SIZE);
+               scopeindex = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
+               scopetable = cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK;
+               /*g_print ("typeref: 0x%x 0x%x %s.%s\n", scopetable, scopeindex,
+                       mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]),
+                       mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]));*/
+               switch (scopetable) {
+               case RESOLTION_SCOPE_ASSEMBLYREF:
+                       /*
+                        * To find the field we have the following info:
+                        * *) name and namespace of the class from the TYPEREF table
+                        * *) name and signature of the field from the MEMBERREF table
+                        */
+                       nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
+                       name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
+
+                       /* this will triggered by references to mscorlib */
+                       if (image->references [scopeindex-1] == NULL)
+                               g_error ("Reference to mscorlib? Probably need to implement %s.%s::%s in corlib", nspace, name, fname);
+
+                       mimage = image->references [scopeindex-1]->image;
+
+                       klass = mono_class_from_name (mimage, nspace, name);
+                       mono_class_init (klass);
+
+                       /* mostly dumb search for now */
+                       for (i = 0; i < klass->field.count; ++i) {
+                               MonoClassField *f = &klass->fields [i];
+                               if (!strcmp (fname, f->name)) {
+                                       if (retklass)
+                                               *retklass = klass;
+                                       return f;
+                               }
+                       }
+                       g_warning ("Missing field %s.%s::%s", nspace, name, fname);
+                       return NULL;
+               default:
+                       return NULL;
+               }
+               break;
+       }
+       default:
+               return NULL;
+       }
+}
+
 static MonoMethod *
-method_from_memberref (MonoImage *image, guint32 index)
+method_from_memberref (MonoImage *image, guint32 idx)
 {
        MonoImage *mimage;
        MonoClass *klass;
@@ -204,7 +183,7 @@ method_from_memberref (MonoImage *image, guint32 index)
        MonoMethodSignature *sig;
        const char *ptr;
 
-       mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], index-1, cols, 3);
+       mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
        nindex = cols [MONO_MEMBERREF_CLASS] >> MEMBERREF_PARENT_BITS;
        class = cols [MONO_MEMBERREF_CLASS] & MEMBERREF_PARENT_MASK;
        /*g_print ("methodref: 0x%x 0x%x %s\n", class, nindex,
@@ -243,7 +222,12 @@ method_from_memberref (MonoImage *image, guint32 index)
                        mimage = image->references [scopeindex-1]->image;
 
                        klass = mono_class_from_name (mimage, nspace, name);
-                       mono_class_metadata_init (klass);
+                       if (!klass) {
+                               g_warning ("Missing method %s.%s::%s", nspace, name, mname);
+                               mono_metadata_free_method_signature (sig);
+                               return NULL;
+                       }
+                       mono_class_init (klass);
 
                        /* mostly dumb search for now */
                        for (i = 0; i < klass->method.count; ++i) {
@@ -255,11 +239,12 @@ method_from_memberref (MonoImage *image, guint32 index)
                                        }
                                }
                        }
-                       g_warning ("can't find method %s.%s::%s", nspace, name, mname);
-                       g_assert_not_reached ();
-                       break;
+                       g_warning ("Missing method %s.%s::%s", nspace, name, mname);
+                       mono_metadata_free_method_signature (sig);
+                       return NULL;
                default:
-                       g_assert_not_reached ();
+                       mono_metadata_free_method_signature (sig);
+                       return NULL;
                }
                break;
        }
@@ -279,24 +264,17 @@ method_from_memberref (MonoImage *image, guint32 index)
                        g_assert_not_reached ();                
 
                result = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
-               result->klass = mono_defaults.array_class;
+               result->klass = mono_class_get (image, MONO_TOKEN_TYPE_SPEC | nindex);
                result->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
                result->signature = sig;
                result->name = mname;
 
-               if (!strcmp (mname, ".ctor")) { 
-                       g_assert (sig->hasthis);
-                       if (type->data.array->rank == sig->param_count) {
-                               result->addr = mono_lookup_internal_call ("__array_ctor");
-                       } else if ((type->data.array->rank * 2) == sig->param_count) {
-                               result->addr = mono_lookup_internal_call ("__array_bound_ctor");
-                       } else 
-                               g_assert_not_reached ();
-
-                       result->flags = METHOD_ATTRIBUTE_PINVOKE_IMPL;
-                       return result;                                          
+               if (!strcmp (mname, ".ctor")) {
+                       /* we special-case this in the runtime. */
+                       result->addr = NULL;
+                       return result;
                }
-
+               
                if (!strcmp (mname, "Set")) {
                        g_assert (sig->hasthis);
                        g_assert (type->data.array->rank + 1 == sig->param_count);
@@ -313,6 +291,14 @@ method_from_memberref (MonoImage *image, guint32 index)
                        return result;
                }
 
+               if (!strcmp (mname, "Address")) {
+                       g_assert (sig->hasthis);
+                       g_assert (type->data.array->rank == sig->param_count);
+
+                       result->addr = mono_lookup_internal_call ("__array_Address");
+                       return result;
+               }
+
                g_assert_not_reached ();
                break;
        }
@@ -324,7 +310,7 @@ method_from_memberref (MonoImage *image, guint32 index)
 }
 
 static void
-fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int index)
+fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int idx)
 {
        MonoMethod *mh = &piinfo->method;
        MonoTableInfo *tables = image->tables;
@@ -342,7 +328,7 @@ fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int index)
                        
                mono_metadata_decode_row (im, i, im_cols, 4);
 
-               if ((im_cols[1] >> 1) == index + 1) {
+               if ((im_cols[1] >> 1) == idx + 1) {
 
                        import = mono_metadata_string_heap (image, im_cols [2]);
 
@@ -361,14 +347,22 @@ fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int index)
        full_name = g_module_build_path (NULL, scope);
        gmodule = g_module_open (full_name, G_MODULE_BIND_LAZY);
 
-       if (!gmodule)
-               g_error ("Failed to load library %s (%s)", full_name, scope);
+       mh->addr = NULL;
+       if (!gmodule) {
+               if (!(gmodule=g_module_open (scope, G_MODULE_BIND_LAZY))) {
+                       g_warning ("Failed to load library %s (%s)", full_name, scope);
+                       g_free (full_name);
+                       return;
+               }
+       }
        g_free (full_name);
 
        g_module_symbol (gmodule, import, &mh->addr); 
 
-       if (!mh->addr)
-               g_error ("Failed to load function %s from %s", import, scope);
+       if (!mh->addr) {
+               g_warning ("Failed to load function %s from %s", import, scope);
+               return;
+       }
 
        mh->flags |= METHOD_ATTRIBUTE_PINVOKE_IMPL;
 }
@@ -378,22 +372,26 @@ mono_get_method (MonoImage *image, guint32 token, MonoClass *klass)
 {
        MonoMethod *result;
        int table = mono_metadata_token_table (token);
-       int index = mono_metadata_token_index (token);
+       int idx = mono_metadata_token_index (token);
        MonoTableInfo *tables = image->tables;
        const char *loc, *sig = NULL;
        char *name;
        int size;
        guint32 cols [MONO_TYPEDEF_SIZE];
 
-       if (table == MONO_TABLE_METHOD && (result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
+       if ((result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
                        return result;
 
        if (table != MONO_TABLE_METHOD) {
+               if (table != MONO_TABLE_MEMBERREF)
+                       g_print("got wrong token: 0x%08x\n", token);
                g_assert (table == MONO_TABLE_MEMBERREF);
-               return method_from_memberref (image, index);
+               result = method_from_memberref (image, idx);
+               g_hash_table_insert (image->method_cache, GINT_TO_POINTER (token), result);
+               return result;
        }
 
-       mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
+       mono_metadata_decode_row (&tables [table], idx - 1, cols, 6);
 
        if ((cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
            (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
@@ -401,6 +399,7 @@ mono_get_method (MonoImage *image, guint32 token, MonoClass *klass)
        else 
                result = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
        
+       result->slot = -1;
        result->klass = klass;
        result->flags = cols [2];
        result->iflags = cols [1];
@@ -417,28 +416,13 @@ mono_get_method (MonoImage *image, guint32 token, MonoClass *klass)
        }
 
        if (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
-               MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
-               guint32 tdef;
-               guint32 tdcols [MONO_TYPEDEF_SIZE];
-
-               tdef = mono_metadata_typedef_from_method (image, index - 1) - 1;
-
-               mono_metadata_decode_row (t, tdef, tdcols, MONO_TYPEDEF_SIZE);
-
-               name = g_strconcat (mono_metadata_string_heap (image, tdcols [MONO_TYPEDEF_NAMESPACE]), ".",
-                                   mono_metadata_string_heap (image, tdcols [MONO_TYPEDEF_NAME]), "::", 
+               name = g_strconcat (result->klass->name_space, ".", result->klass->name, "::", 
                                    mono_metadata_string_heap (image, cols [MONO_METHOD_NAME]), NULL);
-
                result->addr = mono_lookup_internal_call (name);
-
                g_free (name);
-
-               g_assert (result->addr != NULL);
-
                result->flags |= METHOD_ATTRIBUTE_PINVOKE_IMPL;
-
        } else if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
-               fill_pinvoke_info (image, (MonoMethodPInvoke *)result, index - 1);
+               fill_pinvoke_info (image, (MonoMethodPInvoke *)result, idx - 1);
        } else {
                /* if this is a methodref from another module/assembly, this fails */
                loc = mono_cli_rva_map ((MonoCLIImageInfo *)image->image_info, cols [0]);
@@ -469,3 +453,40 @@ mono_free_method  (MonoMethod *method)
        g_free (method);
 }
 
+void
+mono_method_get_param_names (MonoMethod *method, const char **names)
+{
+       int i, lastp;
+       MonoClass *klass = method->klass;
+       MonoTableInfo *methodt = &klass->image->tables [MONO_TABLE_METHOD];
+       MonoTableInfo *paramt = &klass->image->tables [MONO_TABLE_PARAM];
+
+       if (!method->signature->param_count)
+               return;
+       for (i = 0; i < method->signature->param_count; ++i)
+               names [i] = "";
+
+       mono_class_init (klass);
+       if (!klass->methods)
+               return;
+
+       for (i = 0; i < klass->method.count; ++i) {
+               if (method == klass->methods [i]) {
+                       guint32 idx = klass->method.first + i;
+                       guint32 cols [MONO_PARAM_SIZE];
+                       guint param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
+
+                       if (idx < methodt->rows)
+                               lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
+                       else
+                               lastp = paramt->rows;
+                       for (i = param_index; i < lastp; ++i) {
+                               mono_metadata_decode_row (paramt, i -1, cols, MONO_PARAM_SIZE);
+                               if (cols [MONO_PARAM_SEQUENCE]) /* skip return param spec */
+                                       names [cols [MONO_PARAM_SEQUENCE] - 1] = mono_metadata_string_heap (klass->image, cols [MONO_PARAM_NAME]);
+                       }
+                       return;
+               }
+       }
+}
+