From 68d5e54dc4f4a14e70fa20be2d2616378369be5c Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 21 Jan 2025 00:03:08 +0200 Subject: [PATCH 1/3] [mono] Implement `AssemblyExtensions.TryGetRawMetadata`. --- .../tests/AssemblyExtensionsTest.cs | 2 +- .../Reflection/Metadata/AssemblyExtensions.cs | 5 +++++ .../src/System/Reflection/RuntimeAssembly.cs | 9 +++++++++ src/mono/mono/metadata/icall-def.h | 1 + src/mono/mono/metadata/icall.c | 16 ++++++++++++++++ src/mono/mono/metadata/image.c | 1 + src/mono/mono/metadata/metadata-internals.h | 1 + 7 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.Loader/tests/AssemblyExtensionsTest.cs b/src/libraries/System.Runtime.Loader/tests/AssemblyExtensionsTest.cs index 71a4cb434583d1..265efaaa3a50ac 100644 --- a/src/libraries/System.Runtime.Loader/tests/AssemblyExtensionsTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/AssemblyExtensionsTest.cs @@ -12,7 +12,7 @@ public unsafe class AssemblyExtensionsTest [Fact] public void TryGetRawMetadata() { - bool supportsRawMetadata = PlatformDetection.IsNotMonoRuntime && PlatformDetection.IsNotNativeAot; + bool supportsRawMetadata = PlatformDetection.IsNotNativeAot; Assembly assembly = typeof(AssemblyExtensionsTest).Assembly; bool hasMetadata = assembly.TryGetRawMetadata(out byte* blob, out int length); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs index 7eafc1a560964e..fd99ec4b23315a 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs @@ -12,6 +12,11 @@ public static unsafe bool TryGetRawMetadata(this Assembly assembly, out byte* bl { ArgumentNullException.ThrowIfNull(assembly); + if (assembly is RuntimeAssembly runtimeAssembly) + { + return runtimeAssembly.TryGetRawMetadata(out blob, out length); + } + blob = null; length = 0; return false; diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index 6537bf07a0320f..0e2b66efc1a85c 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -474,6 +474,12 @@ internal static RuntimeAssembly InternalLoad(AssemblyName assemblyRef, ref Stack return res; } + internal unsafe bool TryGetRawMetadata(out byte* blob, out int length) + { + var this_assembly = this; + return InternalTryGetRawMetadata(new QCallAssembly(ref this_assembly), out blob, out length); + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern bool GetManifestResourceInfoInternal(QCallAssembly assembly, string name, ManifestResourceInfo info); @@ -489,6 +495,9 @@ internal static RuntimeAssembly InternalLoad(AssemblyName assemblyRef, ref Stack [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern IntPtr InternalGetReferencedAssemblies(Assembly assembly); + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern unsafe bool InternalTryGetRawMetadata(QCallAssembly assembly, out byte* blob, out int length); + internal string? GetSimpleName() { // TODO: Make this cheaper and faster diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index f5a02ac951a810..41a0481a7f047e 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -364,6 +364,7 @@ HANDLES(RASSEM_5, "GetManifestResourceNames", ves_icall_System_Reflection_Runtim HANDLES(RASSEM_6, "GetModulesInternal", ves_icall_System_Reflection_RuntimeAssembly_GetModulesInternal, void, 2, (MonoQCallAssemblyHandle, MonoObjectHandleOnStack)) HANDLES(RASSEM_6b, "GetTopLevelForwardedTypes", ves_icall_System_Reflection_RuntimeAssembly_GetTopLevelForwardedTypes, void, 2, (MonoQCallAssemblyHandle, MonoObjectHandleOnStack)) HANDLES(RASSEM_7, "InternalGetReferencedAssemblies", ves_icall_System_Reflection_Assembly_InternalGetReferencedAssemblies, GPtrArray_ptr, 1, (MonoReflectionAssembly)) +HANDLES(RASSEM_8, "InternalTryGetRawMetadata", ves_icall_System_Reflection_RuntimeAssembly_InternalTryGetRawMetadata, MonoBoolean, 3, (MonoQCallAssemblyHandle, gpointer_ref, gint32_ref)) ICALL_TYPE(MCMETH, "System.Reflection.RuntimeConstructorInfo", MCMETH_1) HANDLES(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_RuntimeMethodInfo_GetGenericMethodDefinition, MonoReflectionMethod, 1, (MonoReflectionMethod)) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 139a2d02dd2012..5ad9bb55345ee5 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -4743,6 +4743,22 @@ ves_icall_System_Reflection_Assembly_InternalGetReferencedAssemblies (MonoReflec return result; } +MonoBoolean +ves_icall_System_Reflection_RuntimeAssembly_InternalTryGetRawMetadata (MonoQCallAssemblyHandle assembly_h, gpointer_ref blob, gint32_ref length, MonoError *error) +{ + MonoAssembly *assembly = assembly_h.assembly; + MonoImage *image = assembly->image; + + if (image_is_dynamic (image)) { + return FALSE; + } + + *blob = image->raw_metadata; + *((guint32*)length) = image->raw_metadata_len; + + return TRUE; +} + /* move this in some file in mono/util/ */ static char * g_concat_dir_and_file (const char *dir, const char *file) diff --git a/src/mono/mono/metadata/image.c b/src/mono/mono/metadata/image.c index 37dec87fe5e820..7c14b5a97dba4e 100644 --- a/src/mono/mono/metadata/image.c +++ b/src/mono/mono/metadata/image.c @@ -468,6 +468,7 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo) if (offset + size > image->raw_data_len) return FALSE; image->raw_metadata = image->raw_data + offset; + image->raw_metadata_len = size; /* 24.2.1: Metadata root starts here */ ptr = image->raw_metadata; diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 3f0345f881185c..b876fdff200d10 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -361,6 +361,7 @@ struct _MonoImage { MonoMemPool *mempool; /*protected by the image lock*/ char *raw_metadata; + guint32 raw_metadata_len; MonoStreamHeader heap_strings; MonoStreamHeader heap_us; From e679833d7b13af1069d8f6ed6941e27e194da0cb Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Tue, 21 Jan 2025 05:19:38 +0200 Subject: [PATCH 2/3] Do not support getting raw metadata of hot-reloaded assemblies. And return if the metadata blob pointer is not null, matching CoreCLR implementation. --- src/mono/mono/metadata/icall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 5ad9bb55345ee5..a2d8706c1abc5b 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -4749,14 +4749,14 @@ ves_icall_System_Reflection_RuntimeAssembly_InternalTryGetRawMetadata (MonoQCall MonoAssembly *assembly = assembly_h.assembly; MonoImage *image = assembly->image; - if (image_is_dynamic (image)) { + if (image_is_dynamic (image) || image->has_updates) { return FALSE; } *blob = image->raw_metadata; *((guint32*)length) = image->raw_metadata_len; - return TRUE; + return *blob != NULL; } /* move this in some file in mono/util/ */ From 1f90cdc1fde8070595309eec97b4761eb8f6909a Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Wed, 22 Jan 2025 01:33:10 +0200 Subject: [PATCH 3/3] Remove unnecessary checks. --- src/mono/mono/metadata/icall.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index a2d8706c1abc5b..6df756472e04e0 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -4749,10 +4749,6 @@ ves_icall_System_Reflection_RuntimeAssembly_InternalTryGetRawMetadata (MonoQCall MonoAssembly *assembly = assembly_h.assembly; MonoImage *image = assembly->image; - if (image_is_dynamic (image) || image->has_updates) { - return FALSE; - } - *blob = image->raw_metadata; *((guint32*)length) = image->raw_metadata_len;