From 2f042a1212137e558fca716dbb92197f7a770e55 Mon Sep 17 00:00:00 2001 From: Koundinya Veluri Date: Thu, 3 Sep 2015 22:06:56 -0700 Subject: [PATCH] Add AssemblyExtensions.TryGetRawMetadata to the System.Reflection.Metadata namespace. This patch contains has the necessary changes in coreclr and mscorlib. Tests will be added separately, once the new API is published and can be consumed. Part of dotnet/corefx#2768 --- src/mscorlib/model.xml | 3 ++ src/mscorlib/mscorlib.shared.sources.props | 4 +++ .../Reflection/Metadata/AssemblyExtensions.cs | 37 ++++++++++++++++++++++ src/vm/assemblynative.cpp | 26 +++++++++++++++ src/vm/assemblynative.hpp | 2 ++ src/vm/ecalllist.h | 10 ++++++ 6 files changed, 82 insertions(+) create mode 100644 src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml index 4d169f8..8136c81 100644 --- a/src/mscorlib/model.xml +++ b/src/mscorlib/model.xml @@ -1021,6 +1021,9 @@ + + + diff --git a/src/mscorlib/mscorlib.shared.sources.props b/src/mscorlib/mscorlib.shared.sources.props index a4b0511..5dc14a4 100644 --- a/src/mscorlib/mscorlib.shared.sources.props +++ b/src/mscorlib/mscorlib.shared.sources.props @@ -677,6 +677,9 @@ + + + @@ -1307,6 +1310,7 @@ true true true + true true true true diff --git a/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs b/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs new file mode 100644 index 0000000..64c0e5c --- /dev/null +++ b/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +namespace System.Reflection.Metadata +{ + public static class AssemblyExtensions + { + [DllImport(JitHelpers.QCall)] + [SuppressUnmanagedCodeSecurity] + [return: MarshalAs(UnmanagedType.Bool)] + private unsafe static extern bool InternalTryGetRawMetadata(RuntimeAssembly assembly, ref byte* blob, ref int length); + + // Retrieves the metadata section of the assembly, for use with System.Reflection.Metadata.MetadataReader. + // - Returns false upon failure. Metadata might not be available for some assemblies, such as AssemblyBuilder, .NET + // native images, etc. + // - Callers should not write to the metadata blob + // - The metadata blob pointer will remain valid as long as the AssemblyLoadContext with which the assembly is + // associated, is alive. The caller is responsible for keeping the assembly object alive while accessing the + // metadata blob. + [CLSCompliant(false)] // out byte* blob + public unsafe static bool TryGetRawMetadata(this Assembly assembly, out byte* blob, out int length) + { + if (assembly == null) + { + throw new ArgumentNullException("assembly"); + } + + blob = null; + length = 0; + return InternalTryGetRawMetadata((RuntimeAssembly)assembly, ref blob, ref length); + } + } +} diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp index 40df006..5b4e0c5 100644 --- a/src/vm/assemblynative.cpp +++ b/src/vm/assemblynative.cpp @@ -2614,3 +2614,29 @@ INT_PTR QCALLTYPE AssemblyNative::GetLoadContextForAssembly(QCall::AssemblyHandl return ptrManagedAssemblyLoadContext; } #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER) + +// static +BOOL QCALLTYPE AssemblyNative::InternalTryGetRawMetadata( + QCall::AssemblyHandle assembly, + UINT8 **blobRef, + INT32 *lengthRef) +{ + QCALL_CONTRACT; + + PTR_CVOID metadata = nullptr; + + BEGIN_QCALL; + + _ASSERTE(assembly != nullptr); + _ASSERTE(blobRef != nullptr); + _ASSERTE(lengthRef != nullptr); + + static_assert_no_msg(sizeof(*lengthRef) == sizeof(COUNT_T)); + metadata = assembly->GetFile()->GetLoadedMetadata(reinterpret_cast(lengthRef)); + *blobRef = reinterpret_cast(const_cast(metadata)); + _ASSERTE(*lengthRef >= 0); + + END_QCALL; + + return metadata != nullptr; +} diff --git a/src/vm/assemblynative.hpp b/src/vm/assemblynative.hpp index 9163710..f4ca12e 100644 --- a/src/vm/assemblynative.hpp +++ b/src/vm/assemblynative.hpp @@ -282,6 +282,8 @@ public: static void QCALLTYPE LoadFromStream(INT_PTR ptrNativeAssemblyLoadContext, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly); static Assembly* LoadFromPEImage(CLRPrivBinderAssemblyLoadContext* pBinderContext, PEImage *pILImage, PEImage *pNIImage); static INT_PTR QCALLTYPE GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly); + + static BOOL QCALLTYPE InternalTryGetRawMetadata(QCall::AssemblyHandle assembly, UINT8 **blobRef, INT32 *lengthRef); }; #endif diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index c35168f..b6bd8ee 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -1156,6 +1156,12 @@ FCFuncStart(gAssemblyFuncs) FCFuncEnd() +#ifdef FEATURE_CORECLR +FCFuncStart(gAssemblyExtensionsFuncs) + QCFuncElement("InternalTryGetRawMetadata", AssemblyNative::InternalTryGetRawMetadata) +FCFuncEnd() +#endif + #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER) FCFuncStart(gAssemblyLoadContextFuncs) QCFuncElement("InitializeAssemblyLoadContext", AssemblyNative::InitializeAssemblyLoadContext) @@ -2148,6 +2154,10 @@ FCClassElement("AssemblyBuilder", "System.Reflection.Emit", gAssemblyBuilderFunc FCClassElement("AssemblyEvidenceFactory", "System.Security.Policy", gAssemblyEvidenceFactoryFuncs) #endif // FEATURE_CAS_POLICY +#ifdef FEATURE_CORECLR +FCClassElement("AssemblyExtensions", "System.Reflection.Metadata", gAssemblyExtensionsFuncs) +#endif + #if defined(FEATURE_HOST_ASSEMBLY_RESOLVER) FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadContextFuncs) #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER) -- 2.7.4