Merge pull request #3335 from lambdageek/dev/system-reflection-assembly
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Mon, 1 Aug 2016 14:41:37 +0000 (10:41 -0400)
committerGitHub <noreply@github.com>
Mon, 1 Aug 2016 14:41:37 +0000 (10:41 -0400)
[reflection] Move AssemblyName to managed

mcs/class/corlib/Mono/RuntimeMarshal.cs [new file with mode: 0644]
mcs/class/corlib/Mono/RuntimeStructs.cs
mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs
mcs/class/corlib/System.Reflection/Assembly.cs
mcs/class/corlib/System.Reflection/AssemblyName.cs
mcs/class/corlib/System.Reflection/MonoAssembly.cs
mcs/class/corlib/corlib.dll.sources
mono/metadata/assembly.c
mono/metadata/icall-def.h
mono/metadata/icall.c

diff --git a/mcs/class/corlib/Mono/RuntimeMarshal.cs b/mcs/class/corlib/Mono/RuntimeMarshal.cs
new file mode 100644 (file)
index 0000000..38da4e2
--- /dev/null
@@ -0,0 +1,65 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono {
+       internal static class RuntimeMarshal {
+               internal static string PtrToUtf8String (IntPtr ptr)
+               {
+                       unsafe {
+                               return new String ((sbyte*)ptr);
+                       }
+               }
+
+               internal static SafeStringMarshal MarshalString (string str)
+               {
+                       return new SafeStringMarshal (str);
+               }
+
+               static int DecodeBlobSize (IntPtr in_ptr, out IntPtr out_ptr)
+               {
+                       uint size;
+                       unsafe {
+                               byte *ptr = (byte*)in_ptr;
+       
+                               if ((*ptr & 0x80) == 0) {
+                                       size = (uint)(ptr [0] & 0x7f);
+                                       ptr++;
+                               } else if ((*ptr & 0x40) == 0){
+                                       size = (uint)(((ptr [0] & 0x3f) << 8) + ptr [1]);
+                                       ptr += 2;
+                               } else {
+                                       size = (uint)(((ptr [0] & 0x1f) << 24) +
+                                               (ptr [1] << 16) +
+                                               (ptr [2] << 8) +
+                                               ptr [3]);
+                                       ptr += 4;
+                               }
+                               out_ptr = (IntPtr)ptr;
+                       }
+
+                       return (int)size;
+               }
+
+               internal static byte[] DecodeBlobArray (IntPtr ptr)
+               {
+                       IntPtr out_ptr;
+                       int size = DecodeBlobSize (ptr, out out_ptr);
+                       byte[] res = new byte [size];
+                       Marshal.Copy (out_ptr, res, 0, size);
+                       return res;
+               }
+
+               internal static int AsciHexDigitValue (int c)
+               {
+                       if (c >= '0' && c <= '9')
+                               return c - '0';
+                       if (c >= 'a' && c <= 'f')
+                               return c - 'a' + 10;
+                       return c - 'A' + 10;
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               internal static extern void FreeAssemblyName (ref MonoAssemblyName name);
+       }
+}
index 20cd93fdaecfa0c70be0f1ae84d492588b1b41aa..ae4550632088f8f90a6bb408a699180857c097b5 100644 (file)
@@ -45,5 +45,20 @@ namespace Mono {
                }
        }
 
+       //Maps to metadata-internals.h:: MonoAssemblyName
+       internal unsafe struct MonoAssemblyName
+       {
+               const int MONO_PUBLIC_KEY_TOKEN_LENGTH = 17;
+
+               internal IntPtr name;
+               internal IntPtr culture;
+               internal IntPtr hash_value;
+               internal IntPtr public_key;
+               internal fixed byte public_key_token [MONO_PUBLIC_KEY_TOKEN_LENGTH];
+               internal uint hash_alg;
+               internal uint hash_len;
+               internal uint flags;
+               internal ushort major, minor, build, revision;
+               internal ushort arch;
+       }
 }
-       
index 6a6fcd36f5abe114d6eaa3751587690b41811a6c..0a189e1faa7e70b7a2db00d32532f5ee80005c82 100644 (file)
@@ -1114,8 +1114,7 @@ namespace System.Reflection.Emit
 
                public override AssemblyName GetName (bool copiedName)
                {
-                       AssemblyName aname = new AssemblyName ();
-                       FillName (this, aname);
+                       var aname = AssemblyName.Create (this, false);
 
                        if (sn != null) {
                                aname.SetPublicKey (sn.PublicKey);
index c90059d3a87432239118d0ab5d144e5bcac1a03e..174d5da5813c72bd9f6b960af06813128db67a7d 100644 (file)
@@ -88,7 +88,7 @@ namespace System.Reflection {
 
                // Note: changes to fields must be reflected in _MonoReflectionAssembly struct (object-internals.h)
 #pragma warning disable 649
-               private IntPtr _mono_assembly;
+               internal IntPtr _mono_assembly;
 #pragma warning restore 649
 
                private ResolveEventHolder resolve_event_holder;
@@ -425,9 +425,6 @@ namespace System.Reflection {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
 
-               [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               static extern internal void FillName (Assembly ass, AssemblyName aname);
-
                public virtual AssemblyName GetName (Boolean copiedName)
                {
                        throw new NotImplementedException ();
index 42006c3e80f99ce9594cecccc582d21a1b0fc395..7ce7241cc98c8851f6893ca193722e3c679c5f90 100644 (file)
@@ -40,6 +40,7 @@ using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
 using System.IO;
 
+using Mono;
 using Mono.Security;
 using Mono.Security.Cryptography;
 
@@ -84,17 +85,29 @@ namespace System.Reflection {
                }
 
                [MethodImpl (MethodImplOptions.InternalCall)]
-               static extern bool ParseName (AssemblyName aname, string assemblyName);
-               
+               static extern bool ParseAssemblyName (IntPtr name, out MonoAssemblyName aname, out bool is_version_definited, out bool is_token_defined);
+
                public AssemblyName (string assemblyName)
                {
                        if (assemblyName == null)
                                throw new ArgumentNullException ("assemblyName");
                        if (assemblyName.Length < 1)
                                throw new ArgumentException ("assemblyName cannot have zero length.");
-                               
-                       if (!ParseName (this, assemblyName))
-                               throw new FileLoadException ("The assembly name is invalid.");
+
+                       using (var name = RuntimeMarshal.MarshalString (assemblyName)) {
+                               MonoAssemblyName nativeName;
+                               bool isVersionDefined, isTokenDefined;
+                               //ParseName free the name if it fails.
+                               if (!ParseAssemblyName (name.Value, out nativeName, out isVersionDefined, out isTokenDefined))
+                                       throw new FileLoadException ("The assembly name is invalid.");
+                               try {
+                                       unsafe {
+                                               this.FillName (&nativeName, null, isVersionDefined, false, isTokenDefined);
+                                       }
+                               } finally {
+                                       RuntimeMarshal.FreeAssemblyName (ref nativeName);
+                               }
+                       }
                }
                
                [MonoLimitation ("Not used, as the values are too limited;  Mono supports more")]
@@ -449,5 +462,63 @@ namespace System.Reflection {
                                contentType = value;
                        }
                }
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr);
+
+               internal unsafe void FillName (MonoAssemblyName *native, string codeBase, bool addVersion, bool addPublickey, bool defaultToken)
+               {
+                       this.name = RuntimeMarshal.PtrToUtf8String (native->name);
+
+                       this.major = native->major;
+                       this.minor = native->minor;
+                       this.build = native->build;
+                       this.revision = native->revision;
+
+                       this.flags = (AssemblyNameFlags)native->flags;
+
+                       this.hashalg = (AssemblyHashAlgorithm)native->hash_alg;
+
+                       this.versioncompat = AssemblyVersionCompatibility.SameMachine;
+                       this.processor_architecture = (ProcessorArchitecture)native->arch;
+
+                       if (addVersion)
+                               this.version = new Version (this.major, this.minor, this.build, this.revision);
+
+                       this.codebase = codeBase;
+
+                       if (native->culture != IntPtr.Zero)
+                               this.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false);
+
+                       if (native->public_key != IntPtr.Zero) {
+                               this.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key);
+                               this.flags |= AssemblyNameFlags.PublicKey;
+                       } else if (addPublickey) {
+                               this.publicKey = EmptyArray<byte>.Value;
+                               this.flags |= AssemblyNameFlags.PublicKey;
+                       }
+
+                       // MonoAssemblyName keeps the public key token as an hexadecimal string
+                       if (native->public_key_token [0] != 0) {
+                               byte[] keyToken = new byte [8];
+                               for (int i = 0, j = 0; i < 8; ++i) {
+                                       keyToken [i] = (byte)(RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]) << 4);
+                                       keyToken [i] |= (byte)RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]);
+                               }
+                               this.keyToken = keyToken;
+                       } else if (defaultToken) {
+                               this.keyToken = EmptyArray<byte>.Value;
+                       }
+               }
+
+               internal static AssemblyName Create (Assembly assembly, bool fillCodebase)
+               {
+                       AssemblyName aname = new AssemblyName ();
+                       unsafe {
+                               MonoAssemblyName *native = GetNativeName (assembly._mono_assembly);
+                               aname.FillName (native, fillCodebase ? assembly.CodeBase : null, true, true, true);
+                       }
+                       return aname;
+               }
        }
 }
index c433bc93dc8866598b839801f6ccb0effbaea6b3..a62b86a63ef2a8665c2315a5f8ae03c3c85ae092 100644 (file)
@@ -41,6 +41,8 @@ using System.Security;
 using System.Security.Policy;
 using System.Security.Permissions;
 
+using Mono;
+
 namespace System.Reflection {
 
        abstract class RuntimeAssembly : Assembly
@@ -162,12 +164,8 @@ namespace System.Reflection {
                                var _ = CodeBase; // this will ensure the Demand is made
                        }
 #endif
-
-                       AssemblyName aname = new AssemblyName ();
-                       FillName (this, aname);
-                       return aname;
+                       return AssemblyName.Create (this, true);
                }
-
        }
 
        [ComVisible (true)]
index e17878fe2cfe735aa501c9016a50327c67728d03..6406b39c7dac0c0aaaf3cda71452b044c5c8527f 100644 (file)
@@ -23,8 +23,9 @@ Mono.Globalization.Unicode/SortKeyBuffer.cs
 Mono.Globalization.Unicode/Normalization.cs
 Mono.Globalization.Unicode/NormalizationTableUtil.cs
 Mono/Runtime.cs
-Mono/RuntimeStructs.cs
 Mono/RuntimeHandles.cs
+Mono/RuntimeMarshal.cs
+Mono/RuntimeStructs.cs
 Mono/SafeGPtrArrayHandle.cs
 Mono/SafeStringMarshal.cs
 Mono/DataConverter.cs
index d59d688c9aef2e19d3488905b241e225f2fdb8a1..4bad7dc5ed6d85719bd7426b3e906655c833c127 100644 (file)
@@ -1999,6 +1999,7 @@ mono_assembly_name_free (MonoAssemblyName *aname)
        g_free ((void *) aname->name);
        g_free ((void *) aname->culture);
        g_free ((void *) aname->hash_value);
+       g_free ((guint8*) aname->public_key);
 }
 
 static gboolean
index 89ca81bea1313120e6b34f2d7835a7ed93815c3d..d529af28d6c79fc479268620d7795659c05b27d8 100644 (file)
@@ -68,6 +68,9 @@ ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFr
 ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1)
 ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree)
 
+ICALL_TYPE(RTMARSHAL, "Mono.RuntimeMarshal", RTMARSHAL_1)
+ICALL(RTMARSHAL_1, "FreeAssemblyName", ves_icall_Mono_RuntimeMarshal_FreeAssemblyName)
+
 ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1)
 ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree)
 ICALL(SAFESTRMARSHAL_2, "StringToUtf8", ves_icall_Mono_SafeStringMarshal_StringToUtf8)
@@ -464,8 +467,7 @@ ICALL(OBJ_1, "GetType", ves_icall_System_Object_GetType)
 ICALL(OBJ_2, "InternalGetHashCode", mono_object_hash)
 ICALL(OBJ_3, "MemberwiseClone", ves_icall_System_Object_MemberwiseClone)
 
-ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1)
-ICALL(ASSEM_1, "FillName", ves_icall_System_Reflection_Assembly_FillName)
+ICALL_TYPE(ASSEM, "System.Reflection.Assembly", ASSEM_1a)
 ICALL(ASSEM_1a, "GetAotId", ves_icall_System_Reflection_Assembly_GetAotId)
 ICALL(ASSEM_2, "GetCallingAssembly", ves_icall_System_Reflection_Assembly_GetCallingAssembly)
 ICALL(ASSEM_3, "GetEntryAssembly", ves_icall_System_Reflection_Assembly_GetEntryAssembly)
@@ -494,8 +496,9 @@ ICALL(ASSEM_24, "get_global_assembly_cache", ves_icall_System_Reflection_Assembl
 ICALL(ASSEM_25, "get_location", ves_icall_System_Reflection_Assembly_get_location)
 ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_load_with_partial_name)
 
-ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_1)
-ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName)
+ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0)
+ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName)
+ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName)
 ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token)
 
 ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1)
index 165cdd39d8fb39480187deee89e1c49e3ea89892..2e3240354898d39ce5f3facc3d931fe501e45420 100644 (file)
@@ -5487,29 +5487,10 @@ ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assem
        return res;
 }
 
-ICALL_EXPORT void
-ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
+ICALL_EXPORT MonoAssemblyName *
+ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
 {
-       MonoError error;
-       gchar *absolute, *dirname;
-       MonoAssembly *mass = assembly->assembly;
-
-       /* XXX this is duplicated code to compute the codebase URI, unify it */
-       if (g_path_is_absolute (mass->image->name)) {
-               absolute = g_strdup (mass->image->name);
-               dirname = g_path_get_dirname (absolute);
-       } else {
-               absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
-               dirname = g_strdup (mass->basedir);
-       }
-
-       replace_shadow_path (mono_object_domain (assembly), dirname, &absolute);
-       g_free (dirname);
-
-       fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
-       mono_error_set_pending_exception (&error);
-
-       g_free (absolute);
+       return &mass->aname;
 }
 
 ICALL_EXPORT void
@@ -5775,35 +5756,18 @@ ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly,
        return res;
 }
 
-ICALL_EXPORT gboolean
-ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
+ICALL_EXPORT void
+ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
 {
-       MonoError error;
-       MonoAssemblyName aname;
-       MonoDomain *domain = mono_object_domain (name);
-       char *val;
-       gboolean is_version_defined;
-       gboolean is_token_defined;
-
-       aname.public_key = NULL;
-       val = mono_string_to_utf8_checked (assname, &error);
-       if (mono_error_set_pending_exception (&error))
-               return FALSE;
-
-       if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
-               g_free ((guint8*) aname.public_key);
-               g_free (val);
-               return FALSE;
-       }
-       
-       fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
-       mono_error_set_pending_exception (&error);
+       mono_assembly_name_free (aname);
+}
 
-       mono_assembly_name_free (&aname);
-       g_free ((guint8*) aname.public_key);
-       g_free (val);
+ICALL_EXPORT gboolean
+ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
+{
+       *is_version_definited = *is_token_defined = FALSE;
 
-       return TRUE;
+       return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
 }
 
 ICALL_EXPORT MonoReflectionType*