Revert until Martin is online to debug
[mono.git] / mono / metadata / loader.c
index 8aa9e643fab25ee9ab241dbb552e57022cbda6e7..1fe54a207fdad96daab4e25142ed9a7edcbe0bde 100644 (file)
@@ -84,6 +84,36 @@ set_loader_error (MonoLoaderError *error)
        TlsSetValue (loader_error_thread_id, error);
 }
 
+/**
+ * mono_loader_set_error_assembly_load:
+ *
+ * Set the loader error for this thread. 
+ */
+void
+mono_loader_set_error_assembly_load (const char *assembly_name, gboolean ref_only)
+{
+       MonoLoaderError *error;
+
+       if (mono_loader_get_last_error ()) 
+               return;
+
+       error = g_new0 (MonoLoaderError, 1);
+       error->kind = MONO_LOADER_ERROR_ASSEMBLY;
+       error->assembly_name = g_strdup (assembly_name);
+       error->ref_only = ref_only;
+
+       /* 
+        * This is not strictly needed, but some (most) of the loader code still
+        * can't deal with load errors, and this message is more helpful than an
+        * assert.
+        */
+       if (ref_only)
+               g_warning ("Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.", assembly_name);
+       else
+               g_warning ("Could not load file or assembly '%s' or one of its dependencies.", assembly_name);
+
+       set_loader_error (error);
+}
 
 /**
  * mono_loader_set_error_type_load:
@@ -181,11 +211,13 @@ mono_loader_clear_error (void)
 {
        MonoLoaderError *ex = (MonoLoaderError*)TlsGetValue (loader_error_thread_id);
 
+       if (ex) {
         g_free (ex->class_name);
         g_free (ex->assembly_name);
-       g_free (ex);
+               g_free (ex);
        
-       TlsSetValue (loader_error_thread_id, NULL);
+               TlsSetValue (loader_error_thread_id, NULL);
+       }
 }
 
 /**
@@ -199,10 +231,10 @@ mono_loader_clear_error (void)
 MonoException *
 mono_loader_error_prepare_exception (MonoLoaderError *error)
 {
-        MonoException *ex = NULL;
+       MonoException *ex = NULL;
 
-        switch (error->kind) {
-        case MONO_LOADER_ERROR_TYPE: {
+       switch (error->kind) {
+       case MONO_LOADER_ERROR_TYPE: {
                char *cname = g_strdup (error->class_name);
                char *aname = g_strdup (error->assembly_name);
                MonoString *class_name;
@@ -216,19 +248,18 @@ mono_loader_error_prepare_exception (MonoLoaderError *error)
                g_free (aname);
                 break;
         }
-        case MONO_LOADER_ERROR_METHOD: {
+       case MONO_LOADER_ERROR_METHOD: {
                char *cname = g_strdup (error->class_name);
                char *aname = g_strdup (error->member_name);
-               MonoString *class_name;
                
                mono_loader_clear_error ();
-                ex = mono_get_exception_missing_method (cname, aname);
+               ex = mono_get_exception_missing_method (cname, aname);
                g_free (cname);
                g_free (aname);
                break;
        }
                
-        case MONO_LOADER_ERROR_FIELD: {
+       case MONO_LOADER_ERROR_FIELD: {
                char *cnspace = g_strdup (*error->klass->name_space ? error->klass->name_space : "");
                char *cname = g_strdup (error->klass->name);
                char *cmembername = g_strdup (error->member_name);
@@ -244,11 +275,26 @@ mono_loader_error_prepare_exception (MonoLoaderError *error)
                g_free (cnspace);
                 break;
         }
-        default:
-                g_assert_not_reached ();
-        }
+       
+       case MONO_LOADER_ERROR_ASSEMBLY: {
+               char *msg;
 
-        return ex;
+               if (error->ref_only)
+                       msg = g_strdup_printf ("Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.", error->assembly_name);
+               else
+                       msg = g_strdup_printf ("Could not load file or assembly '%s' or one of its dependencies.", error->assembly_name);
+
+               mono_loader_clear_error ();
+               ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), error->assembly_name));
+               g_free (msg);
+               break;
+       }
+       
+       default:
+               g_assert_not_reached ();
+       }
+
+       return ex;
 }
 
 static MonoClassField*
@@ -731,6 +777,7 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp
 
        if (!method) {
                char *msig = mono_signature_get_desc (sig, FALSE);
+               char * class_name = mono_type_get_name (&klass->byval_arg);
                GString *s = g_string_new (mname);
                if (sig->generic_param_count)
                        g_string_append_printf (s, "<[%d]>", sig->generic_param_count);
@@ -740,9 +787,10 @@ method_from_memberref (MonoImage *image, guint32 idx, MonoGenericContext *typesp
 
                g_warning (
                        "Missing method %s::%s in assembly %s, referenced in assembly %s",
-                       mono_type_get_name (&klass->byval_arg), msig, klass->image->name, image->name);
+                       class_name, msig, klass->image->name, image->name);
+               mono_loader_set_error_method_load (class_name, mname);
                g_free (msig);
-               mono_loader_set_error_method_load (klass, mname);
+               g_free (class_name);
        }
        mono_metadata_free_method_signature (sig);
 
@@ -1310,7 +1358,7 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass,
        }
 
        /* FIXME: lazyness for generics too, but how? */
-       if (!result->klass->dummy && !(result->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
+       if (!(result->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
            !(cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
            !(result->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) && container) {
                gpointer loc = mono_image_rva_map (image, cols [0]);
@@ -1691,6 +1739,11 @@ mono_loader_unlock (void)
        LeaveCriticalSection (&loader_mutex);
 }
 
+/**
+ * mono_method_signature:
+ *
+ * Return the signature of the method M. On failure, returns NULL.
+ */
 MonoMethodSignature*
 mono_method_signature (MonoMethod *m)
 {
@@ -1753,6 +1806,10 @@ mono_method_signature (MonoMethod *m)
                size = mono_metadata_decode_blob_size (sig, &sig_body);
 
                m->signature = mono_metadata_parse_method_signature_full (img, container, idx, sig_body, NULL);
+               if (!m->signature) {
+                       mono_loader_unlock ();
+                       return NULL;
+               }
 
                if (can_cache_signature)
                        g_hash_table_insert (img->method_signatures, (gpointer)sig, m->signature);
@@ -1832,7 +1889,7 @@ mono_method_get_header (MonoMethod *method)
        gpointer loc;
        MonoMethodNormal* mn = (MonoMethodNormal*) method;
 
-       if (method->klass->dummy || (method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
+       if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
                return NULL;
 
 #ifdef G_LIKELY