[io-layer] Extract error (#4279)
[mono.git] / mono / metadata / assembly.c
index ff098ae934f8f7cf3279e0bb0d1ed9a5763302fb..e909833e7c7231cfb6091c143768ab8234e8c549 100644 (file)
@@ -22,6 +22,7 @@
 #include "object-internals.h"
 #include <mono/metadata/loader.h>
 #include <mono/metadata/tabledefs.h>
+#include <mono/metadata/custom-attrs-internals.h>
 #include <mono/metadata/metadata-internals.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/class-internals.h>
@@ -29,7 +30,6 @@
 #include <mono/metadata/reflection-internals.h>
 #include <mono/metadata/mono-endian.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/io-layer/io-layer.h>
 #include <mono/utils/mono-uri.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/mono-config-dirs.h>
@@ -205,8 +205,6 @@ static GSList *loaded_assembly_bindings = NULL;
 
 /* Class lazy loading functions */
 static GENERATE_TRY_GET_CLASS_WITH_CACHE (internals_visible, System.Runtime.CompilerServices, InternalsVisibleToAttribute)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (reference_assembly, System.Runtime.CompilerServices, ReferenceAssemblyAttribute)
-
 static MonoAssembly*
 mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, MonoAssembly *requesting, gboolean refonly, gboolean postload);
 static MonoAssembly*
@@ -570,7 +568,7 @@ mono_assembly_getrootdir (void)
  * Returns: a string with the directory, this string should be freed by
  * the caller.
  */
-G_CONST_RETURN gchar *
+gchar *
 mono_native_getrootdir (void)
 {
        gchar* fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), mono_config_get_reloc_lib_dir(), NULL);
@@ -800,7 +798,7 @@ mono_assembly_binding_unlock (void)
 }
 
 gboolean
-mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
+mono_assembly_fill_assembly_name_full (MonoImage *image, MonoAssemblyName *aname, gboolean copyBlobs)
 {
        MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLY];
        guint32 cols [MONO_ASSEMBLY_SIZE];
@@ -814,7 +812,11 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
        aname->hash_len = 0;
        aname->hash_value = NULL;
        aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_NAME]);
+       if (copyBlobs)
+               aname->name = g_strdup (aname->name);
        aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_CULTURE]);
+       if (copyBlobs)
+               aname->culture = g_strdup (aname->culture);
        aname->flags = cols [MONO_ASSEMBLY_FLAGS];
        aname->major = cols [MONO_ASSEMBLY_MAJOR_VERSION];
        aname->minor = cols [MONO_ASSEMBLY_MINOR_VERSION];
@@ -845,6 +847,16 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
 
        if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) {
                aname->public_key = (guchar*)mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]);
+               if (copyBlobs) {
+                       const gchar *pkey_end;
+                       int len = mono_metadata_decode_blob_size ((const gchar*) aname->public_key, &pkey_end);
+                       pkey_end += len; /* move to end */
+                       size_t size = pkey_end - (const gchar*)aname->public_key;
+                       guchar *tmp = g_new (guchar, size);
+                       memcpy (tmp, aname->public_key, size);
+                       aname->public_key = tmp;
+               }
+
        }
        else
                aname->public_key = 0;
@@ -877,6 +889,12 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
        return TRUE;
 }
 
+gboolean
+mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
+{
+       return mono_assembly_fill_assembly_name_full (image, aname, FALSE);
+}
+
 /**
  * mono_stringify_assembly_name:
  * @aname: the assembly name.
@@ -1228,7 +1246,7 @@ mono_assembly_load_reference (MonoImage *image, int index)
                                    image->assembly->aname.name, image->assembly, reference->aname.name, reference, reference->ref_count);
                } else {
                        if (image->assembly)
-                               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p]\n",
+                               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p].",
                                    image->assembly->aname.name, image->assembly);
                }
                
@@ -1828,6 +1846,24 @@ mono_assembly_load_friends (MonoAssembly* ass)
        mono_assemblies_unlock ();
 }
 
+struct HasReferenceAssemblyAttributeIterData {
+       gboolean has_attr;
+};
+
+static gboolean
+has_reference_assembly_attribute_iterator (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, gpointer user_data)
+{
+       gboolean stop_scanning = FALSE;
+       struct HasReferenceAssemblyAttributeIterData *iter_data = (struct HasReferenceAssemblyAttributeIterData*)user_data;
+
+       if (!strcmp (name, "ReferenceAssemblyAttribute") && !strcmp (nspace, "System.Runtime.CompilerServices")) {
+               /* Note we don't check the assembly name, same as coreCLR. */
+               iter_data->has_attr = TRUE;
+               stop_scanning = TRUE;
+       }
+
+       return stop_scanning;
+}
 
 /**
  * mono_assembly_has_reference_assembly_attribute:
@@ -1842,24 +1878,16 @@ mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoErro
 {
        mono_error_init (error);
 
-/* TODO: mono_custom_attrs_from_assembly_checked returns NULL if a
- * single assembly is missing.  The custom attr we want is from
- * corlib, however, so we need a more robust version that doesn't care
- * about missing attributes.
- */
-#if 0
-       MonoCustomAttrInfo *attrs = mono_custom_attrs_from_assembly_checked (assembly, TRUE, error);
-       return_val_if_nok (error, FALSE);
-       if (!attrs)
-               return FALSE;
-       MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
-       g_assert (ref_asm_class != NULL && ref_asm_class != mono_defaults.object_class && !strcmp(ref_asm_class->name, "ReferenceAssemblyAttribute") );
-       gboolean result = mono_custom_attrs_has_attr (attrs, ref_asm_class);
-       mono_custom_attrs_free (attrs);
-       return result;
-#else
-       return FALSE;
-#endif
+       /*
+        * This might be called during assembly loading, so do everything using the low-level
+        * metadata APIs.
+        */
+
+       struct HasReferenceAssemblyAttributeIterData iter_data = { FALSE };
+
+       mono_assembly_metadata_foreach_custom_attr (assembly, &has_reference_assembly_attribute_iterator, &iter_data);
+
+       return iter_data.has_attr;
 }
 
 /**
@@ -1981,24 +2009,6 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname,
                }
        }
 
-       mono_assemblies_lock ();
-
-       if (image->assembly) {
-               /* 
-                * This means another thread has already loaded the assembly, but not yet
-                * called the load hooks so the search hook can't find the assembly.
-                */
-               mono_assemblies_unlock ();
-               ass2 = image->assembly;
-               g_free (ass);
-               g_free (base_dir);
-               mono_image_close (image);
-               *status = MONO_IMAGE_OK;
-               return ass2;
-       }
-
-       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
-
        /* We need to check for ReferenceAssmeblyAttribute before we
         * mark the assembly as loaded and before we fire the load
         * hook. Otherwise mono_domain_fire_assembly_load () in
@@ -2006,17 +2016,9 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname,
         * this image and we won't be able to look for a different
         * candidate. */
 
-       if (!refonly && strcmp (ass->aname.name, "mscorlib") != 0) {
-               /* Don't check for reference assmebly attribute for
-                * corlib here because if corlib isn't loaded yet,
-                * it's too early to set up the
-                * ReferenceAssemblyAttribute class.  We check that
-                * we're not running with a reference corlib in
-                * mono_init_internal().
-                */
+       if (!refonly) {
                MonoError refasm_error;
                if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
-                       mono_assemblies_unlock ();
                        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);
                        g_free (ass);
                        g_free (base_dir);
@@ -2027,6 +2029,24 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname,
                mono_error_cleanup (&refasm_error);
        }
 
+       mono_assemblies_lock ();
+
+       if (image->assembly) {
+               /*
+                * This means another thread has already loaded the assembly, but not yet
+                * called the load hooks so the search hook can't find the assembly.
+                */
+               mono_assemblies_unlock ();
+               ass2 = image->assembly;
+               g_free (ass);
+               g_free (base_dir);
+               mono_image_close (image);
+               *status = MONO_IMAGE_OK;
+               return ass2;
+       }
+
+       mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
+
        image->assembly = ass;
 
        loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
@@ -2702,27 +2722,21 @@ mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *sta
        res = probe_for_partial_name (gacpath, fullname, aname, status);
        g_free (gacpath);
 
+       g_free (fullname);
+       mono_assembly_name_free (aname);
+
        if (res)
                res->in_gac = TRUE;
        else {
                MonoDomain *domain = mono_domain_get ();
-               MonoReflectionAssembly *refasm;
 
-               refasm = mono_try_assembly_resolve (domain, mono_string_new (domain, name), NULL, FALSE, &error);
+               res = mono_try_assembly_resolve (domain, name, NULL, FALSE, &error);
                if (!is_ok (&error)) {
-                       g_free (fullname);
-                       mono_assembly_name_free (aname);
                        mono_error_cleanup (&error);
                        if (*status == MONO_IMAGE_OK)
                                *status = MONO_IMAGE_IMAGE_INVALID;
                }
-
-               if (refasm)
-                       res = refasm->assembly;
        }
-       
-       g_free (fullname);
-       mono_assembly_name_free (aname);
 
        return res;
 }