Merge pull request #3992 from lambdageek/dev-handles-srassembly
[mono.git] / mono / metadata / assembly.c
index f4a941f2df718ff37a21045ba627e876c2d48442..2bf24e8c1a60d06fb67c8e86e4ff50f476da5d67 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>
@@ -39,7 +40,6 @@
 #include <mono/metadata/reflection.h>
 #include <mono/metadata/coree.h>
 #include <mono/metadata/cil-coff.h>
-#include <mono/metadata/tokentype.h>
 #include <mono/utils/mono-io-portability.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-os-mutex.h>
@@ -206,8 +206,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*
@@ -801,7 +799,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];
@@ -815,7 +813,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];
@@ -846,6 +848,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;
@@ -878,6 +890,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.
@@ -1229,7 +1247,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);
                }
                
@@ -1829,6 +1847,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:
@@ -1841,12 +1877,6 @@ mono_assembly_load_friends (MonoAssembly* ass)
 gboolean
 mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
 {
-       MonoImage *image;
-       guint32 mtoken, i;
-       guint32 cols [MONO_CUSTOM_ATTR_SIZE];
-       MonoTableInfo *ca;
-       guint32 idx;
-
        mono_error_init (error);
 
        /*
@@ -1854,64 +1884,11 @@ mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoErro
         * metadata APIs.
         */
 
-       image = assembly->image;
-       idx = 1; /* there is only one assembly */
-       idx <<= MONO_CUSTOM_ATTR_BITS;
-       idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
+       struct HasReferenceAssemblyAttributeIterData iter_data = { FALSE };
 
-       /* Inlined from mono_custom_attrs_from_index_checked () */
-       ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
-       i = mono_metadata_custom_attrs_from_index (image, idx);
-       if (!i)
-               return FALSE;
-       i --;
-       while (i < ca->rows) {
-               if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
-                       break;
-               mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
-               i ++;
-               mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
-               if ((cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) != MONO_CUSTOM_ATTR_TYPE_MEMBERREF)
-                       continue;
-               mtoken |= MONO_TOKEN_MEMBER_REF;
-               {
-                       /* method_from_memberref () */
-                       guint32 cols[6];
-                       guint32 nindex, class_index;
-
-                       int idx = mono_metadata_token_index (mtoken);
-
-                       mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], idx-1, cols, 3);
-                       nindex = cols [MONO_MEMBERREF_CLASS] >> MONO_MEMBERREF_PARENT_BITS;
-                       class_index = cols [MONO_MEMBERREF_CLASS] & MONO_MEMBERREF_PARENT_MASK;
-                       if (class_index == MONO_MEMBERREF_PARENT_TYPEREF) {
-                               guint32 type_token = MONO_TOKEN_TYPE_REF | nindex;
-                               /* mono_class_from_typeref_checked () */
-                               {
-                                       guint32 cols [MONO_TYPEREF_SIZE];
-                                       const char *name, *nspace;
-                                       MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
-                                       guint32 idx;
-
-                                       mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
-
-                                       name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
-                                       nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
-                                       idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
-
-                                       if (!strcmp (name, "ReferenceAssemblyAttribute") && !strcmp (nspace, "System.Runtime.CompilerServices")) {
-                                               if ((cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF) {
-                                                       MonoAssemblyName aname;
-                                                       mono_assembly_get_assemblyref (image, idx - 1, &aname);
-                                                       if (!strcmp (aname.name, "System.Runtime") || !strcmp (aname.name, "mscorlib"))
-                                                               return TRUE;
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-       return FALSE;
+       mono_assembly_metadata_foreach_custom_attr (assembly, &has_reference_assembly_attribute_iterator, &iter_data);
+
+       return iter_data.has_attr;
 }
 
 /**
@@ -2040,14 +2017,7 @@ 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_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);