Browse Source

[corlib] Move Assembly::GetName to be implemented in managed.

This involves a few steps.

First define MonoAssemblyName in RuntimeStructs.cs

Then add some helped to decode blob arrays and handle hex digits.

Finally, move the actual implementation from native to managed.
Rodrigo Kumpera 9 years ago
parent
commit
277aab6863

+ 56 - 0
mcs/class/corlib/Mono/RuntimeMarshal.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Mono {
+	internal static class RuntimeMarshal {
+		internal static string PtrToUtf8String (IntPtr ptr)
+		{
+			unsafe {
+				return new String ((sbyte*)ptr);
+			}
+		}
+
+		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;
+		}
+	}
+}

+ 16 - 1
mcs/class/corlib/Mono/RuntimeStructs.cs

@@ -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;
+	}
 }
-	

+ 1 - 2
mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs

@@ -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);

+ 1 - 4
mcs/class/corlib/System.Reflection/Assembly.cs

@@ -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 ();

+ 55 - 0
mcs/class/corlib/System.Reflection/AssemblyName.cs

@@ -40,6 +40,7 @@ using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
 using System.IO;
 
+using Mono;
 using Mono.Security;
 using Mono.Security.Cryptography;
 
@@ -449,5 +450,59 @@ namespace System.Reflection {
 				contentType = value;
 			}
 		}
+
+		[MethodImplAttribute (MethodImplOptions.InternalCall)]
+		static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr);
+
+		internal static AssemblyName Create (Assembly assembly, bool fillCodebase)
+		{
+			AssemblyName aname = new AssemblyName ();
+			unsafe {
+				MonoAssemblyName *native = GetNativeName (assembly._mono_assembly);
+
+				aname.name = RuntimeMarshal.PtrToUtf8String (native->name);
+
+				aname.major = native->major;
+				aname.minor = native->minor;
+				aname.build = native->build;
+				aname.revision = native->revision;
+
+				aname.flags = (AssemblyNameFlags)native->flags;
+
+				aname.hashalg = (AssemblyHashAlgorithm)native->hash_alg;
+
+				aname.versioncompat = AssemblyVersionCompatibility.SameMachine;
+				aname.processor_architecture = (ProcessorArchitecture)native->arch;
+
+				aname.version = new Version (aname.major, aname.minor, aname.build, aname.revision);
+
+				if (fillCodebase)
+					aname.codebase = assembly.CodeBase;
+
+				if (native->culture != IntPtr.Zero)
+					aname.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false);
+
+				if (native->public_key != IntPtr.Zero) {
+					aname.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key);
+					aname.flags |= AssemblyNameFlags.PublicKey;
+				} else {
+					aname.publicKey = EmptyArray<byte>.Value;
+					aname.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++]);
+					}
+					aname.keyToken = keyToken;
+				} else {
+					aname.keyToken = EmptyArray<byte>.Value;
+				}
+			}
+			return aname;
+		}
 	}
 }

+ 3 - 5
mcs/class/corlib/System.Reflection/MonoAssembly.cs

@@ -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)]

+ 2 - 1
mcs/class/corlib/corlib.dll.sources

@@ -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

+ 3 - 3
mono/metadata/icall-def.h

@@ -464,8 +464,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,7 +493,8 @@ 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_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0)
+ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName)
 ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName)
 ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token)
 

+ 3 - 22
mono/metadata/icall.c

@@ -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