From dcecbdc3a12145fe4f255644db509aabbf27cb0a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 16:11:45 +0800 Subject: [PATCH 001/136] Definition of AssemblyVersion and AssemblyIdentity --- .../System.Private.CoreLib.csproj | 4 ++- .../Runtime/Binder/AssemblyIdentity.cs | 34 +++++++++++++++++++ .../Runtime/Binder/AssemblyVersion.cs | 23 +++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 197ca5bf9f4b2e..f175aafa7ae15a 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,6 +119,8 @@ + + @@ -248,7 +250,7 @@ Common\System\Collections\Generic\ArrayBuilder.cs - + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs new file mode 100644 index 00000000000000..6278d7ba9a4dbd --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; + +namespace Internal.Runtime.Binder +{ + internal enum AssemblyIdentityFlags + { + IDENTITY_FLAG_EMPTY = 0x000, + IDENTITY_FLAG_SIMPLE_NAME = 0x001, + IDENTITY_FLAG_VERSION = 0x002, + IDENTITY_FLAG_PUBLIC_KEY_TOKEN = 0x004, + IDENTITY_FLAG_PUBLIC_KEY = 0x008, + IDENTITY_FLAG_CULTURE = 0x010, + IDENTITY_FLAG_PROCESSOR_ARCHITECTURE = 0x040, + IDENTITY_FLAG_RETARGETABLE = 0x080, + IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL = 0x100, + IDENTITY_FLAG_CONTENT_TYPE = 0x800, + IDENTITY_FLAG_FULL_NAME = IDENTITY_FLAG_SIMPLE_NAME | IDENTITY_FLAG_VERSION + } + + internal class AssemblyIdentity + { + public string SimpleName = string.Empty; + public AssemblyVersion Version = new AssemblyVersion(); + public string CultureOrLanguage = string.Empty; + public byte[] PublicKeyOrTokenBLOB = Array.Empty(); + public ProcessorArchitecture ProcessorArchitecture; + public AssemblyContentType ContentType; + public AssemblyIdentityFlags IdentityFlags; + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs new file mode 100644 index 00000000000000..2c513bedc662db --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Internal.Runtime.Binder +{ + internal record struct AssemblyVersion + { + public int Major; + public int Minor; + public int Build; + public int Revision; + + public const int Unspecified = -1; + + public AssemblyVersion() + { + Major = Unspecified; + Minor = Unspecified; + Build = Unspecified; + Revision = Unspecified; + } + } +} From c946228e7bd29a00150739f28eb0f9db66cf02f2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 17:26:15 +0800 Subject: [PATCH 002/136] Port logic body of AssemblyName.Init --- .../System.Private.CoreLib.csproj | 2 + .../Runtime/Binder/AssemblyBinderCommon.cs | 80 ++++++++ .../Runtime/Binder/AssemblyIdentity.cs | 14 +- .../Internal/Runtime/Binder/AssemblyName.cs | 185 ++++++++++++++++++ 4 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index f175aafa7ae15a..eb0625f30df056 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,7 +119,9 @@ + + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs new file mode 100644 index 00000000000000..0863b66c068580 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Internal.Runtime.Binder +{ + internal enum CorPEKind + { + peNot = 0x00000000, // not a PE file + peILonly = 0x00000001, // flag IL_ONLY is set in COR header + pe32BitRequired = 0x00000002, // flag 32BITREQUIRED is set and 32BITPREFERRED is clear in COR header + pe32Plus = 0x00000004, // PE32+ file (64 bit) + pe32Unmanaged = 0x00000008, // PE32 without COR header + pe32BitPreferred = 0x00000010 // flags 32BITREQUIRED and 32BITPREFERRED are set in COR header + } + + internal static class AssemblyBinderCommon + { + // defined in System.Reflection.PortableExecutable.Machine, but it's in System.Reflection.Metadata + // also defined in System.Reflection.ImageFileMachine + private const int IMAGE_FILE_MACHINE_I386 = 0x014c; // Intel 386. + private const int IMAGE_FILE_MACHINE_ARMNT = 0x01c4; // ARM Thumb-2 Little-Endian + private const int IMAGE_FILE_MACHINE_AMD64 = 0x8664; // AMD64 (K8) + private const int IMAGE_FILE_MACHINE_ARM64 = 0xAA64; // ARM64 Little-Endian + + public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) + { + CorPEKind CLRPeKind = (CorPEKind)pdwPAFlags[0]; + int dwImageType = pdwPAFlags[1]; + + if (CLRPeKind == CorPEKind.peNot) + { + // Not a PE. Shouldn't ever get here. + throw new BadImageFormatException(); + } + + if ((CLRPeKind & CorPEKind.peILonly) != 0 && (CLRPeKind & CorPEKind.pe32Plus) == 0 && + (CLRPeKind & CorPEKind.pe32BitRequired) == 0 && dwImageType == IMAGE_FILE_MACHINE_I386) + { + // Processor-agnostic (MSIL) + return PEKind.MSIL; + } + else if ((CLRPeKind & CorPEKind.pe32Plus) != 0) + { + // 64-bit + if ((CLRPeKind & CorPEKind.pe32BitRequired) != 0) + { + // Invalid + throw new BadImageFormatException(); + } + + // Regardless of whether ILONLY is set or not, the architecture + // is the machine type. + if (dwImageType == IMAGE_FILE_MACHINE_ARM64) + return PEKind.ARM64; + else if (dwImageType == IMAGE_FILE_MACHINE_AMD64) + return PEKind.AMD64; + else + { + // We don't support other architectures + throw new BadImageFormatException(); + } + } + else + { + // 32-bit, non-agnostic + if (dwImageType == IMAGE_FILE_MACHINE_I386) + return PEKind.I386; + else if (dwImageType == IMAGE_FILE_MACHINE_ARMNT) + return PEKind.ARM; + else + { + // Not supported + throw new BadImageFormatException(); + } + } + } + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs index 6278d7ba9a4dbd..751a1372e98569 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs @@ -21,13 +21,25 @@ internal enum AssemblyIdentityFlags IDENTITY_FLAG_FULL_NAME = IDENTITY_FLAG_SIMPLE_NAME | IDENTITY_FLAG_VERSION } + internal enum PEKind : uint + { + None = 0x00000000, + MSIL = 0x00000001, + I386 = 0x00000002, + IA64 = 0x00000003, + AMD64 = 0x00000004, + ARM = 0x00000005, + ARM64 = 0x00000006, + Invalid = 0xffffffff, + } + internal class AssemblyIdentity { public string SimpleName = string.Empty; public AssemblyVersion Version = new AssemblyVersion(); public string CultureOrLanguage = string.Empty; public byte[] PublicKeyOrTokenBLOB = Array.Empty(); - public ProcessorArchitecture ProcessorArchitecture; + public PEKind ProcessorArchitecture; public AssemblyContentType ContentType; public AssemblyIdentityFlags IdentityFlags; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs new file mode 100644 index 00000000000000..a1e9e59e046094 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -0,0 +1,185 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Internal.Runtime.Binder +{ + internal unsafe struct AssemblyMetaDataInternal + { + public ushort usMajorVersion; // Major Version. + public ushort usMinorVersion; // Minor Version. + public ushort usBuildNumber; // Build Number. + public ushort usRevisionNumber; // Revision Number. + public byte* szLocale; // Locale. + } + + internal enum CorAssemblyFlags + { + afPublicKey = 0x0001, // The assembly ref holds the full (unhashed) public key. + + afPA_None = 0x0000, // Processor Architecture unspecified + afPA_MSIL = 0x0010, // Processor Architecture: neutral (PE32) + afPA_x86 = 0x0020, // Processor Architecture: x86 (PE32) + afPA_IA64 = 0x0030, // Processor Architecture: Itanium (PE32+) + afPA_AMD64 = 0x0040, // Processor Architecture: AMD X64 (PE32+) + afPA_ARM = 0x0050, // Processor Architecture: ARM (PE32) + afPA_ARM64 = 0x0060, // Processor Architecture: ARM64 (PE32+) + afPA_NoPlatform = 0x0070, // applies to any platform but cannot run on any (e.g. reference assembly), should not have "specified" set + afPA_Specified = 0x0080, // Propagate PA flags to AssemblyRef record + afPA_Mask = 0x0070, // Bits describing the processor architecture + afPA_FullMask = 0x00F0, // Bits describing the PA incl. Specified + afPA_Shift = 0x0004, // NOT A FLAG, shift count in PA flags <--> index conversion + + afEnableJITcompileTracking = 0x8000, // From "DebuggableAttribute". + afDisableJITcompileOptimizer = 0x4000, // From "DebuggableAttribute". + afDebuggableAttributeMask = 0xc000, + + afRetargetable = 0x0100, // The assembly can be retargeted (at runtime) to an + // assembly from a different publisher. + + afContentType_Default = 0x0000, + afContentType_WindowsRuntime = 0x0200, + afContentType_Mask = 0x0E00, // Bits describing ContentType + } + + internal sealed unsafe class AssemblyName : AssemblyIdentity + { + public bool IsDefinition; + + public AssemblyName() + { + IdentityFlags |= + AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE | AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL; + } + + public void Init(IntPtr pPEImage) + { + int* dwPAFlags = stackalloc int[2]; + using IMdInternalImport pIMetaDataAssemblyImport = BinderAcquireImport(pPEImage, dwPAFlags); + + ProcessorArchitecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); + + // Get the assembly token + uint mda; + pIMetaDataAssemblyImport.GetAssemblyFromScope(&mda); + + AssemblyMetaDataInternal amd = default; + byte* pvPublicKeyToken = null; + uint dwPublicKeyToken = 0; + byte* pAssemblyName = null; + CorAssemblyFlags dwRefOrDefFlags = 0; + uint dwHashAlgId = 0; + + // Get name and metadata + pIMetaDataAssemblyImport.GetAssemblyProps( + mda, // [IN] The Assembly for which to get the properties. + &pvPublicKeyToken, // [OUT] Pointer to the PublicKeyToken blob. + &dwPublicKeyToken, // [OUT] Count of bytes in the PublicKeyToken Blob. + &dwHashAlgId, // [OUT] Hash Algorithm. + &pAssemblyName, // [OUT] Name. + &amd, // [OUT] Assembly MetaData. + &dwRefOrDefFlags // [OUT] Flags. + ); + + { + string culture = Encoding.UTF8.GetString(amd.szLocale, string.strlen(amd.szLocale)); + int index = culture.IndexOf(';'); + if (index != -1) + { + culture = culture[..index]; + } + + CultureOrLanguage = culture; + IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE; + } + + { + string assemblyName = Encoding.UTF8.GetString(pAssemblyName, string.strlen(pAssemblyName)); + + const int MAX_PATH_FNAME = 260; + if (assemblyName.Length >= MAX_PATH_FNAME) + { + throw new Exception("FUSION_E_INVALID_NAME"); + } + + SimpleName = assemblyName; + IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_SIMPLE_NAME; + } + + // See if the assembly[def] is retargetable (ie, for a generic assembly). + if ((dwRefOrDefFlags | CorAssemblyFlags.afRetargetable) != 0) + { + IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE; + } + + // Set ContentType + if ((dwRefOrDefFlags | CorAssemblyFlags.afContentType_Mask) == CorAssemblyFlags.afContentType_Default) + { + ContentType = System.Reflection.AssemblyContentType.Default; + } + else + { + // We no longer support WindowsRuntime assembly. + throw new Exception("FUSION_E_INVALID_NAME"); + } + + // Set the assembly version + { + Version = new AssemblyVersion + { + Major = amd.usMajorVersion, + Minor = amd.usMinorVersion, + Build = amd.usBuildNumber, + Revision = amd.usRevisionNumber + }; + + IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_VERSION; + } + + // Set public key and/or public key token (if we have it) + if (dwPublicKeyToken != 0 && pvPublicKeyToken != null) + { + if ((dwRefOrDefFlags & CorAssemblyFlags.afPublicKey) != 0) + { + byte* pByteToken; + uint dwTokenLen; + StrongNameTokenFromPublicKey(pvPublicKeyToken, dwPublicKeyToken, &pByteToken, &dwTokenLen); + + PublicKeyOrTokenBLOB = new ReadOnlySpan(pByteToken, (int)dwTokenLen).ToArray(); + StrongNameFreeBuffer(pByteToken); + } + else + { + PublicKeyOrTokenBLOB = new ReadOnlySpan(pvPublicKeyToken, (int)dwPublicKeyToken).ToArray(); + } + + IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN; + } + } + + // Foo internal calls + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void StrongNameTokenFromPublicKey( + byte* pbPublicKeyBlob, // [in] public key blob + uint cbPublicKeyBlob, + byte** ppbStrongNameToken, // [out] strong name token + uint* pcbStrongNameToken); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void StrongNameFreeBuffer(byte* buffer); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern IMdInternalImport BinderAcquireImport(IntPtr pPEImage, int* dwPAFlags); + } + + internal unsafe interface IMdInternalImport : IDisposable + { + public void GetAssemblyFromScope(uint* ptkAssembly); + + public void GetAssemblyProps(uint mda, byte** ppbPublicKey, uint* pcbPublicKey, uint* pulHashAlgId, byte** pszName, void* pMetadata, CorAssemblyFlags* pdwAsselblyFlags); + } +} From b4c0ba89d24a8a860bfacb928f66788c2710b537 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 17:59:33 +0800 Subject: [PATCH 003/136] Port HashCode and Equals for AssemblyName --- .../Runtime/Binder/AssemblyIdentity.cs | 9 +- .../Internal/Runtime/Binder/AssemblyName.cs | 175 +++++++++++++++++- 2 files changed, 182 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs index 751a1372e98569..10d9d5f91be879 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs @@ -39,8 +39,15 @@ internal class AssemblyIdentity public AssemblyVersion Version = new AssemblyVersion(); public string CultureOrLanguage = string.Empty; public byte[] PublicKeyOrTokenBLOB = Array.Empty(); - public PEKind ProcessorArchitecture; + public PEKind Architecture; public AssemblyContentType ContentType; public AssemblyIdentityFlags IdentityFlags; + + // See https://docs.microsoft.com/dotnet/framework/reflection-and-codedom/specifying-fully-qualified-type-names#specifying-assembly-names + public const string NeutralCulture = "neutral"; + + public string NormalizedCulture => string.IsNullOrEmpty(CultureOrLanguage) ? NeutralCulture : CultureOrLanguage; + + public bool IsRetargetable => (IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE) != 0; } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index a1e9e59e046094..1d2c0cc39521f1 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Text; @@ -45,6 +46,22 @@ internal enum CorAssemblyFlags afContentType_Mask = 0x0E00, // Bits describing ContentType } + internal enum AssemblyNameIncludeFlags + { + INCLUDE_DEFAULT = 0x00, + INCLUDE_VERSION = 0x01, + INCLUDE_ARCHITECTURE = 0x02, + INCLUDE_RETARGETABLE = 0x04, + INCLUDE_CONTENT_TYPE = 0x08, + INCLUDE_PUBLIC_KEY_TOKEN = 0x10, + EXCLUDE_CULTURE = 0x20, + INCLUDE_ALL = INCLUDE_VERSION + | INCLUDE_ARCHITECTURE + | INCLUDE_RETARGETABLE + | INCLUDE_CONTENT_TYPE + | INCLUDE_PUBLIC_KEY_TOKEN, + } + internal sealed unsafe class AssemblyName : AssemblyIdentity { public bool IsDefinition; @@ -60,7 +77,7 @@ public void Init(IntPtr pPEImage) int* dwPAFlags = stackalloc int[2]; using IMdInternalImport pIMetaDataAssemblyImport = BinderAcquireImport(pPEImage, dwPAFlags); - ProcessorArchitecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); + Architecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); // Get the assembly token uint mda; @@ -160,6 +177,11 @@ public void Init(IntPtr pPEImage) } } + // TODO: Is this simple comparison enough? + public bool IsCoreLib => SimpleName == CoreLib.Name; + + public bool IsNeutralCulture => CultureOrLanguage == NeutralCulture; + // Foo internal calls [MethodImpl(MethodImplOptions.InternalCall)] @@ -174,6 +196,157 @@ private static extern void StrongNameTokenFromPublicKey( [MethodImpl(MethodImplOptions.InternalCall)] private static extern IMdInternalImport BinderAcquireImport(IntPtr pPEImage, int* dwPAFlags); + + public int GetHashCode(AssemblyNameIncludeFlags dwIncludeFlags) + { + uint dwHash = 0; + AssemblyIdentityFlags dwUseIdentityFlags = IdentityFlags; + + // Prune unwanted name parts + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_VERSION) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_VERSION; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_ARCHITECTURE) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_PROCESSOR_ARCHITECTURE; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_RETARGETABLE) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_CONTENT_TYPE) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_CONTENT_TYPE; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY; + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.EXCLUDE_CULTURE) != 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE; + } + + static uint HashCaseInsensitive(string str) + { + // ported from SString::HashCaseInsensitive + uint hash = 5381; + + foreach (char ch in str) + { + hash = ((hash << 5) + hash) ^ char.ToUpperInvariant(ch); + } + + return hash; + } + + static uint HashBytes(ReadOnlySpan bytes) + { + // ported from coreclr/inc/utilcode.h + uint hash = 5831; + + foreach (byte b in bytes) + { + hash = ((hash << 5) + hash) ^ b; + } + + return hash; + } + + dwHash ^= HashCaseInsensitive(SimpleName); + dwHash = BitOperations.RotateLeft(dwHash, 4); + + if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0 || + (dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN) != 0) + { + dwHash ^= HashBytes(PublicKeyOrTokenBLOB); + dwHash = BitOperations.RotateLeft(dwHash, 4); + } + + if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_VERSION) != 0) + { + + dwHash ^= (uint)Version.Major; + dwHash = BitOperations.RotateLeft(dwHash, 8); + dwHash ^= (uint)Version.Minor; + dwHash = BitOperations.RotateLeft(dwHash, 8); + dwHash ^= (uint)Version.Build; + dwHash = BitOperations.RotateLeft(dwHash, 8); + dwHash ^= (uint)Version.Revision; + dwHash = BitOperations.RotateLeft(dwHash, 8); + } + + if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) + { + dwHash ^= HashCaseInsensitive(NormalizedCulture); + dwHash = BitOperations.RotateLeft(dwHash, 4); + } + + if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE) != 0) + { + dwHash ^= 1; + dwHash = BitOperations.RotateLeft(dwHash, 4); + } + + if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PROCESSOR_ARCHITECTURE) != 0) + { + dwHash ^= (uint)Architecture; + dwHash = BitOperations.RotateLeft(dwHash, 4); + } + + if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CONTENT_TYPE) != 0) + { + dwHash ^= (uint)ContentType; + dwHash = BitOperations.RotateLeft(dwHash, 4); + } + + return (int)dwHash; + } + + public bool Equals(AssemblyIdentity other, AssemblyNameIncludeFlags dwIncludeFlags) + { + bool fEquals = false; + + if (ContentType == System.Reflection.AssemblyContentType.WindowsRuntime) + { // Assembly is meaningless for WinRT, all assemblies form one joint type namespace + return ContentType == other.ContentType; + } + + if (string.Equals(SimpleName, other.SimpleName, StringComparison.InvariantCultureIgnoreCase) && + ContentType == other.ContentType) + { + fEquals = true; + + if ((dwIncludeFlags & AssemblyNameIncludeFlags.EXCLUDE_CULTURE) == 0) + { + fEquals = string.Equals(NormalizedCulture, other.NormalizedCulture, StringComparison.InvariantCultureIgnoreCase); + } + + if (fEquals && (dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN) != 0) + { + fEquals = PublicKeyOrTokenBLOB.AsSpan().SequenceEqual(other.PublicKeyOrTokenBLOB); + } + + if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_ARCHITECTURE) != 0)) + { + fEquals = Architecture == other.Architecture; + } + + if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_VERSION) != 0)) + { + fEquals = Version == other.Version; + } + + if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_RETARGETABLE) != 0)) + { + fEquals = IsRetargetable == other.IsRetargetable; + } + } + + return fEquals; + } } internal unsafe interface IMdInternalImport : IDisposable From a6bf1213434318d18cd389b89bc09abfb3ace760 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 18:49:37 +0800 Subject: [PATCH 004/136] AssemblyName.GetDisplayName --- .../System.Private.CoreLib.csproj | 1 + .../Internal/Runtime/Binder/AssemblyName.cs | 25 +++ .../Runtime/Binder/TextualIdentityParser.cs | 163 ++++++++++++++++++ .../src/System/Text/ValueStringBuilder.cs | 2 +- 4 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index eb0625f30df056..a17ffcb3e57c68 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -123,6 +123,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 1d2c0cc39521f1..00cd7c9e286d8f 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -347,6 +347,31 @@ public bool Equals(AssemblyIdentity other, AssemblyNameIncludeFlags dwIncludeFla return fEquals; } + + public string GetDisplayName(AssemblyNameIncludeFlags dwIncludeFlags) + { + AssemblyIdentityFlags dwUseIdentityFlags = IdentityFlags; + + // Prune unwanted name parts + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_VERSION) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_VERSION; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_ARCHITECTURE) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_PROCESSOR_ARCHITECTURE; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_RETARGETABLE) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE; + } + if ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_CONTENT_TYPE) == 0) + { + dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_CONTENT_TYPE; + } + + return TextualIdentityParser.ToString(this, dwUseIdentityFlags); + } } internal unsafe interface IMdInternalImport : IDisposable diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs new file mode 100644 index 00000000000000..92238f4e4000a6 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs @@ -0,0 +1,163 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Text; + +namespace Internal.Runtime.Binder +{ + internal static class TextualIdentityParser + { + public static string ToString(AssemblyIdentity pAssemblyIdentity, AssemblyIdentityFlags includeFlags) + { + if (string.IsNullOrEmpty(pAssemblyIdentity.SimpleName)) + { + return string.Empty; + } + + ValueStringBuilder textualIdentity = new ValueStringBuilder(256); + + AppendStringEscaped(ref textualIdentity, pAssemblyIdentity.SimpleName); + + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_VERSION) != 0) + { + AssemblyVersion version = pAssemblyIdentity.Version; + textualIdentity.Append(", Version="); + textualIdentity.AppendSpanFormattable(version.Major); + textualIdentity.Append('.'); + textualIdentity.AppendSpanFormattable(version.Minor); + textualIdentity.Append('.'); + textualIdentity.AppendSpanFormattable(version.Build); + textualIdentity.Append('.'); + textualIdentity.AppendSpanFormattable(version.Revision); + } + + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) + { + textualIdentity.Append(", Culture="); + AppendStringEscaped(ref textualIdentity, pAssemblyIdentity.NormalizedCulture); + } + + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0) + { + textualIdentity.Append(", PublicKey="); + AppendBinary(ref textualIdentity, pAssemblyIdentity.PublicKeyOrTokenBLOB); + } + else if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN) != 0) + { + textualIdentity.Append(", PublicKeyToken="); + AppendBinary(ref textualIdentity, pAssemblyIdentity.PublicKeyOrTokenBLOB); + } + else if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL) != 0) + { + textualIdentity.Append(", PublicKeyToken=null"); + } + + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PROCESSOR_ARCHITECTURE) != 0) + { + textualIdentity.Append(", processorArchitecture="); + textualIdentity.Append(pAssemblyIdentity.Architecture switch + { + PEKind.I386 => "x86", + PEKind.IA64 => "IA64", + PEKind.AMD64 => "AMD64", + PEKind.ARM => "ARM", + PEKind.MSIL => "MSIL", + _ => throw new UnreachableException() + }); + } + + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE) != 0) + { + textualIdentity.Append(", Retargetable=Yes"); + } + + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) + { + textualIdentity.Append($", ContentType={nameof(System.Reflection.AssemblyContentType.WindowsRuntime)}"); + } + + return textualIdentity.ToString(); + } + + private static void AppendStringEscaped(ref ValueStringBuilder vsb, string input) + { + Debug.Assert(input.Length > 0); + + bool fNeedQuotes = (input[0] is '\n' or '\r' or ' ' or '\t') + || (input[^1] is '\n' or '\r' or ' ' or '\t'); + char quoteCharacter = '\"'; + + ValueStringBuilder tmpString = new ValueStringBuilder(stackalloc char[256]); + + // Fusion textual identity compat: escape all non-quote characters even if quoted + foreach (char ch in input) + { + switch (ch) + { + case '\"': + case '\'': + if (fNeedQuotes && (quoteCharacter != ch)) + { + tmpString.Append(ch); + } + else if (!fNeedQuotes) + { + fNeedQuotes = true; + quoteCharacter = (ch == '\"') ? '\'' : '\"'; + tmpString.Append(ch); + } + else + { + tmpString.Append('\\'); + tmpString.Append(ch); + } + break; + + case '=': + case ',': + case '\\': + tmpString.Append('\\'); + tmpString.Append(ch); + break; + + case (char)9: + tmpString.Append("\\t"); + break; + + case (char)10: + tmpString.Append("\\n"); + break; + + case (char)13: + tmpString.Append("\\r"); + break; + + default: + tmpString.Append(ch); + break; + } + } + + if (fNeedQuotes) + { + vsb.Append(quoteCharacter); + vsb.Append(tmpString.AsSpan()); + vsb.Append(quoteCharacter); + } + else + { + vsb.Append(tmpString.AsSpan()); + } + + tmpString.Dispose(); + } + + private static void AppendBinary(ref ValueStringBuilder vsb, ReadOnlySpan data) + { + vsb.EnsureCapacity(vsb.Length + data.Length * 2); + HexConverter.EncodeToUtf16(data, vsb.RawChars[vsb.Length..], HexConverter.Casing.Lower); + } + } +} diff --git a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs index 966f1c8cfc5edc..a0844b04664248 100644 --- a/src/libraries/Common/src/System/Text/ValueStringBuilder.cs +++ b/src/libraries/Common/src/System/Text/ValueStringBuilder.cs @@ -251,7 +251,7 @@ public unsafe void Append(char* value, int length) _pos += length; } - public void Append(ReadOnlySpan value) + public void Append(scoped ReadOnlySpan value) { int pos = _pos; if (pos > _chars.Length - value.Length) From bf85741e293480d660928b374c35cdf0ac0d68a0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 19:05:47 +0800 Subject: [PATCH 005/136] Assembly --- .../System.Private.CoreLib.csproj | 1 + .../src/Internal/Runtime/Binder/Assembly.cs | 42 +++++++++++++++++++ .../Runtime/Binder/AssemblyBinderCommon.cs | 21 ++++++++++ .../Internal/Runtime/Binder/AssemblyName.cs | 5 +-- 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index a17ffcb3e57c68..37be013653d37c 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,6 +119,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs new file mode 100644 index 00000000000000..8abbb9dd9d1c9a --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Internal.Runtime.Binder +{ + // BINDER_SPACE::Assembly represents a result of binding to an actual assembly (PEImage) + // It is basically a tuple of 1) physical assembly and 2) binder which created/owns this binding + // We also store whether it was bound using TPA list + internal class Assembly + { + public IntPtr PEImage; + + public AssemblyName AssemblyName { get; } + + // private IntPtr _pBinder; // PTR_AssemblyBinder + + public bool IsInTPA { get; } + + // private IntPtr _domainAssembly; // DomainAssembly* + + public Assembly(nint pPEImage, bool isInTPA) + { + // Get assembly name def from meta data import and store it for later refs access + AssemblyName = new AssemblyName(pPEImage) + { + IsDefinition = true + }; + + // validate architecture + if (!AssemblyBinderCommon.IsValidArchitecture(AssemblyName.Architecture)) + { + // Assembly image can't be executed on this platform + throw new BadImageFormatException(); + } + + IsInTPA = isInTPA; + PEImage = pPEImage; + } + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 0863b66c068580..739576f34349ea 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -76,5 +76,26 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) } } } + + public static bool IsValidArchitecture(PEKind architecture) + { + if (architecture is PEKind.MSIL or PEKind.None) + return true; + + PEKind processArchitecture = +#if TARGET_X86 + PEKind.I386; +#elif TARGET_AMD64 + PEKind.AMD64; +#elif TARGET_ARM + PEKind.ARM; +#elif TARGET_ARM64 + PEKind.ARM64; +#else + PEKind.MSIL; +#endif + + return architecture == processArchitecture; + } } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 00cd7c9e286d8f..698f8ce11b4381 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -66,14 +66,11 @@ internal sealed unsafe class AssemblyName : AssemblyIdentity { public bool IsDefinition; - public AssemblyName() + public AssemblyName(IntPtr pPEImage) { IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE | AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL; - } - public void Init(IntPtr pPEImage) - { int* dwPAFlags = stackalloc int[2]; using IMdInternalImport pIMetaDataAssemblyImport = BinderAcquireImport(pPEImage, dwPAFlags); From 61143ce73d6bb329fd939f94c8de39092bc6a228 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 19:22:24 +0800 Subject: [PATCH 006/136] Some methods in AssemblyBinderCommon and BindReseult --- .../System.Private.CoreLib.csproj | 1 + .../Runtime/Binder/AssemblyBinderCommon.cs | 63 +++++++++++++++++++ .../Runtime/Binder/AssemblyVersion.cs | 8 +++ .../src/Internal/Runtime/Binder/BindResult.cs | 43 +++++++++++++ 4 files changed, 115 insertions(+) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 37be013653d37c..1b4c9b3c549460 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -124,6 +124,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 739576f34349ea..1fad81410772fe 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -17,6 +17,69 @@ internal enum CorPEKind internal static class AssemblyBinderCommon { + public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) + { + AssemblyVersion pRequestedVersion = requestedName.Version; + AssemblyVersion pFoundVersion = foundName.Version; + + if (!pRequestedVersion.HasMajor) + { + // An unspecified requested version component matches any value for the same component in the found version, + // regardless of lesser-order version components + return true; + } + if (!pFoundVersion.HasMajor || pRequestedVersion.Major > pFoundVersion.Major) + { + // - A specific requested version component does not match an unspecified value for the same component in + // the found version, regardless of lesser-order version components + // - Or, the requested version is greater than the found version + return false; + } + if (pRequestedVersion.Major < pFoundVersion.Major) + { + // The requested version is less than the found version + return true; + } + + if (!pRequestedVersion.HasMinor) + { + return true; + } + if (!pFoundVersion.HasMinor || pRequestedVersion.Minor > pFoundVersion.Minor) + { + return false; + } + if (pRequestedVersion.Minor < pFoundVersion.Minor) + { + return true; + } + + if (!pRequestedVersion.HasBuild) + { + return true; + } + if (!pFoundVersion.HasBuild || pRequestedVersion.Build > pFoundVersion.Build) + { + return false; + } + if (pRequestedVersion.Build < pFoundVersion.Build) + { + return true; + } + + if (!pRequestedVersion.HasRevision) + { + return true; + } + if (!pFoundVersion.HasRevision || pRequestedVersion.Revision > pFoundVersion.Revision) + { + return false; + } + return true; + } + + public static void CreateImageAssembly(IntPtr pPEImage, ref BindResult bindResult) => bindResult.SetResult(new Assembly(pPEImage, isInTPA: false)); + // defined in System.Reflection.PortableExecutable.Machine, but it's in System.Reflection.Metadata // also defined in System.Reflection.ImageFileMachine private const int IMAGE_FILE_MACHINE_I386 = 0x014c; // Intel 386. diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs index 2c513bedc662db..d860e3930d14db 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs @@ -19,5 +19,13 @@ public AssemblyVersion() Build = Unspecified; Revision = Unspecified; } + + public bool HasMajor => Major != Unspecified; + + public bool HasMinor => Minor != Unspecified; + + public bool HasBuild => Build != Unspecified; + + public bool HasRevision => Revision != Unspecified; } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs new file mode 100644 index 00000000000000..8c955473a4cfd3 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Internal.Runtime.Binder +{ + internal struct BindResult + { + public struct AttemptResult + { + public Assembly? Assembly; + public Exception? Exception; + public bool Attempted; + } + + public bool IsInContextBound { get; private set; } + public Assembly? Assembly { get; private set; } + + private AttemptResult _inContextAttempt; + private AttemptResult _applicationAssembliesResult; + + public void SetAttemptResult(Assembly? assembly, Exception? exception, bool isInContext = false) + { + ref AttemptResult result = ref (isInContext ? ref _inContextAttempt : ref _applicationAssembliesResult); + result.Assembly = assembly; + result.Exception = exception; + result.Attempted = true; + } + + public AttemptResult? GetAttemptResult(bool isInContext = false) + { + AttemptResult result = isInContext ? _inContextAttempt : _applicationAssembliesResult; + return result.Attempted ? result : null; + } + + public void SetResult(Assembly assembly, bool isInContext = false) + { + Assembly = assembly; + IsInContextBound = isInContext; + } + } +} From 5fdf8a75d6deaec6e14d9d5286019ebb37e69ba0 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 21:19:12 +0800 Subject: [PATCH 007/136] ApplicationContext --- .../System.Private.CoreLib.csproj | 1 + .../Runtime/Binder/ApplicationContext.cs | 296 ++++++++++++++++++ 2 files changed, 297 insertions(+) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 1b4c9b3c549460..45f13d9832ab99 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,6 +119,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs new file mode 100644 index 00000000000000..57b7faf697577b --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -0,0 +1,296 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Threading; + +namespace Internal.Runtime.Binder +{ + internal struct TPAEntry + { + public string? ILFileName; + public string? NIFileName; + } + + internal class ApplicationContext + { + private volatile int _version; + private readonly Dictionary _executionContext = new Dictionary(); + private readonly Dictionary _failureCache = new(); + private readonly object _contextCriticalSection = new object(); + private readonly List _platformResourceRoots = new List(); + private readonly List _appPaths = new List(); + private Dictionary? _trustedPlatformAssemblyMap; + + private void IncrementVersion() => Interlocked.Increment(ref _version); + + private const char PATH_SEPARATOR_CHAR = ';'; + + private static bool GetNextPath(string paths, ref int startPos, out string outPath) + { + bool wrappedWithQuotes = false; + + // Skip any leading spaces or path separators + while (startPos < paths.Length && paths[startPos] is ' ' or PATH_SEPARATOR_CHAR) + startPos++; + + if (startPos == paths.Length) + { + // No more paths in the string and we just skipped over some white space + outPath = string.Empty; + return false; + } + + // Support paths being wrapped with quotations + while (startPos < paths.Length && paths[startPos] == '\"') + { + startPos++; + wrappedWithQuotes = true; + } + + int iEnd = startPos; // Where current path ends + int iNext; // Where next path starts + + if (wrappedWithQuotes) + { + iEnd = paths.AsSpan(iEnd).IndexOf('\"'); + if (iEnd != -1) + { + // Find where the next path starts - there should be a path separator right after the closing quotation mark + iNext = paths.AsSpan(iEnd).IndexOf(PATH_SEPARATOR_CHAR); + if (iNext != -1) + { + iNext++; + } + else + { + iNext = paths.Length; + } + } + else + { + // There was no terminating quotation mark - that's bad + throw new ArgumentException(nameof(paths)); + } + } + else if ((iEnd = paths.AsSpan(iEnd).IndexOf(PATH_SEPARATOR_CHAR)) != -1) + { + iNext = iEnd + 1; + } + else + { + iNext = iEnd = paths.Length; + } + + // Skip any trailing spaces + while (paths[iEnd - 1] == ' ') + { + iEnd--; + } + + Debug.Assert(startPos < iEnd); + + outPath = paths[startPos..iEnd]; + startPos = iNext; + return true; + } + + private static bool IsRelativePath(ReadOnlySpan path) + { + // ported from coreclr/inc/clr/fs/path.h + +#if TARGET_WINDOWS + // Check for a paths like "C:\..." or "\\...". Additional notes: + // - "\\?\..." - long format paths are considered as absolute paths due to the "\\" prefix + // - "\..." - these paths are relative, as they depend on the current drive + // - "C:..." and not "C:\..." - these paths are relative, as they depend on the current directory for drive C + if (path is [(>= 'A' and <= 'Z') or (>= 'a' and <= 'z'), PathInternal.VolumeSeparatorChar, PathInternal.DirectorySeparatorChar, ..]) + { + return false; + } + if (path is [PathInternal.DirectorySeparatorChar, PathInternal.DirectorySeparatorChar, ..]) + { + return false; + } +#else + if (path is [PathInternal.DirectorySeparatorChar, ..]) + { + return false; + } +#endif + return true; + } + + private static bool GetNextTPAPath(string paths, ref int startPos, bool dllOnly, out string outPath, out string simpleName, out bool isNativeImage) + { + isNativeImage = false; + + while (true) + { + if (!GetNextPath(paths, ref startPos, out outPath)) + { + simpleName = string.Empty; + return false; + } + + if (IsRelativePath(outPath)) + { + throw new ArgumentException(nameof(paths)); + } + + // Find the beginning of the simple name + int iSimpleNameStart = outPath.LastIndexOf(PathInternal.DirectorySeparatorChar); + if (iSimpleNameStart == -1) + { + iSimpleNameStart = 0; + } + else + { + // Advance past the directory separator to the first character of the file name + iSimpleNameStart++; + } + + if (iSimpleNameStart == outPath.Length) + { + throw new ArgumentException(nameof(paths)); + } + + if (dllOnly && (outPath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase) + || outPath.EndsWith(".ni.exe", StringComparison.OrdinalIgnoreCase))) + { + // Skip exe files when the caller requested only dlls + continue; + } + + if (outPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase) + || outPath.EndsWith(".ni.exe", StringComparison.OrdinalIgnoreCase)) + { + simpleName = outPath[iSimpleNameStart..^7]; + isNativeImage = true; + } + else if (outPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) + || outPath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) + { + simpleName = outPath[iSimpleNameStart..^4]; + } + else + { + // Invalid filename + throw new ArgumentException(nameof(paths)); + } + + return true; ; + } + } + + public void SetupBindingPaths(string trustedPlatformAssemblies, string platformResourceRoots, string appPaths, bool acquireLock) + { + if (acquireLock) + { + lock (_contextCriticalSection) + { + Core(trustedPlatformAssemblies, platformResourceRoots, appPaths); + } + } + else + { + Core(trustedPlatformAssemblies, platformResourceRoots, appPaths); + } + + void Core(string trustedPlatformAssemblies, string platformResourceRoots, string appPaths) + { + if (_trustedPlatformAssemblyMap != null) + { + return; + } + + // + // Parse TrustedPlatformAssemblies + // + + _trustedPlatformAssemblyMap = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + for (int i = 0; i < trustedPlatformAssemblies.Length;) + { + if (!GetNextTPAPath(trustedPlatformAssemblies, ref i, dllOnly: false, out string fileName, out string simpleName, out bool isNativeImage)) + { + break; + } + + if (_trustedPlatformAssemblyMap.TryGetValue(simpleName, out TPAEntry existingEntry)) + { + // + // We want to store only the first entry matching a simple name we encounter. + // The exception is if we first store an IL reference and later in the string + // we encounter a native image. Since we don't touch IL in the presence of + // native images, we replace the IL entry with the NI. + // + if ((existingEntry.ILFileName != null && !isNativeImage) || + (existingEntry.NIFileName != null && isNativeImage)) + { + continue; + } + } + + if (isNativeImage) + { + existingEntry.NIFileName = fileName; + } + else + { + existingEntry.ILFileName = fileName; + } + + _trustedPlatformAssemblyMap[simpleName] = existingEntry; + } + + // + // Parse PlatformResourceRoots + // + + for (int i = 0; i < platformResourceRoots.Length;) + { + if (!GetNextPath(platformResourceRoots, ref i, out string pathName)) + { + break; + } + + if (IsRelativePath(pathName)) + { + throw new ArgumentException(nameof(pathName)); + } + + _platformResourceRoots.Add(pathName); + } + + // + // Parse AppPaths + // + + for (int i = 0; i < appPaths.Length;) + { + if (!GetNextPath(appPaths, ref i, out string pathName)) + { + break; + } + + + if (IsRelativePath(pathName)) + { + throw new ArgumentException(nameof(pathName)); + } + + _appPaths.Add(pathName); + } + } + } + + public void AddToFailureCache(string assemblyNameOrPath, Exception bindException) + { + _failureCache.Add(assemblyNameOrPath, bindException); + IncrementVersion(); + } + } +} From 7175e30c21c9103f1ac93c73b32d97bfb5d8b5cc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 21:57:30 +0800 Subject: [PATCH 008/136] Basic assembly binder wrapper --- .../System.Private.CoreLib.csproj | 1 + .../Runtime/Binder/ApplicationContext.cs | 16 ++- .../Internal/Runtime/Binder/AssemblyBinder.cs | 10 ++ .../Runtime/Binder/AssemblyBinderCommon.cs | 123 ++++++++++++++++++ .../Internal/Runtime/Binder/AssemblyName.cs | 17 ++- 5 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 45f13d9832ab99..ef7c345c021e04 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -121,6 +121,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index 57b7faf697577b..b7af092019f661 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -18,9 +18,15 @@ internal struct TPAEntry internal class ApplicationContext { private volatile int _version; + + public int Version => _version; + private readonly Dictionary _executionContext = new Dictionary(); - private readonly Dictionary _failureCache = new(); - private readonly object _contextCriticalSection = new object(); + + public Dictionary FailureCache { get; } = new Dictionary(); + + public object ContextCriticalSection { get; } = new object(); + private readonly List _platformResourceRoots = new List(); private readonly List _appPaths = new List(); private Dictionary? _trustedPlatformAssemblyMap; @@ -190,7 +196,7 @@ public void SetupBindingPaths(string trustedPlatformAssemblies, string platformR { if (acquireLock) { - lock (_contextCriticalSection) + lock (ContextCriticalSection) { Core(trustedPlatformAssemblies, platformResourceRoots, appPaths); } @@ -287,9 +293,9 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string } } - public void AddToFailureCache(string assemblyNameOrPath, Exception bindException) + public void AddToFailureCache(string assemblyNameOrPath, int hResult) { - _failureCache.Add(assemblyNameOrPath, bindException); + FailureCache.Add(assemblyNameOrPath, hResult); IncrementVersion(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs new file mode 100644 index 00000000000000..c320cde12daa52 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Internal.Runtime.Binder +{ + internal abstract class AssemblyBinder + { + public abstract ApplicationContext AppContext { get; } + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 1fad81410772fe..807c78a2ba22ec 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -2,6 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; namespace Internal.Runtime.Binder { @@ -140,6 +144,125 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) } } + public static Assembly? BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths) + { + int kContextVersion = 0; + BindResult bindResult; + ApplicationContext applicationContext = binder.AppContext; + + // Tracing happens outside the binder lock to avoid calling into managed code within the lock + //BinderTracing::ResolutionAttemptedOperation tracer{ pAssemblyName, pBinder, 0 /*managedALC*/, hr}; + + Retry: + lock (applicationContext.ContextCriticalSection) + { + bindResult = BindByName(applicationContext, assemblyName, false, false, excludeAppPaths); + + // Remember the post-bind version + kContextVersion = applicationContext.Version; + } + + // tracer.TraceBindResult(bindResult); + + if (bindResult.Assembly != null) + { + if (RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult)) + { + Debug.Assert(hostBindResult.Assembly != null); + return hostBindResult.Assembly; + } + else + { + // Another bind interfered. We need to retry the entire bind. + // This by design loops as long as needed because by construction we eventually + // will succeed or fail the bind. + bindResult = default; + goto Retry; + } + } + + return null; + } + + // Skipped - the managed binder can't bootstrap CoreLib + // static Assembly? BindToSystem(string systemDirectory); + // static Assembly? BindToSystemSatellite(string systemDirectory, string simpleName, string cultureName); + + static BindResult BindByName(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipFailureChecking, bool skipVersionCompatibilityCheck, bool excludeAppPaths) + { + BindResult bindResult = default; + + // Look for already cached binding failure (ignore PA, every PA will lock the context) + string assemblyDisplayName = assemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION); + + try + { + applicationContext.FailureCache.TryGetValue(assemblyDisplayName, out int hr); + if (hr < 0) // FAILED(hr) + { + if (hr == HResults.E_FILENOTFOUND && skipFailureChecking) + { + // Ignore pre-existing transient bind error (re-bind will succeed) + applicationContext.FailureCache.Remove(assemblyDisplayName); + } + + return default; + } + else if (hr == HResults.S_FALSE) + { + // workaround: Special case for byte arrays. Rerun the bind to create binding log. + assemblyName.IsDefinition = true; + hr = HResults.S_OK; + } + + if (!IsValidArchitecture(assemblyName.Architecture)) + { + // Assembly reference contains wrong architecture + throw new Exception("FUSION_E_INVALID_NAME"); + } + + bindResult = BindLocked(applicationContext, assemblyName, skipVersionCompatibilityCheck, excludeAppPaths); + + if (bindResult.Assembly == null) + { + // Behavior rules are clueless now + throw new FileNotFoundException(); + } + + return bindResult; + } + catch (Exception ex) + { + if (skipFailureChecking) + { + if (ex is not FileNotFoundException) + { + // Cache non-transient bind error for byte-array + ex = Marshal.GetExceptionForHR(HResults.S_FALSE)!; + } + else + { + // Ignore transient bind error (re-bind will succeed) + return bindResult; + } + } + + applicationContext.AddToFailureCache(assemblyDisplayName, ex.HResult); + + throw ex; + } + } + + static BindResult BindLocked(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipVersionCompatibilityCheck, bool excludeAppPaths) + { + throw null; + } + + static bool RegisterAndGetHostChosen(ApplicationContext applicationContext, int kContextVersion, BindResult bindResult, out BindResult hostBindResult) + { + throw null; + } + public static bool IsValidArchitecture(PEKind architecture) { if (architecture is PEKind.MSIL or PEKind.None) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 698f8ce11b4381..49ec1b9ad7a9e6 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -62,7 +62,7 @@ internal enum AssemblyNameIncludeFlags | INCLUDE_PUBLIC_KEY_TOKEN, } - internal sealed unsafe class AssemblyName : AssemblyIdentity + internal sealed unsafe class AssemblyName : AssemblyIdentity, IEquatable { public bool IsDefinition; @@ -175,9 +175,9 @@ public AssemblyName(IntPtr pPEImage) } // TODO: Is this simple comparison enough? - public bool IsCoreLib => SimpleName == CoreLib.Name; + public bool IsCoreLib => string.EqualsOrdinalIgnoreCase(SimpleName, CoreLib.Name); - public bool IsNeutralCulture => CultureOrLanguage == NeutralCulture; + public bool IsNeutralCulture => string.EqualsOrdinalIgnoreCase(CultureOrLanguage, NeutralCulture); // Foo internal calls @@ -194,6 +194,8 @@ private static extern void StrongNameTokenFromPublicKey( [MethodImpl(MethodImplOptions.InternalCall)] private static extern IMdInternalImport BinderAcquireImport(IntPtr pPEImage, int* dwPAFlags); + public override int GetHashCode() => GetHashCode(AssemblyNameIncludeFlags.INCLUDE_ALL); + public int GetHashCode(AssemblyNameIncludeFlags dwIncludeFlags) { uint dwHash = 0; @@ -302,8 +304,15 @@ static uint HashBytes(ReadOnlySpan bytes) return (int)dwHash; } - public bool Equals(AssemblyIdentity other, AssemblyNameIncludeFlags dwIncludeFlags) + public override bool Equals(object? obj) => obj is AssemblyName other && Equals(other); + + public bool Equals(AssemblyName? other) => Equals(other, AssemblyNameIncludeFlags.INCLUDE_ALL); + + public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFlags) { + if (other is null) + return false; + bool fEquals = false; if (ContentType == System.Reflection.AssemblyContentType.WindowsRuntime) From 6cfdc449ef4e5286e9904a56e1307f8976fe73fe Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 22:08:13 +0800 Subject: [PATCH 009/136] Refactor FailureCache --- .../Runtime/Binder/ApplicationContext.cs | 11 ++++++-- .../Runtime/Binder/AssemblyBinderCommon.cs | 28 +++++++++---------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index b7af092019f661..8b54e9ada12a66 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -15,6 +15,11 @@ internal struct TPAEntry public string? NIFileName; } + internal record struct FailureCacheKey(string SimpleName, AssemblyVersion Version) + { + public FailureCacheKey(AssemblyName assemblyName) : this(assemblyName.SimpleName, assemblyName.Version) { } + } + internal class ApplicationContext { private volatile int _version; @@ -23,7 +28,7 @@ internal class ApplicationContext private readonly Dictionary _executionContext = new Dictionary(); - public Dictionary FailureCache { get; } = new Dictionary(); + public Dictionary FailureCache { get; } = new Dictionary(); public object ContextCriticalSection { get; } = new object(); @@ -293,9 +298,9 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string } } - public void AddToFailureCache(string assemblyNameOrPath, int hResult) + public void AddToFailureCache(AssemblyName assemblyName, Exception? failure) { - FailureCache.Add(assemblyNameOrPath, hResult); + FailureCache.Add(new FailureCacheKey(assemblyName), failure); IncrementVersion(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 807c78a2ba22ec..cb7edb4ebad188 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -188,33 +188,33 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) // static Assembly? BindToSystem(string systemDirectory); // static Assembly? BindToSystemSatellite(string systemDirectory, string simpleName, string cultureName); - static BindResult BindByName(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipFailureChecking, bool skipVersionCompatibilityCheck, bool excludeAppPaths) + private static BindResult BindByName(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipFailureChecking, bool skipVersionCompatibilityCheck, bool excludeAppPaths) { - BindResult bindResult = default; - // Look for already cached binding failure (ignore PA, every PA will lock the context) - string assemblyDisplayName = assemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION); - try + if (applicationContext.FailureCache.TryGetValue(new FailureCacheKey(assemblyName), out Exception? failure)) { - applicationContext.FailureCache.TryGetValue(assemblyDisplayName, out int hr); - if (hr < 0) // FAILED(hr) + if (failure != null) // FAILED(hr) { - if (hr == HResults.E_FILENOTFOUND && skipFailureChecking) + if (failure is FileNotFoundException && skipFailureChecking) { // Ignore pre-existing transient bind error (re-bind will succeed) - applicationContext.FailureCache.Remove(assemblyDisplayName); + applicationContext.FailureCache.Remove(new FailureCacheKey(assemblyName)); } return default; } - else if (hr == HResults.S_FALSE) + else // hr == HResults.S_FALSE { // workaround: Special case for byte arrays. Rerun the bind to create binding log. assemblyName.IsDefinition = true; - hr = HResults.S_OK; } + } + BindResult bindResult = default; + + try + { if (!IsValidArchitecture(assemblyName.Architecture)) { // Assembly reference contains wrong architecture @@ -238,7 +238,7 @@ static BindResult BindByName(ApplicationContext applicationContext, AssemblyName if (ex is not FileNotFoundException) { // Cache non-transient bind error for byte-array - ex = Marshal.GetExceptionForHR(HResults.S_FALSE)!; + ex = null!; } else { @@ -247,9 +247,9 @@ static BindResult BindByName(ApplicationContext applicationContext, AssemblyName } } - applicationContext.AddToFailureCache(assemblyDisplayName, ex.HResult); + applicationContext.AddToFailureCache(assemblyName, ex); - throw ex; + throw; } } From 52dae46bd4278a3baaaec4f05af42f9f1602b2a4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 22:24:14 +0800 Subject: [PATCH 010/136] BindLocked --- .../Runtime/Binder/ApplicationContext.cs | 11 +-- .../Runtime/Binder/AssemblyBinderCommon.cs | 81 ++++++++++++++++++- .../src/Internal/Runtime/Binder/BindResult.cs | 5 ++ 3 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index 8b54e9ada12a66..6f8f48506f611d 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -34,7 +34,8 @@ internal class ApplicationContext private readonly List _platformResourceRoots = new List(); private readonly List _appPaths = new List(); - private Dictionary? _trustedPlatformAssemblyMap; + + public Dictionary? TrustedPlatformAssemblyMap { get; private set; } private void IncrementVersion() => Interlocked.Increment(ref _version); @@ -213,7 +214,7 @@ public void SetupBindingPaths(string trustedPlatformAssemblies, string platformR void Core(string trustedPlatformAssemblies, string platformResourceRoots, string appPaths) { - if (_trustedPlatformAssemblyMap != null) + if (TrustedPlatformAssemblyMap != null) { return; } @@ -222,7 +223,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string // Parse TrustedPlatformAssemblies // - _trustedPlatformAssemblyMap = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + TrustedPlatformAssemblyMap = new Dictionary(StringComparer.InvariantCultureIgnoreCase); for (int i = 0; i < trustedPlatformAssemblies.Length;) { if (!GetNextTPAPath(trustedPlatformAssemblies, ref i, dllOnly: false, out string fileName, out string simpleName, out bool isNativeImage)) @@ -230,7 +231,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string break; } - if (_trustedPlatformAssemblyMap.TryGetValue(simpleName, out TPAEntry existingEntry)) + if (TrustedPlatformAssemblyMap.TryGetValue(simpleName, out TPAEntry existingEntry)) { // // We want to store only the first entry matching a simple name we encounter. @@ -254,7 +255,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string existingEntry.ILFileName = fileName; } - _trustedPlatformAssemblyMap[simpleName] = existingEntry; + TrustedPlatformAssemblyMap[simpleName] = existingEntry; } // diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index cb7edb4ebad188..8344631b962b98 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -221,7 +221,7 @@ private static BindResult BindByName(ApplicationContext applicationContext, Asse throw new Exception("FUSION_E_INVALID_NAME"); } - bindResult = BindLocked(applicationContext, assemblyName, skipVersionCompatibilityCheck, excludeAppPaths); + BindLocked(applicationContext, assemblyName, skipVersionCompatibilityCheck, excludeAppPaths, ref bindResult); if (bindResult.Assembly == null) { @@ -253,7 +253,84 @@ private static BindResult BindByName(ApplicationContext applicationContext, Asse } } - static BindResult BindLocked(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipVersionCompatibilityCheck, bool excludeAppPaths) + private static void BindLocked(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipVersionCompatibilityCheck, bool excludeAppPaths, ref BindResult bindResult) + { + bool isTpaListProvided = applicationContext.TrustedPlatformAssemblyMap != null; + Assembly? assembly = null; + + try + { + assembly = FindInExecutionContext(applicationContext, assemblyName); + } + catch (Exception ex) + { + bindResult.SetAttemptResult(assembly, ex, isInContext: true); + throw; + } + + if (assembly == null) // if (FAILED(hr) || pAssembly == NULL) + { + bindResult.SetAttemptResult(null, null, isInContext: true); + } + + if (assembly != null) + { + if (!skipVersionCompatibilityCheck) + { + // Can't give higher version than already bound + bool isCompatible = IsCompatibleAssemblyVersion(assemblyName, assembly.AssemblyName); + Exception? exception = isCompatible ? null : new Exception("FUSION_E_APP_DOMAIN_LOCKED"); + bindResult.SetAttemptResult(assembly, exception, isInContext: true); + + // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version + if (exception != null && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED + exception = new Exception("FUSION_E_REF_DEF_MISMATCH"); + + if (exception != null) + throw exception; + } + else + { + bindResult.SetAttemptResult(assembly, null, isInContext: true); + } + + bindResult.SetResult(assembly, isInContext: true); + } + else if (isTpaListProvided) + { + // BindByTpaList handles setting attempt results on the bind result + try + { + BindByTpaList(applicationContext, assemblyName, excludeAppPaths, ref bindResult); + + if (bindResult.Assembly != null) // SUCCEEDED(hr) && pBindResult->HaveResult() + { + bool isCompatible = IsCompatibleAssemblyVersion(assemblyName, bindResult.Assembly.AssemblyName); + Exception? exception = isCompatible ? null : new Exception("FUSION_E_APP_DOMAIN_LOCKED"); + bindResult.SetAttemptResult(bindResult.Assembly, exception, isInContext: false); + + // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version + if (exception != null && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED + exception = new Exception("FUSION_E_REF_DEF_MISMATCH"); + + if (exception != null) + throw exception; + } + } + catch + { + bindResult.SetNoResult(); + throw; + } + } + } + + static void BindByTpaList(ApplicationContext applicationContext, AssemblyName assemblyName, bool excludeAppPaths, ref BindResult bindResult) + { + throw null; + } + + static Assembly? FindInExecutionContext(ApplicationContext applicationContext, AssemblyName assembly) { throw null; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs index 8c955473a4cfd3..e7758717733e34 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs @@ -39,5 +39,10 @@ public void SetResult(Assembly assembly, bool isInContext = false) Assembly = assembly; IsInContextBound = isInContext; } + + public void SetNoResult() + { + Assembly = null; + } } } From e7789cd6e99310d381f0682b911d61d90ce7435a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 22:28:40 +0800 Subject: [PATCH 011/136] FindInExecutionContext --- .../Runtime/Binder/ApplicationContext.cs | 2 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index 6f8f48506f611d..6d03a1a1c017bf 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -26,7 +26,7 @@ internal class ApplicationContext public int Version => _version; - private readonly Dictionary _executionContext = new Dictionary(); + public Dictionary ExecutionContext { get; } = new Dictionary(); public Dictionary FailureCache { get; } = new Dictionary(); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 8344631b962b98..26efc7eab7a424 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -325,12 +325,23 @@ private static void BindLocked(ApplicationContext applicationContext, AssemblyNa } } - static void BindByTpaList(ApplicationContext applicationContext, AssemblyName assemblyName, bool excludeAppPaths, ref BindResult bindResult) + private static Assembly? FindInExecutionContext(ApplicationContext applicationContext, AssemblyName assemblyName) { - throw null; + applicationContext.ExecutionContext.TryGetValue(assemblyName, out Assembly? assembly); + + // Set any found context entry. It is up to the caller to check the returned HRESULT + // for errors due to validation + + if (assembly != null && assemblyName.IsDefinition + && (assembly.AssemblyName.Architecture != assemblyName.Architecture)) + { + throw new Exception("FUSION_E_APP_DOMAIN_LOCKED"); + } + + return assembly; } - static Assembly? FindInExecutionContext(ApplicationContext applicationContext, AssemblyName assembly) + static void BindByTpaList(ApplicationContext applicationContext, AssemblyName assemblyName, bool excludeAppPaths, ref BindResult bindResult) { throw null; } From c32ec9887245f9861fc182e8b999c3d0f9a86739 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 30 Aug 2023 23:49:17 +0800 Subject: [PATCH 012/136] BindByTpaList --- .../Runtime/Binder/ApplicationContext.cs | 5 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 171 +++++++++++++++++- 2 files changed, 173 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index 6d03a1a1c017bf..b98cee355c7859 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -33,7 +33,8 @@ internal class ApplicationContext public object ContextCriticalSection { get; } = new object(); private readonly List _platformResourceRoots = new List(); - private readonly List _appPaths = new List(); + + public List AppPaths { get; } = new List(); public Dictionary? TrustedPlatformAssemblyMap { get; private set; } @@ -294,7 +295,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string throw new ArgumentException(nameof(pathName)); } - _appPaths.Add(pathName); + AppPaths.Add(pathName); } } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 26efc7eab7a424..49b01847087ebc 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -2,10 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; namespace Internal.Runtime.Binder { @@ -341,7 +343,174 @@ private static void BindLocked(ApplicationContext applicationContext, AssemblyNa return assembly; } - static void BindByTpaList(ApplicationContext applicationContext, AssemblyName assemblyName, bool excludeAppPaths, ref BindResult bindResult) + // + // Tests whether a candidate assembly's name matches the requested. + // This does not do a version check. The binder applies version policy + // further up the stack once it gets a successful bind. + // + private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyName, AssemblyName boundAssemblyName, bool tpaListAssembly) + { + AssemblyNameIncludeFlags includeFlags = AssemblyNameIncludeFlags.INCLUDE_DEFAULT; + + if (!tpaListAssembly) + { + if (requestedAssemblyName.IsNeutralCulture) + { + includeFlags |= AssemblyNameIncludeFlags.EXCLUDE_CULTURE; + } + } + + if (requestedAssemblyName.Architecture != PEKind.None) + { + includeFlags |= AssemblyNameIncludeFlags.INCLUDE_ARCHITECTURE; + } + + return boundAssemblyName.Equals(requestedAssemblyName, includeFlags); + } + + // TODO: BindSatelliteResource + + /* + * BindByTpaList is the entry-point for the custom binding algorithm in CoreCLR. + * + * The search for assemblies will proceed in the following order: + * + * If this application is a single-file bundle, the meta-data contained in the bundle + * will be probed to find the requested assembly. If the assembly is not found, + * The list of platform assemblies (TPAs) are considered next. + * + * Platform assemblies are specified as a list of files. This list is the only set of + * assemblies that we will load as platform. They can be specified as IL or NIs. + * + * Resources for platform assemblies are located by probing starting at the Platform Resource Roots, + * a set of folders configured by the host. + * + * If a requested assembly identity cannot be found in the TPA list or the resource roots, + * it is considered an application assembly. We probe for application assemblies in the + * AppPaths, a list of paths containing IL files and satellite resource folders. + * + */ + + public static void BindByTpaList(ApplicationContext applicationContext, AssemblyName requestedAssemblyName, bool excludeAppPaths, ref BindResult bindResult) + { + bool fPartialMatchOnTpa = false; + + if (requestedAssemblyName.IsNeutralCulture) + { + // IF_FAIL_GO(BindSatelliteResource(pApplicationContext, pRequestedAssemblyName, pBindResult)); + } + else + { + Assembly? tpaAssembly = null; + + // Is assembly in the bundle? + // Single-file bundle contents take precedence over TPA. + // The list of bundled assemblies is contained in the bundle manifest, and NOT in the TPA. + // Therefore the bundle is first probed using the assembly's simple name. + // If found, the assembly is loaded from the bundle. + + // if (Bundle::AppIsBundle()) + + // Is assembly on TPA list? + Debug.Assert(applicationContext.TrustedPlatformAssemblyMap != null); + if (applicationContext.TrustedPlatformAssemblyMap.TryGetValue(requestedAssemblyName.SimpleName, out TPAEntry tpaEntry)) + { + string? tpaFileName = tpaEntry.NIFileName ?? tpaEntry.ILFileName; + Debug.Assert(tpaFileName != null); + + try + { + tpaAssembly = GetAssembly(tpaFileName, isInTPA: true); + // BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); + + bindResult.SetAttemptResult(tpaAssembly, null); + + if (TestCandidateRefMatchesDef(requestedAssemblyName, tpaAssembly.AssemblyName, true)) + { + // We have found the requested assembly match on TPA with validation of the full-qualified name. Bind to it. + bindResult.SetResult(tpaAssembly); + bindResult.SetAttemptResult(tpaAssembly, null); + return; + } + else + { + // We found the assembly on TPA but it didn't match the RequestedAssembly assembly-name. In this case, lets proceed to see if we find the requested + // assembly in the App paths. + bindResult.SetAttemptResult(tpaAssembly, new Exception("FUSION_E_REF_DEF_MISMATCH")); + fPartialMatchOnTpa = true; + } + } + catch (Exception ex) + { + bindResult.SetAttemptResult(null, ex); + + // On file not found, simply fall back to app path probing + if (ex is not FileNotFoundException) + { + // Any other error is fatal + throw; + } + } + + // We either didn't find a candidate, or the ref-def failed. Either way; fall back to app path probing. + } + + if (!excludeAppPaths) + { + // Probe AppPaths + + try + { + Assembly assembly = BindAssemblyByProbingPaths(applicationContext.AppPaths, requestedAssemblyName); + bindResult.SetAttemptResult(assembly, null); + + // At this point, we have found an assembly with the expected name in the App paths. If this was also found on TPA, + // make sure that the app assembly has the same fullname (excluding version) as the TPA version. If it does, then + // we should bind to the TPA assembly. If it does not, then bind to the app assembly since it has a different fullname than the + // TPA assembly. + if (fPartialMatchOnTpa) + { + Debug.Assert(tpaAssembly != null); + + if (TestCandidateRefMatchesDef(assembly.AssemblyName, tpaAssembly.AssemblyName, true)) + { + // Fullname (SimpleName+Culture+PKT) matched for TPA and app assembly - so bind to TPA instance. + bindResult.SetResult(tpaAssembly); + bindResult.SetAttemptResult(tpaAssembly, null); + return; + } + else + { + // Fullname (SimpleName+Culture+PKT) did not match for TPA and app assembly - so bind to app instance. + bindResult.SetResult(assembly); + return; + } + } + } + catch (Exception ex) + { + bindResult.SetAttemptResult(null, ex); + + if (ex is not FileNotFoundException) + { + throw; + } + } + } + } + + // Couldn't find a matching assembly in any of the probing paths + // Return S_FALSE here. BindByName will interpret a successful HRESULT + // and lack of BindResult as a failure to find a matching assembly. + return; + } + + static Assembly BindAssemblyByProbingPaths(List appPaths, AssemblyName requestedAssemblyName) + { + throw null; + } + + static Assembly GetAssembly(string assemblyPath, bool isInTPA) { throw null; } From 9a47f75a028e043d97b5d12a6fd8a7d90c5faec2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Aug 2023 00:06:58 +0800 Subject: [PATCH 013/136] RegisterAndGetHostChosen --- .../Runtime/Binder/ApplicationContext.cs | 2 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 90 ++++++++++++++++++- .../src/Internal/Runtime/Binder/BindResult.cs | 4 +- 3 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index b98cee355c7859..8d4d1039efb396 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -38,7 +38,7 @@ internal class ApplicationContext public Dictionary? TrustedPlatformAssemblyMap { get; private set; } - private void IncrementVersion() => Interlocked.Increment(ref _version); + public void IncrementVersion() => Interlocked.Increment(ref _version); private const char PATH_SEPARATOR_CHAR = ';'; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 49b01847087ebc..701b5cb9a57127 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -505,17 +505,99 @@ public static void BindByTpaList(ApplicationContext applicationContext, Assembly return; } - static Assembly BindAssemblyByProbingPaths(List appPaths, AssemblyName requestedAssemblyName) + // static Assembly GetAssembly(string assemblyPath, bool isInTPA, BundleFileLocation); + + public static void Register(ApplicationContext applicationContext, ref BindResult bindResult) { - throw null; + Debug.Assert(bindResult.IsContextBound); + Debug.Assert(bindResult.Assembly != null); + + applicationContext.IncrementVersion(); + + // Register the bindResult in the ExecutionContext only if we dont have it already. + // This method is invoked under a lock (by its caller), so we are thread safe. + Assembly? assembly = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName); + + if (assembly == null) + { + applicationContext.ExecutionContext.Add(bindResult.Assembly.AssemblyName, bindResult.Assembly); + } + else + { + // Update the BindResult with the assembly we found + bindResult.SetResult(assembly, isInContext: true); + } } - static Assembly GetAssembly(string assemblyPath, bool isInTPA) + public static bool RegisterAndGetHostChosen(ApplicationContext applicationContext, int kContextVersion, BindResult bindResult, out BindResult hostBindResult) + { + Debug.Assert(bindResult.Assembly != null); + hostBindResult = default; + + if (!bindResult.IsContextBound) + { + hostBindResult = bindResult; + + // Lock the application context + lock (applicationContext.ContextCriticalSection) + { + // Only perform costly validation if other binds succeeded before us + if (kContextVersion != applicationContext.Version) + { + if (OtherBindInterferred(applicationContext, bindResult)) // S_FALSE == return true + { + // Another bind interfered + return false; // S_FALSE == return false + } + } + + // No bind interfered, we can now register + Register(applicationContext, ref hostBindResult); + } + } + else + { + // No work required. Return the input + hostBindResult = bindResult; + } + + return true; + } + + private static bool OtherBindInterferred(ApplicationContext applicationContext, BindResult bindResult) + { + Debug.Assert(bindResult.Assembly != null); + + // Look for already cached binding failure (ignore PA, every PA will lock the context) + if (!applicationContext.FailureCache.ContainsKey(new FailureCacheKey(bindResult.Assembly.AssemblyName))) + { + // hr == S_OK + try + { + Assembly? assembly = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName); + if (assembly != null) // SUCCEEDED(hr) + { + // We can accept this bind in the domain + return false; // S_OK == return false + } + } + catch + { + // No throwing + } + + } + + // Some other bind interfered + return true; // S_FALSE == return true + } + + static Assembly BindAssemblyByProbingPaths(List appPaths, AssemblyName requestedAssemblyName) { throw null; } - static bool RegisterAndGetHostChosen(ApplicationContext applicationContext, int kContextVersion, BindResult bindResult, out BindResult hostBindResult) + static Assembly GetAssembly(string assemblyPath, bool isInTPA) { throw null; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs index e7758717733e34..dd01323a4e35d4 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs @@ -14,7 +14,7 @@ public struct AttemptResult public bool Attempted; } - public bool IsInContextBound { get; private set; } + public bool IsContextBound { get; private set; } public Assembly? Assembly { get; private set; } private AttemptResult _inContextAttempt; @@ -37,7 +37,7 @@ public void SetAttemptResult(Assembly? assembly, Exception? exception, bool isIn public void SetResult(Assembly assembly, bool isInContext = false) { Assembly = assembly; - IsInContextBound = isInContext; + IsContextBound = isInContext; } public void SetNoResult() From 21ea3e16c3ddbec30ea873bb43f22d7fbdbc004f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Aug 2023 11:22:59 +0800 Subject: [PATCH 014/136] BindAssemblyByProbingPaths --- .../Runtime/Binder/AssemblyBinderCommon.cs | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 701b5cb9a57127..f7a39b9d0e01ad 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -370,6 +370,48 @@ private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyNam // TODO: BindSatelliteResource + private static Assembly BindAssemblyByProbingPaths(List bindingPaths, AssemblyName requestedAssemblyName) + { + // Loop through the binding paths looking for a matching assembly + foreach (string bindingPath in bindingPaths) + { + string fileNameWithoutExtension = Path.Combine(bindingPath, requestedAssemblyName.SimpleName); + + // Look for a matching dll first + string fileName = fileNameWithoutExtension + ".dll"; + + try + { + Assembly assembly = GetAssembly(fileName, false); + + // BinderTracing::PathProbed(fileName, pathSource, hr); + + // We found a candidate. + // + // Below this point, we either establish that the ref-def matches, or + // we fail the bind. + + // Compare requested AssemblyName with that from the candidate assembly + if (!TestCandidateRefMatchesDef(requestedAssemblyName, assembly.AssemblyName, false)) + throw new Exception("FUSION_E_REF_DEF_MISMATCH"); + + return assembly; // S_OK + } + catch (Exception ex) + { + if (ex is FileNotFoundException) + { + // Since we're probing, file not founds are ok and we should just try another + // probing path + continue; + } + + } + } + + throw new FileNotFoundException(); + } + /* * BindByTpaList is the entry-point for the custom binding algorithm in CoreCLR. * @@ -592,11 +634,6 @@ private static bool OtherBindInterferred(ApplicationContext applicationContext, return true; // S_FALSE == return true } - static Assembly BindAssemblyByProbingPaths(List appPaths, AssemblyName requestedAssemblyName) - { - throw null; - } - static Assembly GetAssembly(string assemblyPath, bool isInTPA) { throw null; From 93b4b10b1fac9c79cded4df09aa570bea1fc98ea Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Aug 2023 21:46:46 +0800 Subject: [PATCH 015/136] Use HResult instead of exception --- .../Runtime/Binder/ApplicationContext.cs | 6 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 345 +++++++++--------- .../src/Internal/Runtime/Binder/BindResult.cs | 6 +- 3 files changed, 183 insertions(+), 174 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index 8d4d1039efb396..aad59c9e92421d 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -28,7 +28,7 @@ internal class ApplicationContext public Dictionary ExecutionContext { get; } = new Dictionary(); - public Dictionary FailureCache { get; } = new Dictionary(); + public Dictionary FailureCache { get; } = new Dictionary(); public object ContextCriticalSection { get; } = new object(); @@ -300,9 +300,9 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string } } - public void AddToFailureCache(AssemblyName assemblyName, Exception? failure) + public void AddToFailureCache(AssemblyName assemblyName, int hresult) { - FailureCache.Add(new FailureCacheKey(assemblyName), failure); + FailureCache.Add(new FailureCacheKey(assemblyName), hresult); IncrementVersion(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index f7a39b9d0e01ad..bd765e074655ef 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -146,10 +146,14 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) } } - public static Assembly? BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths) + private const int FUSION_E_APP_DOMAIN_LOCKED = unchecked((int)0x80131053); + + public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) { int kContextVersion = 0; - BindResult bindResult; + BindResult bindResult = default; + int hr; + result = null; ApplicationContext applicationContext = binder.AppContext; // Tracing happens outside the binder lock to avoid calling into managed code within the lock @@ -158,7 +162,9 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) Retry: lock (applicationContext.ContextCriticalSection) { - bindResult = BindByName(applicationContext, assemblyName, false, false, excludeAppPaths); + hr = BindByName(applicationContext, assemblyName, false, false, excludeAppPaths, ref bindResult); + + if (hr < 0) return hr; // Remember the post-bind version kContextVersion = applicationContext.Version; @@ -168,12 +174,9 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) if (bindResult.Assembly != null) { - if (RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult)) - { - Debug.Assert(hostBindResult.Assembly != null); - return hostBindResult.Assembly; - } - else + hr = RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult); + + if (hr == HResults.S_FALSE) { // Another bind interfered. We need to retry the entire bind. // This by design loops as long as needed because by construction we eventually @@ -181,99 +184,105 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) bindResult = default; goto Retry; } + else if (hr == HResults.S_OK) + { + Debug.Assert(hostBindResult.Assembly != null); + result = hostBindResult.Assembly; + } } - return null; + return hr; } // Skipped - the managed binder can't bootstrap CoreLib // static Assembly? BindToSystem(string systemDirectory); // static Assembly? BindToSystemSatellite(string systemDirectory, string simpleName, string cultureName); - private static BindResult BindByName(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipFailureChecking, bool skipVersionCompatibilityCheck, bool excludeAppPaths) + private static int BindByName( + ApplicationContext applicationContext, + AssemblyName assemblyName, + bool skipFailureChecking, + bool skipVersionCompatibilityCheck, + bool excludeAppPaths, + ref BindResult bindResult) { // Look for already cached binding failure (ignore PA, every PA will lock the context) - if (applicationContext.FailureCache.TryGetValue(new FailureCacheKey(assemblyName), out Exception? failure)) + if (applicationContext.FailureCache.TryGetValue(new FailureCacheKey(assemblyName), out int hr)) { - if (failure != null) // FAILED(hr) + if (hr < 0) // FAILED(hr) { - if (failure is FileNotFoundException && skipFailureChecking) + if (hr == HResults.E_FILENOTFOUND && skipFailureChecking) { // Ignore pre-existing transient bind error (re-bind will succeed) applicationContext.FailureCache.Remove(new FailureCacheKey(assemblyName)); } - return default; + return hr; // goto LogExit } - else // hr == HResults.S_FALSE + else if (hr == HResults.S_FALSE) { // workaround: Special case for byte arrays. Rerun the bind to create binding log. assemblyName.IsDefinition = true; } } - BindResult bindResult = default; - - try + if (!IsValidArchitecture(assemblyName.Architecture)) { - if (!IsValidArchitecture(assemblyName.Architecture)) - { - // Assembly reference contains wrong architecture - throw new Exception("FUSION_E_INVALID_NAME"); - } + // Assembly reference contains wrong architecture + hr = HResults.FUSION_E_INVALID_NAME; + goto Exit; + } - BindLocked(applicationContext, assemblyName, skipVersionCompatibilityCheck, excludeAppPaths, ref bindResult); + hr = BindLocked(applicationContext, assemblyName, skipVersionCompatibilityCheck, excludeAppPaths, ref bindResult); - if (bindResult.Assembly == null) - { - // Behavior rules are clueless now - throw new FileNotFoundException(); - } + if (hr < 0) return hr; - return bindResult; + if (bindResult.Assembly == null) + { + // Behavior rules are clueless now + hr = HResults.E_FILENOTFOUND; + goto Exit; } - catch (Exception ex) + + Exit: + if (hr < 0) { if (skipFailureChecking) { - if (ex is not FileNotFoundException) + if (hr != HResults.E_FILENOTFOUND) { // Cache non-transient bind error for byte-array - ex = null!; + hr = HResults.S_FALSE; } else { // Ignore transient bind error (re-bind will succeed) - return bindResult; + return hr; // goto LogExit; } } - applicationContext.AddToFailureCache(assemblyName, ex); - - throw; + applicationContext.AddToFailureCache(assemblyName, hr); } + + return hr; } - private static void BindLocked(ApplicationContext applicationContext, AssemblyName assemblyName, bool skipVersionCompatibilityCheck, bool excludeAppPaths, ref BindResult bindResult) + private static int BindLocked( + ApplicationContext applicationContext, + AssemblyName assemblyName, + bool skipVersionCompatibilityCheck, + bool excludeAppPaths, + ref BindResult bindResult) { bool isTpaListProvided = applicationContext.TrustedPlatformAssemblyMap != null; - Assembly? assembly = null; + int hr = FindInExecutionContext(applicationContext, assemblyName, out Assembly? assembly); - try - { - assembly = FindInExecutionContext(applicationContext, assemblyName); - } - catch (Exception ex) - { - bindResult.SetAttemptResult(assembly, ex, isInContext: true); - throw; - } + // Add the attempt to the bind result on failure / not found. On success, it will be added after the version check. + if (hr < 0 || assembly == null) + bindResult.SetAttemptResult(hr, assembly, isInContext: true); - if (assembly == null) // if (FAILED(hr) || pAssembly == NULL) - { - bindResult.SetAttemptResult(null, null, isInContext: true); - } + if (hr < 0) return hr; if (assembly != null) { @@ -281,66 +290,63 @@ private static void BindLocked(ApplicationContext applicationContext, AssemblyNa { // Can't give higher version than already bound bool isCompatible = IsCompatibleAssemblyVersion(assemblyName, assembly.AssemblyName); - Exception? exception = isCompatible ? null : new Exception("FUSION_E_APP_DOMAIN_LOCKED"); - bindResult.SetAttemptResult(assembly, exception, isInContext: true); + hr = isCompatible ? HResults.S_OK : FUSION_E_APP_DOMAIN_LOCKED; + bindResult.SetAttemptResult(hr, assembly, isInContext: true); // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version - if (exception != null && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED - exception = new Exception("FUSION_E_REF_DEF_MISMATCH"); - - if (exception != null) - throw exception; + if (hr == FUSION_E_APP_DOMAIN_LOCKED && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED + hr = HResults.FUSION_E_REF_DEF_MISMATCH; } else { - bindResult.SetAttemptResult(assembly, null, isInContext: true); + bindResult.SetAttemptResult(hr, assembly, isInContext: true); } + if (hr < 0) return hr; + bindResult.SetResult(assembly, isInContext: true); } else if (isTpaListProvided) { // BindByTpaList handles setting attempt results on the bind result - try - { - BindByTpaList(applicationContext, assemblyName, excludeAppPaths, ref bindResult); - - if (bindResult.Assembly != null) // SUCCEEDED(hr) && pBindResult->HaveResult() - { - bool isCompatible = IsCompatibleAssemblyVersion(assemblyName, bindResult.Assembly.AssemblyName); - Exception? exception = isCompatible ? null : new Exception("FUSION_E_APP_DOMAIN_LOCKED"); - bindResult.SetAttemptResult(bindResult.Assembly, exception, isInContext: false); + hr = BindByTpaList(applicationContext, assemblyName, excludeAppPaths, ref bindResult); - // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version - if (exception != null && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED - exception = new Exception("FUSION_E_REF_DEF_MISMATCH"); + if (hr >= 0 && bindResult.Assembly != null) // SUCCEEDED(hr) && pBindResult->HaveResult() + { + bool isCompatible = IsCompatibleAssemblyVersion(assemblyName, bindResult.Assembly.AssemblyName); + hr = isCompatible ? HResults.S_OK : FUSION_E_APP_DOMAIN_LOCKED; + bindResult.SetAttemptResult(hr, assembly, isInContext: false); - if (exception != null) - throw exception; - } + // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version + if (hr == FUSION_E_APP_DOMAIN_LOCKED && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED + hr = HResults.FUSION_E_REF_DEF_MISMATCH; } - catch + + if (hr < 0) { bindResult.SetNoResult(); - throw; } } + + return hr; } - private static Assembly? FindInExecutionContext(ApplicationContext applicationContext, AssemblyName assemblyName) + private static int FindInExecutionContext(ApplicationContext applicationContext, AssemblyName assemblyName, out Assembly? assembly) { - applicationContext.ExecutionContext.TryGetValue(assemblyName, out Assembly? assembly); + applicationContext.ExecutionContext.TryGetValue(assemblyName, out assembly); // Set any found context entry. It is up to the caller to check the returned HRESULT // for errors due to validation + if (assembly == null) + return HResults.S_FALSE; if (assembly != null && assemblyName.IsDefinition && (assembly.AssemblyName.Architecture != assemblyName.Architecture)) { - throw new Exception("FUSION_E_APP_DOMAIN_LOCKED"); + return FUSION_E_APP_DOMAIN_LOCKED; } - return assembly; + return HResults.S_OK; } // @@ -370,7 +376,7 @@ private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyNam // TODO: BindSatelliteResource - private static Assembly BindAssemblyByProbingPaths(List bindingPaths, AssemblyName requestedAssemblyName) + private static int BindAssemblyByProbingPaths(List bindingPaths, AssemblyName requestedAssemblyName, out Assembly? result) { // Loop through the binding paths looking for a matching assembly foreach (string bindingPath in bindingPaths) @@ -380,36 +386,44 @@ private static Assembly BindAssemblyByProbingPaths(List bindingPaths, As // Look for a matching dll first string fileName = fileNameWithoutExtension + ".dll"; - try - { - Assembly assembly = GetAssembly(fileName, false); + int hr = GetAssembly(fileName, isInTPA: false, out Assembly? assembly); + // BinderTracing::PathProbed(fileName, pathSource, hr); + if (hr < 0) + { + fileName = fileNameWithoutExtension + ".exe"; + hr = GetAssembly(fileName, isInTPA: false, out assembly); // BinderTracing::PathProbed(fileName, pathSource, hr); + } - // We found a candidate. - // - // Below this point, we either establish that the ref-def matches, or - // we fail the bind. + // Since we're probing, file not founds are ok and we should just try another + // probing path + if (hr == HResults.COR_E_FILENOTFOUND) + { + continue; + } - // Compare requested AssemblyName with that from the candidate assembly - if (!TestCandidateRefMatchesDef(requestedAssemblyName, assembly.AssemblyName, false)) - throw new Exception("FUSION_E_REF_DEF_MISMATCH"); + // Set any found assembly. It is up to the caller to check the returned HRESULT for errors due to validation + result = assembly; + if (hr < 0) + return hr; - return assembly; // S_OK - } - catch (Exception ex) - { - if (ex is FileNotFoundException) - { - // Since we're probing, file not founds are ok and we should just try another - // probing path - continue; - } + // We found a candidate. + // + // Below this point, we either establish that the ref-def matches, or + // we fail the bind. - } + Debug.Assert(assembly != null); + + // Compare requested AssemblyName with that from the candidate assembly + if (!TestCandidateRefMatchesDef(requestedAssemblyName, assembly.AssemblyName, tpaListAssembly: false)) + return HResults.FUSION_E_REF_DEF_MISMATCH; + + return HResults.S_OK; } - throw new FileNotFoundException(); + result = null; + return HResults.COR_E_FILENOTFOUND; } /* @@ -433,7 +447,7 @@ private static Assembly BindAssemblyByProbingPaths(List bindingPaths, As * */ - public static void BindByTpaList(ApplicationContext applicationContext, AssemblyName requestedAssemblyName, bool excludeAppPaths, ref BindResult bindResult) + public static int BindByTpaList(ApplicationContext applicationContext, AssemblyName requestedAssemblyName, bool excludeAppPaths, ref BindResult bindResult) { bool fPartialMatchOnTpa = false; @@ -460,39 +474,33 @@ public static void BindByTpaList(ApplicationContext applicationContext, Assembly string? tpaFileName = tpaEntry.NIFileName ?? tpaEntry.ILFileName; Debug.Assert(tpaFileName != null); - try - { - tpaAssembly = GetAssembly(tpaFileName, isInTPA: true); - // BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); + int hr = GetAssembly(tpaFileName, isInTPA: true, out tpaAssembly); + // BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); - bindResult.SetAttemptResult(tpaAssembly, null); + bindResult.SetAttemptResult(hr, tpaAssembly); - if (TestCandidateRefMatchesDef(requestedAssemblyName, tpaAssembly.AssemblyName, true)) + // On file not found, simply fall back to app path probing + if (hr != HResults.E_FILENOTFOUND) + { + // Any other error is fatal + if (hr < 0) return hr; + + Debug.Assert(tpaAssembly != null); + if (TestCandidateRefMatchesDef(requestedAssemblyName, tpaAssembly.AssemblyName, tpaListAssembly: true)) { // We have found the requested assembly match on TPA with validation of the full-qualified name. Bind to it. bindResult.SetResult(tpaAssembly); - bindResult.SetAttemptResult(tpaAssembly, null); - return; + bindResult.SetAttemptResult(HResults.S_OK, tpaAssembly); + return HResults.S_OK; } else { // We found the assembly on TPA but it didn't match the RequestedAssembly assembly-name. In this case, lets proceed to see if we find the requested // assembly in the App paths. - bindResult.SetAttemptResult(tpaAssembly, new Exception("FUSION_E_REF_DEF_MISMATCH")); + bindResult.SetAttemptResult(HResults.FUSION_E_REF_DEF_MISMATCH, tpaAssembly); fPartialMatchOnTpa = true; } } - catch (Exception ex) - { - bindResult.SetAttemptResult(null, ex); - - // On file not found, simply fall back to app path probing - if (ex is not FileNotFoundException) - { - // Any other error is fatal - throw; - } - } // We either didn't find a candidate, or the ref-def failed. Either way; fall back to app path probing. } @@ -501,10 +509,13 @@ public static void BindByTpaList(ApplicationContext applicationContext, Assembly { // Probe AppPaths - try + int hr = BindAssemblyByProbingPaths(applicationContext.AppPaths, requestedAssemblyName, out Assembly? assembly); + bindResult.SetAttemptResult(hr, assembly); + + if (hr != HResults.E_FILENOTFOUND) { - Assembly assembly = BindAssemblyByProbingPaths(applicationContext.AppPaths, requestedAssemblyName); - bindResult.SetAttemptResult(assembly, null); + if (hr < 0) return hr; + Debug.Assert(assembly != null); // At this point, we have found an assembly with the expected name in the App paths. If this was also found on TPA, // make sure that the app assembly has the same fullname (excluding version) as the TPA version. If it does, then @@ -518,24 +529,21 @@ public static void BindByTpaList(ApplicationContext applicationContext, Assembly { // Fullname (SimpleName+Culture+PKT) matched for TPA and app assembly - so bind to TPA instance. bindResult.SetResult(tpaAssembly); - bindResult.SetAttemptResult(tpaAssembly, null); - return; + bindResult.SetAttemptResult(hr, tpaAssembly); + return HResults.S_OK; } else { // Fullname (SimpleName+Culture+PKT) did not match for TPA and app assembly - so bind to app instance. bindResult.SetResult(assembly); - return; + return HResults.S_OK; } } - } - catch (Exception ex) - { - bindResult.SetAttemptResult(null, ex); - - if (ex is not FileNotFoundException) + else { - throw; + // We didn't see this assembly on TPA - so simply bind to the app instance. + bindResult.SetResult(assembly); + return HResults.S_OK; } } } @@ -544,12 +552,17 @@ public static void BindByTpaList(ApplicationContext applicationContext, Assembly // Couldn't find a matching assembly in any of the probing paths // Return S_FALSE here. BindByName will interpret a successful HRESULT // and lack of BindResult as a failure to find a matching assembly. - return; + return HResults.S_FALSE; } // static Assembly GetAssembly(string assemblyPath, bool isInTPA, BundleFileLocation); - public static void Register(ApplicationContext applicationContext, ref BindResult bindResult) + static int GetAssembly(string assemblyPath, bool isInTPA, out Assembly? assembly) + { + throw null; + } + + public static int Register(ApplicationContext applicationContext, ref BindResult bindResult) { Debug.Assert(bindResult.IsContextBound); Debug.Assert(bindResult.Assembly != null); @@ -558,7 +571,9 @@ public static void Register(ApplicationContext applicationContext, ref BindResul // Register the bindResult in the ExecutionContext only if we dont have it already. // This method is invoked under a lock (by its caller), so we are thread safe. - Assembly? assembly = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName); + int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out Assembly? assembly); + if (hr < 0) + return hr; if (assembly == null) { @@ -569,12 +584,15 @@ public static void Register(ApplicationContext applicationContext, ref BindResul // Update the BindResult with the assembly we found bindResult.SetResult(assembly, isInContext: true); } + + return HResults.S_OK; } - public static bool RegisterAndGetHostChosen(ApplicationContext applicationContext, int kContextVersion, BindResult bindResult, out BindResult hostBindResult) + public static int RegisterAndGetHostChosen(ApplicationContext applicationContext, int kContextVersion, in BindResult bindResult, out BindResult hostBindResult) { Debug.Assert(bindResult.Assembly != null); hostBindResult = default; + int hr = HResults.S_OK; if (!bindResult.IsContextBound) { @@ -586,15 +604,19 @@ public static bool RegisterAndGetHostChosen(ApplicationContext applicationContex // Only perform costly validation if other binds succeeded before us if (kContextVersion != applicationContext.Version) { - if (OtherBindInterferred(applicationContext, bindResult)) // S_FALSE == return true + hr = OtherBindInterferred(applicationContext, bindResult); + if (hr < 0) return hr; + + if (hr == HResults.S_FALSE) { // Another bind interfered - return false; // S_FALSE == return false + return hr; } } // No bind interfered, we can now register - Register(applicationContext, ref hostBindResult); + hr = Register(applicationContext, ref hostBindResult); + if (hr < 0) return hr; } } else @@ -603,40 +625,27 @@ public static bool RegisterAndGetHostChosen(ApplicationContext applicationContex hostBindResult = bindResult; } - return true; + return hr; } - private static bool OtherBindInterferred(ApplicationContext applicationContext, BindResult bindResult) + private static int OtherBindInterferred(ApplicationContext applicationContext, BindResult bindResult) { Debug.Assert(bindResult.Assembly != null); + Debug.Assert(bindResult.Assembly.AssemblyName != null); // Look for already cached binding failure (ignore PA, every PA will lock the context) - if (!applicationContext.FailureCache.ContainsKey(new FailureCacheKey(bindResult.Assembly.AssemblyName))) + if (!applicationContext.FailureCache.ContainsKey(new FailureCacheKey(bindResult.Assembly.AssemblyName))) // hr == S_OK { - // hr == S_OK - try - { - Assembly? assembly = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName); - if (assembly != null) // SUCCEEDED(hr) - { - // We can accept this bind in the domain - return false; // S_OK == return false - } - } - catch + int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out Assembly? assembly); + if (hr >= 0 && assembly != null) { - // No throwing + // We can accept this bind in the domain + return HResults.S_OK; } - } // Some other bind interfered - return true; // S_FALSE == return true - } - - static Assembly GetAssembly(string assemblyPath, bool isInTPA) - { - throw null; + return HResults.S_FALSE; } public static bool IsValidArchitecture(PEKind architecture) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs index dd01323a4e35d4..f0eda0d346162b 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs @@ -10,7 +10,7 @@ internal struct BindResult public struct AttemptResult { public Assembly? Assembly; - public Exception? Exception; + public int HResult; public bool Attempted; } @@ -20,11 +20,11 @@ public struct AttemptResult private AttemptResult _inContextAttempt; private AttemptResult _applicationAssembliesResult; - public void SetAttemptResult(Assembly? assembly, Exception? exception, bool isInContext = false) + public void SetAttemptResult(int hResult, Assembly? assembly, bool isInContext = false) { ref AttemptResult result = ref (isInContext ? ref _inContextAttempt : ref _applicationAssembliesResult); + result.HResult = hResult; result.Assembly = assembly; - result.Exception = exception; result.Attempted = true; } From a7de55ae8aba99d9ad7c5adc06d9cde561c980ec Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Aug 2023 22:47:39 +0800 Subject: [PATCH 016/136] GetAssembly --- .../Runtime/Binder/AssemblyBinderCommon.cs | 97 +++++++++++++++++-- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index bd765e074655ef..c2126e356a830a 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -5,9 +5,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; +using System.Text; namespace Internal.Runtime.Binder { @@ -21,8 +21,21 @@ internal enum CorPEKind pe32BitPreferred = 0x00000010 // flags 32BITREQUIRED and 32BITPREFERRED are set in COR header } - internal static class AssemblyBinderCommon + internal struct BundleFileLocation { + public long Size; + public long Offset; + public long UncompressedSize; + } + + internal static partial class AssemblyBinderCommon + { + [LibraryImport("Foo", StringMarshalling = StringMarshalling.Utf8)] + private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void ReleasePEImage(IntPtr pPEImage); + public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; @@ -146,7 +159,28 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) } } + // HResult + private const int RO_E_METADATA_NAME_NOT_FOUND = unchecked((int)0x8000000F); + private const int E_PATHNOTFOUND = unchecked((int)0x80070003); + private const int E_NOTREADY = unchecked((int)0x80070015); + private const int E_BADNETPATH = unchecked((int)0x80070035); + private const int E_BADNETNAME = unchecked((int)0x80070043); + private const int E_INVALID_NAME = unchecked((int)0x8007007B); + private const int E_MODNOTFOUND = unchecked((int)0x8007007E); + private const int E_DLLNOTFOUND = unchecked((int)0x80070485); + private const int E_WRONG_TARGET_NAME = unchecked((int)0x80070574); + private const int INET_E_CANNOT_CONNECT = unchecked((int)0x800C0004); + private const int INET_E_RESOURCE_NOT_FOUND = unchecked((int)0x800C0005); + private const int INET_E_OBJECT_NOT_FOUND = unchecked((int)0x800C0006); + private const int INET_E_DATA_NOT_AVAILABLE = unchecked((int)0x800C0007); + private const int INET_E_DOWNLOAD_FAILURE = unchecked((int)0x800C0008); + private const int INET_E_CONNECTION_TIMEOUT = unchecked((int)0x800C000B); + private const int INET_E_UNKNOWN_PROTOCOL = unchecked((int)0x800C000D); private const int FUSION_E_APP_DOMAIN_LOCKED = unchecked((int)0x80131053); + private const int CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW = unchecked((int)0x80132000); + private const int CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH = unchecked((int)0x80132001); + private const int CLR_E_BIND_ASSEMBLY_NOT_FOUND = unchecked((int)0x80132004); + private const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) { @@ -555,11 +589,60 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN return HResults.S_FALSE; } - // static Assembly GetAssembly(string assemblyPath, bool isInTPA, BundleFileLocation); - - static int GetAssembly(string assemblyPath, bool isInTPA, out Assembly? assembly) + private static int GetAssembly(string assemblyPath, bool isInTPA, out Assembly? assembly, BundleFileLocation bundleFileLocation = default) { - throw null; + int hr = BinderAcquirePEImage(assemblyPath, out IntPtr pPEImage, bundleFileLocation); + + try + { + if (hr < 0) + { + // Normalize file not found + + // ported from Assembly::FileNotFound in coreclr\vm\assembly.cpp + if (hr is HResults.E_FILENOTFOUND + or E_MODNOTFOUND + or E_INVALID_NAME + or HResults.CTL_E_FILENOTFOUND + or E_PATHNOTFOUND + or E_BADNETNAME + or E_BADNETPATH + or E_NOTREADY + or E_WRONG_TARGET_NAME + or INET_E_UNKNOWN_PROTOCOL + or INET_E_CONNECTION_TIMEOUT + or INET_E_CANNOT_CONNECT + or INET_E_RESOURCE_NOT_FOUND + or INET_E_OBJECT_NOT_FOUND + or INET_E_DOWNLOAD_FAILURE + or INET_E_DATA_NOT_AVAILABLE + or E_DLLNOTFOUND + or CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW + or CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH + or CLR_E_BIND_ASSEMBLY_NOT_FOUND + or RO_E_METADATA_NAME_NOT_FOUND + or CLR_E_BIND_TYPE_NOT_FOUND) + { + hr = HResults.E_FILENOTFOUND; + } + + assembly = null; + return hr; + } + + assembly = new Assembly(pPEImage, isInTPA); + return HResults.S_OK; + } + catch (Exception e) + { + assembly = null; + return e.HResult; + } + finally + { + // SAFE_RELEASE(pPEImage); + ReleasePEImage(pPEImage); + } } public static int Register(ApplicationContext applicationContext, ref BindResult bindResult) From 9c77d7eaf290d8ef44a66a3eb2108c353e02f364 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Aug 2023 23:08:44 +0800 Subject: [PATCH 017/136] BindUsingPEImage --- .../Runtime/Binder/AssemblyBinderCommon.cs | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index c2126e356a830a..b29d85adce3562 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -36,6 +36,9 @@ internal static partial class AssemblyBinderCommon [MethodImpl(MethodImplOptions.InternalCall)] private static extern void ReleasePEImage(IntPtr pPEImage); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); + public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; @@ -731,6 +734,110 @@ private static int OtherBindInterferred(ApplicationContext applicationContext, B return HResults.S_FALSE; } + // BindUsingHostAssemblyResolver + + public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) + { + int hr; + + int kContextVersion = 0; + BindResult bindResult = default; + + // Prepare binding data + assembly = null; + ApplicationContext applicationContext = binder.AppContext; + + // Tracing happens outside the binder lock to avoid calling into managed code within the lock + // BinderTracing::ResolutionAttemptedOperation tracer{pAssemblyName, pBinder, 0 /*managedALC*/, hr}; + + Retry: + bool mvidMismatch = false; + + // Lock the application context + lock (applicationContext.ContextCriticalSection) + { + // Attempt uncached bind and register stream if possible + // We skip version compatibility check - so assemblies with same simple name will be reported + // as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check). + hr = BindByName(applicationContext, assemblyName, true, true, excludeAppPaths, ref bindResult); + + if (hr == HResults.E_FILENOTFOUND) + { + // IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); + try + { + bindResult.SetResult(new Assembly(pPEImage, false)); + } + catch (Exception ex) + { + return ex.HResult; + } + } + else if (hr == HResults.S_OK) + { + if (bindResult.Assembly != null) + { + // Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name + // does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being + // requested. + + Guid incomingMVID; + Guid boundMVID; + + try + { + PEImage_GetMVID(pPEImage, out incomingMVID); + PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); + } + catch (Exception ex) + { + return ex.HResult; + } + + mvidMismatch = incomingMVID != boundMVID; + if (mvidMismatch) + { + // MVIDs do not match, so fail the load. + return HResults.COR_E_FILELOAD; + } + + // MVIDs match - request came in for the same assembly that was previously loaded. + // Let it through... + } + } + + // Remember the post-bind version of the context + kContextVersion = applicationContext.Version; + } + + if (bindResult.Assembly != null) + { + // This has to happen outside the binder lock as it can cause new binds + hr = RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult); + if (hr < 0) return hr; + + if (hr == HResults.S_FALSE) + { + // tracer.TraceBindResult(bindResult); + + // Another bind interfered. We need to retry entire bind. + // This by design loops as long as needed because by construction we eventually + // will succeed or fail the bind. + bindResult = default; + goto Retry; + } + else if (hr == HResults.S_OK) + { + assembly = hostBindResult.Assembly; + } + } + + // tracer.TraceBindResult(bindResult, mvidMismatch); + return hr; + } + + // CreateDefaultBinder + public static bool IsValidArchitecture(PEKind architecture) { if (architecture is PEKind.MSIL or PEKind.None) From 116f7bfc65f63bbbb72c2da5b59e4bc504d3ffe9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 31 Aug 2023 23:26:35 +0800 Subject: [PATCH 018/136] Guard behind feature switch --- .../System.Private.CoreLib.csproj | 20 ++++++++++--------- src/coreclr/clr.featuredefines.props | 2 ++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index ef7c345c021e04..b88d298fcf0229 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,15 +119,6 @@ - - - - - - - - - @@ -308,6 +299,17 @@ + + + + + + + + + + + diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props index 0ccfc347d0a0eb..0991e5bd6e9529 100644 --- a/src/coreclr/clr.featuredefines.props +++ b/src/coreclr/clr.featuredefines.props @@ -10,6 +10,7 @@ true true true + false @@ -67,5 +68,6 @@ $(DefineConstants);PROFILING_SUPPORTED $(DefineConstants);FEATURE_PROFAPI_ATTACH_DETACH + $(DefineConstants);FEATURE_MANAGED_BINDER From 9fff7e244c5c9b425e42f8fc0763ce98d9b77ec7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 1 Sep 2023 11:15:42 +0800 Subject: [PATCH 019/136] Reuse IsPathFullyQualified --- .../Runtime/Binder/ApplicationContext.cs | 32 ++----------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index aad59c9e92421d..be1dc9780161c0 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -111,32 +111,6 @@ private static bool GetNextPath(string paths, ref int startPos, out string outPa return true; } - private static bool IsRelativePath(ReadOnlySpan path) - { - // ported from coreclr/inc/clr/fs/path.h - -#if TARGET_WINDOWS - // Check for a paths like "C:\..." or "\\...". Additional notes: - // - "\\?\..." - long format paths are considered as absolute paths due to the "\\" prefix - // - "\..." - these paths are relative, as they depend on the current drive - // - "C:..." and not "C:\..." - these paths are relative, as they depend on the current directory for drive C - if (path is [(>= 'A' and <= 'Z') or (>= 'a' and <= 'z'), PathInternal.VolumeSeparatorChar, PathInternal.DirectorySeparatorChar, ..]) - { - return false; - } - if (path is [PathInternal.DirectorySeparatorChar, PathInternal.DirectorySeparatorChar, ..]) - { - return false; - } -#else - if (path is [PathInternal.DirectorySeparatorChar, ..]) - { - return false; - } -#endif - return true; - } - private static bool GetNextTPAPath(string paths, ref int startPos, bool dllOnly, out string outPath, out string simpleName, out bool isNativeImage) { isNativeImage = false; @@ -149,7 +123,7 @@ private static bool GetNextTPAPath(string paths, ref int startPos, bool dllOnly, return false; } - if (IsRelativePath(outPath)) + if (!Path.IsPathFullyQualified(outPath)) { throw new ArgumentException(nameof(paths)); } @@ -270,7 +244,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string break; } - if (IsRelativePath(pathName)) + if (!Path.IsPathFullyQualified(pathName)) { throw new ArgumentException(nameof(pathName)); } @@ -290,7 +264,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string } - if (IsRelativePath(pathName)) + if (!Path.IsPathFullyQualified(pathName)) { throw new ArgumentException(nameof(pathName)); } From b092474dcdfb9c1e5fbfb8676656e42c5443813e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 1 Sep 2023 11:18:32 +0800 Subject: [PATCH 020/136] Reuse ComputePublicKeyToken --- .../Internal/Runtime/Binder/AssemblyName.cs | 19 ++++--------------- .../AssemblyNameHelpers.StrongName.cs | 14 ++++++-------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 49ec1b9ad7a9e6..ab82a6b2e5aef2 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; using System.Text; @@ -158,12 +159,10 @@ public AssemblyName(IntPtr pPEImage) { if ((dwRefOrDefFlags & CorAssemblyFlags.afPublicKey) != 0) { - byte* pByteToken; - uint dwTokenLen; - StrongNameTokenFromPublicKey(pvPublicKeyToken, dwPublicKeyToken, &pByteToken, &dwTokenLen); + byte[]? publicKeyToken = System.Reflection.AssemblyNameHelpers.ComputePublicKeyToken(new ReadOnlySpan(pvPublicKeyToken, (int)dwPublicKeyToken)); + Debug.Assert(publicKeyToken != null); - PublicKeyOrTokenBLOB = new ReadOnlySpan(pByteToken, (int)dwTokenLen).ToArray(); - StrongNameFreeBuffer(pByteToken); + PublicKeyOrTokenBLOB = publicKeyToken; } else { @@ -181,16 +180,6 @@ public AssemblyName(IntPtr pPEImage) // Foo internal calls - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void StrongNameTokenFromPublicKey( - byte* pbPublicKeyBlob, // [in] public key blob - uint cbPublicKeyBlob, - byte** ppbStrongNameToken, // [out] strong name token - uint* pcbStrongNameToken); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void StrongNameFreeBuffer(byte* buffer); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern IMdInternalImport BinderAcquireImport(IntPtr pPEImage, int* dwPAFlags); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs index 6c2a6352118ce3..6927fff5d71c1d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs @@ -8,9 +8,9 @@ namespace System.Reflection { internal static partial class AssemblyNameHelpers { - public static byte[]? ComputePublicKeyToken(byte[]? publicKey) + public static byte[]? ComputePublicKeyToken(ReadOnlySpan publicKey) { - if (publicKey == null) + if (publicKey == default) return null; if (publicKey.Length == 0) @@ -35,16 +35,14 @@ internal static partial class AssemblyNameHelpers // // This validation logic is a port of StrongNameIsValidPublicKey() from src\coreclr\md\runtime\strongnameinternal.cpp // - private static bool IsValidPublicKey(byte[] publicKey) + private static bool IsValidPublicKey(ReadOnlySpan publicKeyBlob) { - uint publicKeyLength = (uint)(publicKey.Length); + uint publicKeyLength = (uint)(publicKeyBlob.Length); // The buffer must be at least as large as the public key structure (for compat with desktop, we actually compare with the size of the header + 4). if (publicKeyLength < SizeOfPublicKeyBlob + 4) return false; - // Poor man's reinterpret_cast into the PublicKeyBlob structure. - ReadOnlySpan publicKeyBlob = new ReadOnlySpan(publicKey); uint sigAlgID = BinaryPrimitives.ReadUInt32LittleEndian(publicKeyBlob); uint hashAlgID = BinaryPrimitives.ReadUInt32LittleEndian(publicKeyBlob.Slice(4)); uint cbPublicKey = BinaryPrimitives.ReadUInt32LittleEndian(publicKeyBlob.Slice(8)); @@ -71,7 +69,7 @@ private static bool IsValidPublicKey(byte[] publicKey) return false; // The key blob must indicate that it is a PUBLICKEYBLOB - if (publicKey[SizeOfPublicKeyBlob] != PUBLICKEYBLOB) + if (publicKeyBlob[SizeOfPublicKeyBlob] != PUBLICKEYBLOB) return false; return true; @@ -94,7 +92,7 @@ private static uint GetAlgSid(uint x) private const uint ALG_CLASS_SIGNATURE = (1 << 13); private const uint PUBLICKEYBLOB = 0x6; - private const uint SizeOfPublicKeyBlob = 12; + private const int SizeOfPublicKeyBlob = 12; private const int PublicKeyTokenLength = 8; From b4dbceaf3e4b4a16e0b754e054323a27cc02e3f9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 3 Sep 2023 20:20:14 +0800 Subject: [PATCH 021/136] Revert "Guard behind feature switch" This reverts commit 116f7bfc65f63bbbb72c2da5b59e4bc504d3ffe9. --- .../System.Private.CoreLib.csproj | 20 +++++++++---------- src/coreclr/clr.featuredefines.props | 2 -- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index b88d298fcf0229..ef7c345c021e04 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,6 +119,15 @@ + + + + + + + + + @@ -299,17 +308,6 @@ - - - - - - - - - - - diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props index 0991e5bd6e9529..0ccfc347d0a0eb 100644 --- a/src/coreclr/clr.featuredefines.props +++ b/src/coreclr/clr.featuredefines.props @@ -10,7 +10,6 @@ true true true - false @@ -68,6 +67,5 @@ $(DefineConstants);PROFILING_SUPPORTED $(DefineConstants);FEATURE_PROFAPI_ATTACH_DETACH - $(DefineConstants);FEATURE_MANAGED_BINDER From 6d71c2619bce4e0843413006e6d631757a6f6761 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 4 Sep 2023 21:15:16 +0800 Subject: [PATCH 022/136] Satisfy sealed analyzer --- .../src/Internal/Runtime/Binder/ApplicationContext.cs | 2 +- .../src/Internal/Runtime/Binder/Assembly.cs | 2 +- .../src/Internal/Runtime/Binder/AssemblyBinderCommon.cs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index be1dc9780161c0..bdb30574ffbb7f 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -20,7 +20,7 @@ internal record struct FailureCacheKey(string SimpleName, AssemblyVersion Versio public FailureCacheKey(AssemblyName assemblyName) : this(assemblyName.SimpleName, assemblyName.Version) { } } - internal class ApplicationContext + internal sealed class ApplicationContext { private volatile int _version; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 8abbb9dd9d1c9a..c34247da51d65f 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -8,7 +8,7 @@ namespace Internal.Runtime.Binder // BINDER_SPACE::Assembly represents a result of binding to an actual assembly (PEImage) // It is basically a tuple of 1) physical assembly and 2) binder which created/owns this binding // We also store whether it was bound using TPA list - internal class Assembly + internal sealed class Assembly { public IntPtr PEImage; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index b29d85adce3562..411c61d95b9eee 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -833,6 +833,7 @@ public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyN } // tracer.TraceBindResult(bindResult, mvidMismatch); + Debug.Assert(mvidMismatch); return hr; } From a85d2230a6fc881a4f939c52c9bad5ebbcd3837d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 5 Sep 2023 23:46:48 +0800 Subject: [PATCH 023/136] Tracing ResolutionAttemptedOperation --- .../System.Private.CoreLib.csproj | 1 + .../Runtime/Binder/AssemblyBinderCommon.cs | 58 ++-- .../Tracing/ResolutionAttemptedOperation.cs | 253 ++++++++++++++++++ .../src/Resources/Strings.resx | 70 ++--- 4 files changed, 321 insertions(+), 61 deletions(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index ef7c345c021e04..31acea961f64dc 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -128,6 +128,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 411c61d95b9eee..b96120d654809a 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +using Internal.Runtime.Binder.Tracing; namespace Internal.Runtime.Binder { @@ -163,38 +164,38 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) } // HResult - private const int RO_E_METADATA_NAME_NOT_FOUND = unchecked((int)0x8000000F); - private const int E_PATHNOTFOUND = unchecked((int)0x80070003); - private const int E_NOTREADY = unchecked((int)0x80070015); - private const int E_BADNETPATH = unchecked((int)0x80070035); - private const int E_BADNETNAME = unchecked((int)0x80070043); - private const int E_INVALID_NAME = unchecked((int)0x8007007B); - private const int E_MODNOTFOUND = unchecked((int)0x8007007E); - private const int E_DLLNOTFOUND = unchecked((int)0x80070485); - private const int E_WRONG_TARGET_NAME = unchecked((int)0x80070574); - private const int INET_E_CANNOT_CONNECT = unchecked((int)0x800C0004); - private const int INET_E_RESOURCE_NOT_FOUND = unchecked((int)0x800C0005); - private const int INET_E_OBJECT_NOT_FOUND = unchecked((int)0x800C0006); - private const int INET_E_DATA_NOT_AVAILABLE = unchecked((int)0x800C0007); - private const int INET_E_DOWNLOAD_FAILURE = unchecked((int)0x800C0008); - private const int INET_E_CONNECTION_TIMEOUT = unchecked((int)0x800C000B); - private const int INET_E_UNKNOWN_PROTOCOL = unchecked((int)0x800C000D); - private const int FUSION_E_APP_DOMAIN_LOCKED = unchecked((int)0x80131053); - private const int CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW = unchecked((int)0x80132000); - private const int CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH = unchecked((int)0x80132001); - private const int CLR_E_BIND_ASSEMBLY_NOT_FOUND = unchecked((int)0x80132004); - private const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); + public const int RO_E_METADATA_NAME_NOT_FOUND = unchecked((int)0x8000000F); + public const int E_PATHNOTFOUND = unchecked((int)0x80070003); + public const int E_NOTREADY = unchecked((int)0x80070015); + public const int E_BADNETPATH = unchecked((int)0x80070035); + public const int E_BADNETNAME = unchecked((int)0x80070043); + public const int E_INVALID_NAME = unchecked((int)0x8007007B); + public const int E_MODNOTFOUND = unchecked((int)0x8007007E); + public const int E_DLLNOTFOUND = unchecked((int)0x80070485); + public const int E_WRONG_TARGET_NAME = unchecked((int)0x80070574); + public const int INET_E_CANNOT_CONNECT = unchecked((int)0x800C0004); + public const int INET_E_RESOURCE_NOT_FOUND = unchecked((int)0x800C0005); + public const int INET_E_OBJECT_NOT_FOUND = unchecked((int)0x800C0006); + public const int INET_E_DATA_NOT_AVAILABLE = unchecked((int)0x800C0007); + public const int INET_E_DOWNLOAD_FAILURE = unchecked((int)0x800C0008); + public const int INET_E_CONNECTION_TIMEOUT = unchecked((int)0x800C000B); + public const int INET_E_UNKNOWN_PROTOCOL = unchecked((int)0x800C000D); + public const int FUSION_E_APP_DOMAIN_LOCKED = unchecked((int)0x80131053); + public const int CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW = unchecked((int)0x80132000); + public const int CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH = unchecked((int)0x80132001); + public const int CLR_E_BIND_ASSEMBLY_NOT_FOUND = unchecked((int)0x80132004); + public const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) { int kContextVersion = 0; BindResult bindResult = default; - int hr; + int hr = HResults.S_OK; result = null; ApplicationContext applicationContext = binder.AppContext; - // Tracing happens outside the binder lock to avoid calling into managed code within the lock - //BinderTracing::ResolutionAttemptedOperation tracer{ pAssemblyName, pBinder, 0 /*managedALC*/, hr}; + // Tracing happens outside the binder lock to avoid calling into managed code within the lock + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, managedALC: 0, ref hr); Retry: lock (applicationContext.ContextCriticalSection) @@ -207,7 +208,7 @@ public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, kContextVersion = applicationContext.Version; } - // tracer.TraceBindResult(bindResult); + tracer.TraceBindResult(bindResult); if (bindResult.Assembly != null) { @@ -738,7 +739,7 @@ private static int OtherBindInterferred(ApplicationContext applicationContext, B public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) { - int hr; + int hr = HResults.S_OK; int kContextVersion = 0; BindResult bindResult = default; @@ -748,7 +749,7 @@ public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyN ApplicationContext applicationContext = binder.AppContext; // Tracing happens outside the binder lock to avoid calling into managed code within the lock - // BinderTracing::ResolutionAttemptedOperation tracer{pAssemblyName, pBinder, 0 /*managedALC*/, hr}; + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, managedALC: 0, ref hr); Retry: bool mvidMismatch = false; @@ -832,8 +833,7 @@ public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyN } } - // tracer.TraceBindResult(bindResult, mvidMismatch); - Debug.Assert(mvidMismatch); + tracer.TraceBindResult(bindResult, mvidMismatch); return hr; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs new file mode 100644 index 00000000000000..37828a55533ff3 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -0,0 +1,253 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Diagnostics.Tracing; +using System.Runtime.CompilerServices; + +namespace Internal.Runtime.Binder.Tracing +{ + // An object of this class manages firing events for all the stages during a binder resolving + // attempt operation. It has minimal cost if tracing for this event is disabled. + // + // This class should be declared in the stack. As information is determined by each stage + // (e.g. an AssemblySpec is initialized), the appropriate Set*() method should be called. All + // pointers held by an object of this class must either be a nullptr, or point to a valid + // object during the time it is in scope. + // + // As the resolution progresses to different stages, the GoToStage() method should be called. + // Calling it will fire an event for the previous stage with whatever context the class had + // at that point; it is assumed that if GoToStage() is called, the previous stage failed + // (the HRESULT is read by the dtor to assess success). + // + // It holds a reference to a HRESULT (that must be live during the lifetime of this object), + // which is used to determine the success or failure of a stage either at the moment this + // class is destructed (e.g. last stage), or when moving from one stage to another. (This + // is especially useful if the HRESULT is captured from an exception handler.) + internal ref struct ResolutionAttemptedOperation + { + // This must match the ResolutionAttemptedStage value map in ClrEtwAll.man + public enum Stage : ushort + { + FindInLoadContext = 0, + AssemblyLoadContextLoad = 1, + ApplicationAssemblies = 2, + DefaultAssemblyLoadContextFallback = 3, + ResolveSatelliteAssembly = 4, + AssemblyLoadContextResolvingEvent = 5, + AppDomainAssemblyResolveEvent = 6, + NotYetStarted = 0xffff, // Used as flag to not fire event; not present in value map + }; + + // This must match the ResolutionAttemptedResult value map in ClrEtwAll.man + private enum Result : ushort + { + Success = 0, + AssemblyNotFound = 1, + IncompatibleVersion = 2, + MismatchedAssemblyName = 3, + Failure = 4, + Exception = 5, + }; + + private ref readonly int _hr; + private Stage _stage; + private bool _tracingEnabled; + private AssemblyName? _assemblyNameObject; + private Assembly? _foundAssembly; + private string _assemblyName = string.Empty; + private string _assemblyLoadContextName = string.Empty; + private string? _exceptionMessage; + + internal static bool IsEnabled() + { + return true; + } + + // One of native bindContext or binder is expected to be non-zero. If the managed ALC is set, binder is ignored. + public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? binder, IntPtr managedALC, ref int hResult) + { + _hr = ref hResult; + _stage = Stage.NotYetStarted; + _tracingEnabled = IsEnabled(); + _assemblyNameObject = assemblyName; + + Debug.Assert(binder != null || managedALC != 0); + + if (!_tracingEnabled) + return; + + // When binding the main assembly (by code base instead of name), the assembly name will be null. In this special case, we just + // leave the assembly name empty. + if (_assemblyNameObject != null) + _assemblyName = _assemblyNameObject.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); + + if (managedALC != 0) + { + // AssemblyBinder::GetNameForDiagnosticsFromManagedALC(managedALC, m_assemblyLoadContextName); + } + else + { + // binder->GetNameForDiagnostics(m_assemblyLoadContextName); + } + } + + public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) + { + if (_tracingEnabled) + return; + + string? errorMsg = null; + + // Use the error message that would be reported in the file load exception + if (mvidMismatch) + { + errorMsg = SR.Format(SR.Host_AssemblyResolver_AssemblyAlreadyLoadedInContext, _assemblyName, SR.Host_AssemblyResolver_AssemblyAlreadyLoadedInContext); + } + + BindResult.AttemptResult? inContextAttempt = bindResult.GetAttemptResult(isInContext: true); + BindResult.AttemptResult? appAssembliesAttempt = bindResult.GetAttemptResult(isInContext: false); + + if (inContextAttempt is { } inContextAttemptValue) + { + // If there the attempt HR represents a success, but the tracked HR represents a failure (e.g. from further validation), report the failed HR + bool isLastAttempt = appAssembliesAttempt == null; + TraceStage(Stage.FindInLoadContext, + isLastAttempt && (_hr < 0) && (inContextAttemptValue.HResult >= 0) ? _hr : inContextAttemptValue.HResult, + inContextAttemptValue.Assembly, + mvidMismatch && isLastAttempt ? errorMsg : null); + } + + if (appAssembliesAttempt is { } appAssembliesAttemptValue) + { + TraceStage(Stage.ApplicationAssemblies, + (_hr < 0) && (appAssembliesAttemptValue.HResult >= 0) ? _hr : appAssembliesAttemptValue.HResult, + appAssembliesAttemptValue.Assembly, + mvidMismatch ? errorMsg : null); + } + } + + public void SetFoundAssembly(Assembly assembly) => _foundAssembly = assembly; + + public void GoToStage(Stage stage) + { + Debug.Assert(stage != _stage); + Debug.Assert(stage != Stage.NotYetStarted); + + if (!_tracingEnabled) + return; + + // Going to a different stage should only happen if the current + // stage failed (or if the binding process wasn't yet started). + // Firing the event at this point not only helps timing each binding + // stage, but avoids keeping track of which stages were reached to + // resolve the assembly. + TraceStage(_stage, _hr, _foundAssembly); + _stage = stage; + _exceptionMessage = string.Empty; + } + + public void SetException(Exception ex) + { + if (!_tracingEnabled) + return; + + _exceptionMessage = ex.Message; + } + + // FEATURE_EVENT_TRACE + public void Dispose() + { + if (!_tracingEnabled) + return; + + TraceStage(_stage, _hr, _foundAssembly); + } + + // Foo + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string PEImage_GetPath(IntPtr pPEImage); + + public void TraceStage(Stage stage, int hResult, Assembly? resultAssembly, string? customError = null) + { + if (!_tracingEnabled || stage == Stage.NotYetStarted) + return; + + string resultAssemblyName = string.Empty; + string resultAssemblyPath = string.Empty; + + if (resultAssembly != null) + { + resultAssemblyName = resultAssembly.AssemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); + resultAssemblyPath = PEImage_GetPath(resultAssembly.PEImage); + } + + Result result; + string errorMsg; + if (customError != null) + { + errorMsg = customError; + result = Result.Failure; + } + else if (!string.IsNullOrEmpty(_exceptionMessage)) + { + errorMsg = _exceptionMessage; + result = Result.Exception; + } + else + { + switch (hResult) + { + case HResults.S_FALSE: + case HResults.COR_E_FILENOTFOUND: + result = Result.AssemblyNotFound; + errorMsg = "Could not locate assembly"; + break; + + case AssemblyBinderCommon.FUSION_E_APP_DOMAIN_LOCKED: + result = Result.IncompatibleVersion; + errorMsg = "Requested version"; + + if (_assemblyNameObject != null) + { + AssemblyVersion version = _assemblyNameObject.Version; + errorMsg += $" {version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; + } + + if (resultAssembly != null) + { + AssemblyVersion version = resultAssembly.AssemblyName.Version; + errorMsg += $" is incompatible with found version {version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; + } + + break; + + case HResults.FUSION_E_REF_DEF_MISMATCH: + result = Result.MismatchedAssemblyName; + errorMsg = $"Requested assembly name ':{_assemblyName}' does not match found assembly name"; + + if (resultAssembly != null) + { + errorMsg += $" '{resultAssemblyName}'"; + } + + break; + + case >= 0: // SUCCEEDED(hr) + result = Result.Success; + Debug.Assert(resultAssembly != null); + errorMsg = string.Empty; + break; + + default: + result = Result.Failure; + errorMsg = $"Resolution failed with HRESULT ({_hr:x8})"; + break; + } + } + + // FireEtwResolutionAttempted + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 2e00d445ee47ef..4701655e22ed4d 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -376,7 +376,7 @@ One of the identified items was in an invalid format. - + Generic arguments after array spec or pointer type. @@ -1080,7 +1080,7 @@ Field '{0}' does not belong to the same class as the constructor. - + Field '{0}' does not have a valid type. @@ -1502,7 +1502,7 @@ Path cannot be the empty string or all whitespace. - Value of argument {0} does not match parameter type: {1} -> {2}. + Value of argument {0} does not match parameter type: {1} -> {2}. Parameter {0} does not have a valid type. @@ -3774,7 +3774,7 @@ "Property '{0}' does not have a setter. - "Value of property '{0}' does not match property type: '{1}' -> '{2}'. + "Value of property '{0}' does not match property type: '{1}' -> '{2}'. Cannot load hostpolicy library. AssemblyDependencyResolver is currently only supported if the runtime is hosted through hostpolicy library. @@ -4253,4 +4253,10 @@ SearchValues<string> supports only StringComparison.Ordinal and StringComparison.OrdinalIgnoreCase. - + + Could not load file or assembly {0}. {1} + + + Assembly with same name is already loaded. + + \ No newline at end of file From 18da9944c31e3d8c8ac29af107d264a6c48e13dd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 7 Sep 2023 08:57:33 +0800 Subject: [PATCH 024/136] Event source qcall --- .../System.Private.CoreLib.csproj | 1 + .../Tracing/ResolutionAttemptedOperation.cs | 10 ++- ...eEventSource.Binder.NativeSinks.CoreCLR.cs | 62 +++++++++++++++++++ src/coreclr/scripts/genRuntimeEventSources.py | 4 ++ src/coreclr/vm/nativeeventsource.cpp | 10 +++ src/coreclr/vm/nativeeventsource.h | 1 + src/coreclr/vm/qcallentrypoints.cpp | 1 + 7 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 31acea961f64dc..3a215cb8af4065 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -149,6 +149,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index 37828a55533ff3..9a8e2786075543 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -247,7 +247,15 @@ public void TraceStage(Stage stage, int hResult, Assembly? resultAssembly, strin } } - // FireEtwResolutionAttempted + NativeRuntimeEventSource.Log.ResolutionAttempted( + 0, // GetClrInstanceId() + _assemblyName, + (ushort)stage, + _assemblyLoadContextName, + (ushort)result, + resultAssemblyName, + resultAssemblyPath, + errorMsg); } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs new file mode 100644 index 00000000000000..6f40855dd2e7fc --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs @@ -0,0 +1,62 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Diagnostics.Tracing +{ + // This is part of the NativeRuntimeEventsource, which is the managed version of the Microsoft-Windows-DotNETRuntime provider. + // It contains the runtime specific interop to native event sinks. + // + // Currently the Binder events are only used by managed binder of CoreCLR. + internal sealed unsafe partial class NativeRuntimeEventSource : EventSource + { + [NonEvent] + [MethodImpl(MethodImplOptions.NoInlining)] + public void ResolutionAttempted(ushort CLRInstanceId, + string AssemblyName, + ushort Stage, + string AssemblyLoadContext, + ushort Result, + string ResultAssemblyName, + string ResultAssemblyPath, + string ErrorMessage) + { + if (IsEnabled(EventLevel.Informational, Keywords.AssemblyLoaderKeyword)) + { + ResolutionAttempted(CLRInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, null, null); + } + } + + [Event(292, Level = EventLevel.Informational, Message = "", Task = default, Opcode = default, Version = 0, Keywords = Keywords.AssemblyLoaderKeyword)] + private unsafe void ResolutionAttempted( + ushort CLRInstanceId, + string AssemblyName, + ushort Stage, + string AssemblyLoadContext, + ushort Result, + string ResultAssemblyName, + string ResultAssemblyPath, + string ErrorMessage, + Guid* ActivityId = null, + Guid* RelatedActivityId = null) + { + LogResolutionAttempted(CLRInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, ActivityId, RelatedActivityId); + } + + [NonEvent] + [LibraryImport(RuntimeHelpers.QCall, StringMarshalling = StringMarshalling.Utf16)] + private static partial void LogResolutionAttempted( + ushort CLRInstanceId, + string AssemblyName, + ushort Stage, + string AssemblyLoadContext, + ushort Result, + string ResultAssemblyName, + string ResultAssemblyPath, + string ErrorMessage, + Guid* ActivityId, + Guid* RelatedActivityId); + } +} diff --git a/src/coreclr/scripts/genRuntimeEventSources.py b/src/coreclr/scripts/genRuntimeEventSources.py index f47a30f284519f..0e0b6e338c8827 100644 --- a/src/coreclr/scripts/genRuntimeEventSources.py +++ b/src/coreclr/scripts/genRuntimeEventSources.py @@ -92,6 +92,10 @@ def generateEvent(eventNode, providerNode, outputFile, stringTable): if "Contention" in symbol: return + # Fired by managed binder + if "ResolutionAttempted" in symbol: + return + evtLevel = eventNode.getAttribute("level")[4:] evtKeywords = "" # Write the event attribute. diff --git a/src/coreclr/vm/nativeeventsource.cpp b/src/coreclr/vm/nativeeventsource.cpp index b4bca0355e6c7a..d4031022a2687a 100644 --- a/src/coreclr/vm/nativeeventsource.cpp +++ b/src/coreclr/vm/nativeeventsource.cpp @@ -189,4 +189,14 @@ extern "C" void QCALLTYPE LogContentionStop(uint8_t ContentionFlags, uint16_t Cl END_QCALL; } +extern "C" void QCALLTYPE LogResolutionAttempted(uint16_t CLRInstanceId, LPCWSTR AssemblyName, uint16_t Stage, LPCWSTR AssemblyLoadContext, uint16_t Result, LPCWSTR ResultAssemblyName, LPCWSTR ResultAssemblyPath, LPCWSTR ErrorMessage, LPCGUID ActivityId, LPCGUID RelatedActivityId) +{ + QCALL_CONTRACT; + BEGIN_QCALL; + + FireEtwResolutionAttempted(CLRInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, ActivityId, RelatedActivityId); + + END_QCALL; +} + #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/vm/nativeeventsource.h b/src/coreclr/vm/nativeeventsource.h index a407c4b5ebb10b..182a2b973589b4 100644 --- a/src/coreclr/vm/nativeeventsource.h +++ b/src/coreclr/vm/nativeeventsource.h @@ -31,6 +31,7 @@ extern "C" void QCALLTYPE LogThreadPoolIOPack(_In_z_ void* nativeOverlapped, _In extern "C" void QCALLTYPE LogContentionLockCreated(void* LockID, void* AssociatedObjectID, uint16_t ClrInstanceID); extern "C" void QCALLTYPE LogContentionStart(uint8_t ContentionFlags, uint16_t ClrInstanceID, void* LockID, void* AssociatedObjectID, uint64_t LockOwnerThreadID); extern "C" void QCALLTYPE LogContentionStop(uint8_t ContentionFlags, uint16_t ClrInstanceID, double DurationNs); +extern "C" void QCALLTYPE LogResolutionAttempted(uint16_t CLRInstanceId, LPCWSTR AssemblyName, uint16_t Stage, LPCWSTR AssemblyLoadContext, uint16_t Result, LPCWSTR ResultAssemblyName, LPCWSTR ResultAssemblyPath, LPCWSTR ErrorMessage, LPCGUID ActivityId, LPCGUID RelatedActivityId); #endif // defined(FEATURE_PERFTRACING) #endif //_NATIVEEVENTSOURCE_H_ diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 0725bd7a87f097..4b0e940c904f91 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -281,6 +281,7 @@ static const Entry s_QCall[] = DllImportEntry(LogContentionLockCreated) DllImportEntry(LogContentionStart) DllImportEntry(LogContentionStop) + DllImportEntry(LogResolutionAttempted) DllImportEntry(EventPipeInternal_Enable) DllImportEntry(EventPipeInternal_Disable) DllImportEntry(EventPipeInternal_GetSessionInfo) From fb8f831e63f747cd4b3659c1c0ff8987fcfd8a61 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 7 Sep 2023 08:57:55 +0800 Subject: [PATCH 025/136] GetClrInstanceId --- .../Binder/Tracing/ResolutionAttemptedOperation.cs | 1 - ...RuntimeEventSource.Binder.NativeSinks.CoreCLR.cs | 8 ++++++-- src/coreclr/vm/eventpipeinternal.cpp | 13 +++++++++++++ src/coreclr/vm/eventpipeinternal.h | 2 ++ src/coreclr/vm/qcallentrypoints.cpp | 1 + 5 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index 9a8e2786075543..1ce3fcdbeac096 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -248,7 +248,6 @@ public void TraceStage(Stage stage, int hResult, Assembly? resultAssembly, strin } NativeRuntimeEventSource.Log.ResolutionAttempted( - 0, // GetClrInstanceId() _assemblyName, (ushort)stage, _assemblyLoadContextName, diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs index 6f40855dd2e7fc..bbe024c112818a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs @@ -12,9 +12,13 @@ namespace System.Diagnostics.Tracing // Currently the Binder events are only used by managed binder of CoreCLR. internal sealed unsafe partial class NativeRuntimeEventSource : EventSource { + [NonEvent] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_GetClrInstanceId")] + private static partial ushort GetClrInstanceId(); + [NonEvent] [MethodImpl(MethodImplOptions.NoInlining)] - public void ResolutionAttempted(ushort CLRInstanceId, + public void ResolutionAttempted( string AssemblyName, ushort Stage, string AssemblyLoadContext, @@ -25,7 +29,7 @@ public void ResolutionAttempted(ushort CLRInstanceId, { if (IsEnabled(EventLevel.Informational, Keywords.AssemblyLoaderKeyword)) { - ResolutionAttempted(CLRInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, null, null); + ResolutionAttempted(GetClrInstanceId(), AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, null, null); } } diff --git a/src/coreclr/vm/eventpipeinternal.cpp b/src/coreclr/vm/eventpipeinternal.cpp index 57cf10ff30a11f..14bf24db6438e9 100644 --- a/src/coreclr/vm/eventpipeinternal.cpp +++ b/src/coreclr/vm/eventpipeinternal.cpp @@ -282,4 +282,17 @@ extern "C" BOOL QCALLTYPE EventPipeInternal_WaitForSessionSignal(UINT64 sessionI return result; } +extern "C" uint16_t QCALLTYPE EventPipeInternal_GetClrInstanceId() +{ + QCALL_CONTRACT; + + uint16_t result; + BEGIN_QCALL; + + result = GetClrInstanceId(); + + END_QCALL; + return result; +} + #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/vm/eventpipeinternal.h b/src/coreclr/vm/eventpipeinternal.h index 1ecbb79162e84b..362b55c996c22b 100644 --- a/src/coreclr/vm/eventpipeinternal.h +++ b/src/coreclr/vm/eventpipeinternal.h @@ -94,6 +94,8 @@ extern "C" BOOL QCALLTYPE EventPipeInternal_WaitForSessionSignal( UINT64 sessionID, INT32 timeoutMs); +extern "C" uint16_t QCALLTYPE EventPipeInternal_GetClrInstanceId(); + #endif // FEATURE_PERFTRACING #endif // __EVENTPIPEINTERNAL_H__ diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 4b0e940c904f91..3a02731bbf42f8 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -294,6 +294,7 @@ static const Entry s_QCall[] = DllImportEntry(EventPipeInternal_GetNextEvent) DllImportEntry(EventPipeInternal_SignalSession) DllImportEntry(EventPipeInternal_WaitForSessionSignal) + DllImportEntry(EventPipeInternal_GetClrInstanceId) #endif #if defined(TARGET_UNIX) DllImportEntry(CloseHandle) From f71b1758cfaf76e148596b26d3eb072b0e109260 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 7 Sep 2023 21:07:26 +0800 Subject: [PATCH 026/136] KnownPathProbed event --- .../Runtime/Binder/AssemblyBinderCommon.cs | 10 +++-- .../Tracing/ResolutionAttemptedOperation.cs | 11 ++++++ ...eEventSource.Binder.NativeSinks.CoreCLR.cs | 38 +++++++++++++++++-- src/coreclr/scripts/genRuntimeEventSources.py | 2 + src/coreclr/vm/nativeeventsource.cpp | 10 +++++ src/coreclr/vm/nativeeventsource.h | 1 + src/coreclr/vm/qcallentrypoints.cpp | 1 + 7 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index b96120d654809a..6c7f9ac75f9ca9 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -4,9 +4,11 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.Tracing; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using System.Text; using Internal.Runtime.Binder.Tracing; @@ -416,6 +418,8 @@ private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyNam private static int BindAssemblyByProbingPaths(List bindingPaths, AssemblyName requestedAssemblyName, out Assembly? result) { + PathSource pathSource = PathSource.AppPaths; + // Loop through the binding paths looking for a matching assembly foreach (string bindingPath in bindingPaths) { @@ -425,13 +429,13 @@ private static int BindAssemblyByProbingPaths(List bindingPaths, Assembl string fileName = fileNameWithoutExtension + ".dll"; int hr = GetAssembly(fileName, isInTPA: false, out Assembly? assembly); - // BinderTracing::PathProbed(fileName, pathSource, hr); + NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); if (hr < 0) { fileName = fileNameWithoutExtension + ".exe"; hr = GetAssembly(fileName, isInTPA: false, out assembly); - // BinderTracing::PathProbed(fileName, pathSource, hr); + NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); } // Since we're probing, file not founds are ok and we should just try another @@ -513,7 +517,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN Debug.Assert(tpaFileName != null); int hr = GetAssembly(tpaFileName, isInTPA: true, out tpaAssembly); - // BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); + NativeRuntimeEventSource.Log.KnownPathProbed(tpaFileName, (ushort)PathSource.ApplicationAssemblies, hr); bindResult.SetAttemptResult(hr, tpaAssembly); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index 1ce3fcdbeac096..4198a4c502a535 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -257,4 +257,15 @@ public void TraceStage(Stage stage, int hResult, Assembly? resultAssembly, strin errorMsg); } } + + // This must match the BindingPathSource value map in ClrEtwAll.man + internal enum PathSource : ushort + { + ApplicationAssemblies, + Unused, + AppPaths, + PlatformResourceRoots, + SatelliteSubdirectory, + Bundle + }; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs index bbe024c112818a..4dcdf1eb680f6d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs @@ -35,7 +35,7 @@ public void ResolutionAttempted( [Event(292, Level = EventLevel.Informational, Message = "", Task = default, Opcode = default, Version = 0, Keywords = Keywords.AssemblyLoaderKeyword)] private unsafe void ResolutionAttempted( - ushort CLRInstanceId, + ushort ClrInstanceId, string AssemblyName, ushort Stage, string AssemblyLoadContext, @@ -46,13 +46,13 @@ private unsafe void ResolutionAttempted( Guid* ActivityId = null, Guid* RelatedActivityId = null) { - LogResolutionAttempted(CLRInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, ActivityId, RelatedActivityId); + LogResolutionAttempted(ClrInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, ActivityId, RelatedActivityId); } [NonEvent] [LibraryImport(RuntimeHelpers.QCall, StringMarshalling = StringMarshalling.Utf16)] private static partial void LogResolutionAttempted( - ushort CLRInstanceId, + ushort ClrInstanceId, string AssemblyName, ushort Stage, string AssemblyLoadContext, @@ -62,5 +62,37 @@ private static partial void LogResolutionAttempted( string ErrorMessage, Guid* ActivityId, Guid* RelatedActivityId); + + [NonEvent] + [MethodImpl(MethodImplOptions.NoInlining)] + public void KnownPathProbed(string FilePath, ushort Source, int Result) + { + if (IsEnabled(EventLevel.Informational, Keywords.AssemblyLoaderKeyword)) + { + KnownPathProbed(GetClrInstanceId(), FilePath, Source, Result); + } + } + + [Event(296, Level = EventLevel.Informational, Message = "", Task = default, Opcode = default, Version = 0, Keywords = Keywords.AssemblyLoaderKeyword)] + private unsafe void KnownPathProbed( + ushort ClrInstanceID, + string FilePath, + ushort Source, + int Result, + Guid* ActivityId = null, + Guid* RelatedActivityId = null) + { + LogKnownPathProbed(ClrInstanceID, FilePath, Source, Result, ActivityId, RelatedActivityId); + } + + [NonEvent] + [LibraryImport(RuntimeHelpers.QCall, StringMarshalling = StringMarshalling.Utf16)] + private static partial void LogKnownPathProbed( + ushort ClrInstanceId, + string FilePath, + ushort Source, + int Result, + Guid* ActivityId, + Guid* RelatedActivityId); } } diff --git a/src/coreclr/scripts/genRuntimeEventSources.py b/src/coreclr/scripts/genRuntimeEventSources.py index 0e0b6e338c8827..4ebcee8c7caed5 100644 --- a/src/coreclr/scripts/genRuntimeEventSources.py +++ b/src/coreclr/scripts/genRuntimeEventSources.py @@ -95,6 +95,8 @@ def generateEvent(eventNode, providerNode, outputFile, stringTable): # Fired by managed binder if "ResolutionAttempted" in symbol: return + if "KnownPathProbed" in symbol: + return evtLevel = eventNode.getAttribute("level")[4:] evtKeywords = "" diff --git a/src/coreclr/vm/nativeeventsource.cpp b/src/coreclr/vm/nativeeventsource.cpp index d4031022a2687a..c1dba3ef156de3 100644 --- a/src/coreclr/vm/nativeeventsource.cpp +++ b/src/coreclr/vm/nativeeventsource.cpp @@ -199,4 +199,14 @@ extern "C" void QCALLTYPE LogResolutionAttempted(uint16_t CLRInstanceId, LPCWSTR END_QCALL; } +extern "C" void QCALLTYPE LogKnownPathProbed(uint16_t CLRInstanceId, LPCWSTR FilePath, uint16_t Source, int32_t Result, LPCGUID ActivityId, LPCGUID RelatedActivityId) +{ + QCALL_CONTRACT; + BEGIN_QCALL; + + FireEtwKnownPathProbed(CLRInstanceId, FilePath, Source, Result, ActivityId, RelatedActivityId); + + END_QCALL; +} + #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/vm/nativeeventsource.h b/src/coreclr/vm/nativeeventsource.h index 182a2b973589b4..d4bc30040c7d81 100644 --- a/src/coreclr/vm/nativeeventsource.h +++ b/src/coreclr/vm/nativeeventsource.h @@ -32,6 +32,7 @@ extern "C" void QCALLTYPE LogContentionLockCreated(void* LockID, void* Associate extern "C" void QCALLTYPE LogContentionStart(uint8_t ContentionFlags, uint16_t ClrInstanceID, void* LockID, void* AssociatedObjectID, uint64_t LockOwnerThreadID); extern "C" void QCALLTYPE LogContentionStop(uint8_t ContentionFlags, uint16_t ClrInstanceID, double DurationNs); extern "C" void QCALLTYPE LogResolutionAttempted(uint16_t CLRInstanceId, LPCWSTR AssemblyName, uint16_t Stage, LPCWSTR AssemblyLoadContext, uint16_t Result, LPCWSTR ResultAssemblyName, LPCWSTR ResultAssemblyPath, LPCWSTR ErrorMessage, LPCGUID ActivityId, LPCGUID RelatedActivityId); +extern "C" void QCALLTYPE LogKnownPathProbed(uint16_t CLRInstanceId, LPCWSTR FilePath, uint16_t Source, int32_t Result, LPCGUID ActivityId, LPCGUID RelatedActivityId); #endif // defined(FEATURE_PERFTRACING) #endif //_NATIVEEVENTSOURCE_H_ diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 3a02731bbf42f8..2a0ac5df3787d6 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -282,6 +282,7 @@ static const Entry s_QCall[] = DllImportEntry(LogContentionStart) DllImportEntry(LogContentionStop) DllImportEntry(LogResolutionAttempted) + DllImportEntry(LogKnownPathProbed) DllImportEntry(EventPipeInternal_Enable) DllImportEntry(EventPipeInternal_Disable) DllImportEntry(EventPipeInternal_GetSessionInfo) From 1390d937ba0aced3125101731b63b4a925afd477 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 7 Sep 2023 23:06:33 +0800 Subject: [PATCH 027/136] Fix compilation --- src/coreclr/vm/eventpipeinternal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/eventpipeinternal.cpp b/src/coreclr/vm/eventpipeinternal.cpp index 14bf24db6438e9..8e7ac182078077 100644 --- a/src/coreclr/vm/eventpipeinternal.cpp +++ b/src/coreclr/vm/eventpipeinternal.cpp @@ -286,7 +286,7 @@ extern "C" uint16_t QCALLTYPE EventPipeInternal_GetClrInstanceId() { QCALL_CONTRACT; - uint16_t result; + uint16_t result = 0; BEGIN_QCALL; result = GetClrInstanceId(); From e13468a1dca1386949f096b997c7145cf955f62d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 7 Sep 2023 23:46:29 +0800 Subject: [PATCH 028/136] MdImport for AssemblyName --- .../Runtime/Binder/AssemblyBinderCommon.cs | 5 +- .../Internal/Runtime/Binder/AssemblyName.cs | 48 ++++++------------- .../src/System/Reflection/MdImport.cs | 32 +++++++++++++ src/coreclr/vm/ecalllist.h | 8 ++++ src/coreclr/vm/managedmdimport.cpp | 34 +++++++++++++ src/coreclr/vm/managedmdimport.hpp | 13 +++++ src/coreclr/vm/peimage.cpp | 40 ++++++++++++++++ src/coreclr/vm/peimage.h | 4 ++ 8 files changed, 148 insertions(+), 36 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 6c7f9ac75f9ca9..8b9a02779a372f 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -8,8 +8,6 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; using Internal.Runtime.Binder.Tracing; namespace Internal.Runtime.Binder @@ -33,6 +31,9 @@ internal struct BundleFileLocation internal static partial class AssemblyBinderCommon { + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern unsafe IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); + [LibraryImport("Foo", StringMarshalling = StringMarshalling.Utf8)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index ab82a6b2e5aef2..1d53978bae8b89 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -4,8 +4,6 @@ using System; using System.Diagnostics; using System.Numerics; -using System.Runtime.CompilerServices; -using System.Text; namespace Internal.Runtime.Binder { @@ -73,34 +71,30 @@ public AssemblyName(IntPtr pPEImage) AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE | AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL; int* dwPAFlags = stackalloc int[2]; - using IMdInternalImport pIMetaDataAssemblyImport = BinderAcquireImport(pPEImage, dwPAFlags); + IntPtr pIMetaDataAssemblyImport = AssemblyBinderCommon.BinderAcquireImport(pPEImage, dwPAFlags); + var scope = new System.Reflection.MetadataImport(pIMetaDataAssemblyImport, null); Architecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); // Get the assembly token - uint mda; - pIMetaDataAssemblyImport.GetAssemblyFromScope(&mda); + uint mda = scope.GetAssemblyFromScope(); AssemblyMetaDataInternal amd = default; - byte* pvPublicKeyToken = null; - uint dwPublicKeyToken = 0; - byte* pAssemblyName = null; - CorAssemblyFlags dwRefOrDefFlags = 0; - uint dwHashAlgId = 0; // Get name and metadata - pIMetaDataAssemblyImport.GetAssemblyProps( - mda, // [IN] The Assembly for which to get the properties. - &pvPublicKeyToken, // [OUT] Pointer to the PublicKeyToken blob. - &dwPublicKeyToken, // [OUT] Count of bytes in the PublicKeyToken Blob. - &dwHashAlgId, // [OUT] Hash Algorithm. - &pAssemblyName, // [OUT] Name. - &amd, // [OUT] Assembly MetaData. - &dwRefOrDefFlags // [OUT] Flags. - ); + scope.GetAssemblyProps( + mda, + out var pvPublicKeyToken, + out var dwPublicKeyToken, + out var dwHashAlgId, + out var assemblyName, + &amd, + out uint flags); + + CorAssemblyFlags dwRefOrDefFlags = (CorAssemblyFlags)flags; { - string culture = Encoding.UTF8.GetString(amd.szLocale, string.strlen(amd.szLocale)); + string culture = new MdUtf8String(amd.szLocale).ToString(); int index = culture.IndexOf(';'); if (index != -1) { @@ -112,8 +106,6 @@ public AssemblyName(IntPtr pPEImage) } { - string assemblyName = Encoding.UTF8.GetString(pAssemblyName, string.strlen(pAssemblyName)); - const int MAX_PATH_FNAME = 260; if (assemblyName.Length >= MAX_PATH_FNAME) { @@ -178,11 +170,6 @@ public AssemblyName(IntPtr pPEImage) public bool IsNeutralCulture => string.EqualsOrdinalIgnoreCase(CultureOrLanguage, NeutralCulture); - // Foo internal calls - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IMdInternalImport BinderAcquireImport(IntPtr pPEImage, int* dwPAFlags); - public override int GetHashCode() => GetHashCode(AssemblyNameIncludeFlags.INCLUDE_ALL); public int GetHashCode(AssemblyNameIncludeFlags dwIncludeFlags) @@ -368,11 +355,4 @@ public string GetDisplayName(AssemblyNameIncludeFlags dwIncludeFlags) return TextualIdentityParser.ToString(this, dwUseIdentityFlags); } } - - internal unsafe interface IMdInternalImport : IDisposable - { - public void GetAssemblyFromScope(uint* ptkAssembly); - - public void GetAssemblyProps(uint mda, byte** ppbPublicKey, uint* pcbPublicKey, uint* pulHashAlgId, byte** pszName, void* pMetadata, CorAssemblyFlags* pdwAsselblyFlags); - } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index 9b8ac3570d5bf8..85c75e741e2c8f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -551,6 +551,38 @@ public bool IsValidToken(int token) { return _IsValidToken(m_metadataImport2, token); } + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern void _GetAssemblyFromScope(IntPtr scope, out uint tkAssembly); + public uint GetAssemblyFromScope() + { + _GetAssemblyFromScope(m_metadataImport2, out uint tkAssembly); + return tkAssembly; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern unsafe void _GetAssemblyProps( + IntPtr scope, + uint mda, + out byte* ppbPublicKey, + out uint pcbPublicKey, + out uint pulHashAlgId, + void** pszName, + void* pMetadata, + out uint pdwAsselblyFlags); + public unsafe void GetAssemblyProps( + uint assemblyToken, + out byte* publicKey, + out uint publicKeyLength, + out uint hashAlgId, + out string assemblyName, + void* pMetadata, + out uint asselblyFlags) + { + void* _name; + _GetAssemblyProps(m_metadataImport2, assemblyToken, out publicKey, out publicKeyLength, out hashAlgId, &_name, pMetadata, out asselblyFlags); + assemblyName = new MdUtf8String(_name).ToString(); + } #endregion } diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index c8c83502cfbab2..a3280b5f8933fc 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -200,6 +200,9 @@ FCFuncStart(gMetaDataImport) FCFuncElement("_GetPInvokeMap", MetaDataImport::GetPinvokeMap) FCFuncElement("_IsValidToken", MetaDataImport::IsValidToken) FCFuncElement("_GetMarshalAs", MetaDataImport::GetMarshalAs) + + FCFuncElement("_GetAssemblyFromScope", MetaDataImport::GetAssemblyFromScope) + FCFuncElement("_GetAssemblyProps", MetaDataImport::GetAssemblyProps) FCFuncEnd() FCFuncStart(gSignatureNative) @@ -669,6 +672,10 @@ FCFuncStart(gComAwareWeakReferenceFuncs) FCFuncElement("HasInteropInfo", ComAwareWeakReferenceNative::HasInteropInfo) FCFuncEnd() +FCFuncStart(gAssemblyBinderCommonFuncs) + FCFuncElement("BinderAcquireImport", PEImage::ManagedBinderAcquireImport) +FCFuncEnd() + #ifdef FEATURE_COMINTEROP // @@ -771,6 +778,7 @@ FCClassElement("ValueType", "System", gValueTypeFuncs) FCClassElement("Variant", "System", gVariantFuncs) #endif FCClassElement("WaitHandle", "System.Threading", gWaitHandleFuncs) +FCClassElement("AssemblyBinderCommon", "Internal.Runtime.Binder", gAssemblyBinderCommonFuncs) #undef FCFuncElement #undef FCFuncElementSig diff --git a/src/coreclr/vm/managedmdimport.cpp b/src/coreclr/vm/managedmdimport.cpp index 622e74edb994d1..873ac8e0e30ec0 100644 --- a/src/coreclr/vm/managedmdimport.cpp +++ b/src/coreclr/vm/managedmdimport.cpp @@ -655,6 +655,40 @@ MDImpl2(void, MetaDataImport::GetMemberRefProps, } FCIMPLEND +MDImpl1(void, MetaDataImport::GetAssemblyFromScope, + mdAssembly* ptkAssembly) +{ + FCALL_CONTRACT; + + HRESULT hr; + IMDInternalImport *_pScope = pScope; + + hr = _pScope->GetAssemblyFromScope(ptkAssembly); + if (FAILED(hr)) + { + FCThrowVoid(kBadImageFormatException); + } +} +FCIMPLEND + +MDImpl7(void, MetaDataImport::GetAssemblyProps, + mdAssembly mda, + const void** ppbPublicKey, + ULONG* pcbPublicKey, + ULONG* pulHashAlgId, + LPCSTR* pszName, + AssemblyMetaDataInternal* pMetaData, + DWORD* pdwAsselblyFlags) +{ + FCALL_CONTRACT; + + HRESULT hr; + IMDInternalImport *_pScope = pScope; + + hr = _pScope->GetAssemblyProps(mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, pszName, pMetaData, pdwAsselblyFlags); +} +FCIMPLEND + #if defined(_MSC_VER) && defined(TARGET_X86) #pragma optimize("", on) // restore command line optimization defaults #endif diff --git a/src/coreclr/vm/managedmdimport.hpp b/src/coreclr/vm/managedmdimport.hpp index 72e3703c376d46..025ee60d230d1d 100644 --- a/src/coreclr/vm/managedmdimport.hpp +++ b/src/coreclr/vm/managedmdimport.hpp @@ -113,6 +113,19 @@ class MetaDataImport STRINGREF* marshalType, STRINGREF* marshalCookie, INT32* iidParamIndex); + + //// + //// Assembly + //// + MDDecl1(void, GetAssemblyFromScope, mdAssembly* ptkAssembly); + MDDecl7(void, GetAssemblyProps, + mdAssembly mda, + const void** ppbPublicKey, + ULONG* pcbPublicKey, + ULONG* pulHashAlgId, + LPCSTR* pszName, + AssemblyMetaDataInternal* pMetaData, + DWORD* pdwAsselblyFlags); }; #endif diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index 656b42b8111c70..a355c88ab6ed7a 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -915,3 +915,43 @@ BOOL PEImage::IsPtrInImage(PTR_CVOID data) return FALSE; } + +#ifndef DACCESS_COMPILE +FCIMPL2(IMDInternalImport*, PEImage::ManagedBinderAcquireImport, PEImage* pPEImage, DWORD* pdwPAFlags) +{ + FCALL_CONTRACT; + + _ASSERTE(pPEImage != NULL); + _ASSERTE(pdwPAFlags != NULL); + + IMDInternalImport* ret = NULL; + + // The same logic of BinderAcquireImport + + HELPER_METHOD_FRAME_BEGIN_RET_0(); + + PEImageLayout* pLayout = pPEImage->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); + + // CheckCorHeader includes check of NT headers too + if (!pLayout->CheckCorHeader()) + ThrowHR(COR_E_ASSEMBLYEXPECTED); + + if (!pLayout->CheckFormat()) + ThrowHR(COR_E_BADIMAGEFORMAT); + + pPEImage->GetPEKindAndMachine(&pdwPAFlags[0], &pdwPAFlags[1]); + + ret = pPEImage->GetMDImport(); + if (!ret) + { + ThrowHR(COR_E_BADIMAGEFORMAT); + } + + // No AddRef + + HELPER_METHOD_FRAME_END(); + + return ret; +} +FCIMPLEND +#endif // DACCESS_COMPILE diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index e7bfc11d319f12..ee06e9e6730f00 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -264,6 +264,10 @@ class PEImage final static IJWFixupData* GetIJWData(void* pBase); static PTR_LoaderHeap GetDllThunkHeap(void* pBase); static void UnloadIJWModule(void* pBase); + +#ifndef DACCESS_COMPILE + static FCDECL2(IMDInternalImport*, ManagedBinderAcquireImport, PEImage*, DWORD*); +#endif private: From 6196fbe7ac9346f12a0304927bd4a16f9b01522e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 00:07:57 +0800 Subject: [PATCH 029/136] AssemblyNameData --- .../src/Internal/Runtime/Binder/Assembly.cs | 2 +- .../Internal/Runtime/Binder/AssemblyBinder.cs | 20 ++++++++++ .../Runtime/Binder/AssemblyBinderCommon.cs | 6 +-- .../Runtime/Binder/AssemblyIdentity.cs | 2 +- .../Internal/Runtime/Binder/AssemblyName.cs | 37 +++++++++++++++++-- .../Runtime/Binder/TextualIdentityParser.cs | 2 +- 6 files changed, 60 insertions(+), 9 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index c34247da51d65f..588f4d8f99f818 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -29,7 +29,7 @@ public Assembly(nint pPEImage, bool isInTPA) }; // validate architecture - if (!AssemblyBinderCommon.IsValidArchitecture(AssemblyName.Architecture)) + if (!AssemblyBinderCommon.IsValidArchitecture(AssemblyName.ProcessorArchitecture)) { // Assembly image can't be executed on this platform throw new BadImageFormatException(); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index c320cde12daa52..456c2a97b24782 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -3,6 +3,26 @@ namespace Internal.Runtime.Binder { + // System.Reflection.TypeLoading.AssemblyNameData + internal unsafe readonly struct AssemblyNameData + { + public readonly void* Name; + public readonly void* Culture; + + public readonly byte* PublicKeyOrToken; + public readonly int PublicKeyOrTokenLength; + + public readonly int MajorVersion; + public readonly int MinorVersion; + public readonly int BuildNumber; + public readonly int RevisionNumber; + + public readonly PEKind ProcessorArchitecture; + public readonly System.Reflection.AssemblyContentType ContentType; + + public readonly AssemblyIdentityFlags IdentityFlags; + } + internal abstract class AssemblyBinder { public abstract ApplicationContext AppContext { get; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 8b9a02779a372f..4631812085f294 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -268,7 +268,7 @@ private static int BindByName( } } - if (!IsValidArchitecture(assemblyName.Architecture)) + if (!IsValidArchitecture(assemblyName.ProcessorArchitecture)) { // Assembly reference contains wrong architecture hr = HResults.FUSION_E_INVALID_NAME; @@ -382,7 +382,7 @@ private static int FindInExecutionContext(ApplicationContext applicationContext, return HResults.S_FALSE; if (assembly != null && assemblyName.IsDefinition - && (assembly.AssemblyName.Architecture != assemblyName.Architecture)) + && (assembly.AssemblyName.ProcessorArchitecture != assemblyName.ProcessorArchitecture)) { return FUSION_E_APP_DOMAIN_LOCKED; } @@ -407,7 +407,7 @@ private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyNam } } - if (requestedAssemblyName.Architecture != PEKind.None) + if (requestedAssemblyName.ProcessorArchitecture != PEKind.None) { includeFlags |= AssemblyNameIncludeFlags.INCLUDE_ARCHITECTURE; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs index 10d9d5f91be879..e1820e680ab199 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs @@ -39,7 +39,7 @@ internal class AssemblyIdentity public AssemblyVersion Version = new AssemblyVersion(); public string CultureOrLanguage = string.Empty; public byte[] PublicKeyOrTokenBLOB = Array.Empty(); - public PEKind Architecture; + public PEKind ProcessorArchitecture; public AssemblyContentType ContentType; public AssemblyIdentityFlags IdentityFlags; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 1d53978bae8b89..adb6798132eb2c 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -74,7 +74,7 @@ public AssemblyName(IntPtr pPEImage) IntPtr pIMetaDataAssemblyImport = AssemblyBinderCommon.BinderAcquireImport(pPEImage, dwPAFlags); var scope = new System.Reflection.MetadataImport(pIMetaDataAssemblyImport, null); - Architecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); + ProcessorArchitecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); // Get the assembly token uint mda = scope.GetAssemblyFromScope(); @@ -165,6 +165,37 @@ public AssemblyName(IntPtr pPEImage) } } + public AssemblyName(in AssemblyNameData data) + { + AssemblyIdentityFlags flags = data.IdentityFlags; + SimpleName = new MdUtf8String(data.Name).ToString(); + Version = new AssemblyVersion + { + Major = data.MajorVersion, + Minor = data.MinorVersion, + Build = data.BuildNumber, + Revision = data.RevisionNumber + }; + CultureOrLanguage = new MdUtf8String(data.Culture).ToString(); + + PublicKeyOrTokenBLOB = new ReadOnlySpan(data.PublicKeyOrToken, data.PublicKeyOrTokenLength).ToArray(); + if ((flags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0) + { + // Convert public key to token + + byte[]? publicKeyToken = System.Reflection.AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrTokenBLOB); + Debug.Assert(publicKeyToken != null); + + PublicKeyOrTokenBLOB = publicKeyToken; + flags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY; + flags |= AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN; + } + + ProcessorArchitecture = data.ProcessorArchitecture; + ContentType = data.ContentType; + IdentityFlags = flags; + } + // TODO: Is this simple comparison enough? public bool IsCoreLib => string.EqualsOrdinalIgnoreCase(SimpleName, CoreLib.Name); @@ -267,7 +298,7 @@ static uint HashBytes(ReadOnlySpan bytes) if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PROCESSOR_ARCHITECTURE) != 0) { - dwHash ^= (uint)Architecture; + dwHash ^= (uint)ProcessorArchitecture; dwHash = BitOperations.RotateLeft(dwHash, 4); } @@ -313,7 +344,7 @@ public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFl if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_ARCHITECTURE) != 0)) { - fEquals = Architecture == other.Architecture; + fEquals = ProcessorArchitecture == other.ProcessorArchitecture; } if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_VERSION) != 0)) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs index 92238f4e4000a6..f482b98a9623e5 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs @@ -57,7 +57,7 @@ public static string ToString(AssemblyIdentity pAssemblyIdentity, AssemblyIdenti if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PROCESSOR_ARCHITECTURE) != 0) { textualIdentity.Append(", processorArchitecture="); - textualIdentity.Append(pAssemblyIdentity.Architecture switch + textualIdentity.Append(pAssemblyIdentity.ProcessorArchitecture switch { PEKind.I386 => "x86", PEKind.IA64 => "IA64", From c459c76a89ecb836779e453cff6e6eb091f61aab Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 00:43:16 +0800 Subject: [PATCH 030/136] Basic AssemblyBinder --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 189 +++++++++++++++++- 1 file changed, 188 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 456c2a97b24782..99bbc09e0f5ac4 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -1,6 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + namespace Internal.Runtime.Binder { // System.Reflection.TypeLoading.AssemblyNameData @@ -25,6 +30,188 @@ internal unsafe readonly struct AssemblyNameData internal abstract class AssemblyBinder { - public abstract ApplicationContext AppContext { get; } + public int BindAssemblyByName(in AssemblyNameData pAssemblyNameData, out Assembly assembly) + { + return BindUsingAssemblyName(new AssemblyName(pAssemblyNameData), out assembly); + } + + public abstract int BindUsingPEImage(IntPtr pPEImage, bool excludeAppPaths, out Assembly assembly); + + public abstract int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly assembly); + + /// + /// Get LoaderAllocator for binders that contain it. For other binders, return NULL. + /// + public abstract System.Reflection.LoaderAllocator? GetLoaderAllocator(); + + public abstract bool IsDefault { get; } + + public ApplicationContext AppContext { get; } + + // A GC handle to the managed AssemblyLoadContext. + // It is a long weak handle for collectible AssemblyLoadContexts and strong handle for non-collectible ones. + public GCHandle ManagedAssemblyLoadContext { get; set; } + + // NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); + + public void AddLoadedAssembly(IVMAssembly loadedAssembly) + { + // BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); + // TODO: is the lock shared outside this type? + lock (_loadLock) + { + _loadedAssemblies.Add(loadedAssembly); + + // #ifdef FEATURE_READYTORUN + DeclareLoadedAssembly(loadedAssembly); + // #endif // FEATURE_READYTORUN + } + } + + // void GetNameForDiagnostics(/*out*/ SString& alcName); + // + // static void GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName); + // static void GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ SString& alcName); + + //# ifdef FEATURE_READYTORUN + + private static void MvidMismatchFatalError(Guid mvidActual, Guid mvidExpected, string simpleName, bool compositeComponent, string assemblyRequirementName) + { + string message; + + if (compositeComponent) + { + message = $"MVID mismatch between loaded assembly '{simpleName}' (MVID = {mvidActual}) and an assembly with the same simple name embedded in the native image '{assemblyRequirementName}' (MVID = {mvidExpected})"; + } + else + { + message = $"MVID mismatch between loaded assembly '{simpleName}' (MVID = {mvidActual}) and version of assembly '{simpleName}' expected by assembly '{assemblyRequirementName}' (MVID = {mvidExpected})"; + } + + Environment.FailFast(message); + } + + // Must be called under the LoadLock + public void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool compositeComponent, string imageName) + { + // If the table is empty, then we didn't fill it with all the loaded assemblies as they were loaded. Record this detail, and fix after adding the dependency + bool addAllLoadedModules = false; + if (_assemblySimpleNameMvidCheckHash.Count == 0) + { + addAllLoadedModules = true; + } + + ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrNullRef(_assemblySimpleNameMvidCheckHash, simpleName); + if (Unsafe.IsNullRef(ref entry)) + { + entry = new SimpleNameToExpectedMVIDAndRequiringAssembly + { + Mvid = mvid, + CompositeComponent = compositeComponent, + AssemblyRequirementName = imageName + }; + } + else + { + // Elem already exists. Determine if the existing elem is another one with the same mvid, in which case just record that a dependency is in play. + // If the existing elem has a different mvid, fail. + if (entry.Mvid == mvid) + { + // Mvid matches exactly. + if (entry.AssemblyRequirementName == null) + { + entry.AssemblyRequirementName = imageName; + entry.CompositeComponent = compositeComponent; + } + else + { + MvidMismatchFatalError(entry.Mvid, mvid, simpleName, compositeComponent, imageName); + } + } + } + + if (addAllLoadedModules) + { + foreach (IVMAssembly assembly in _loadedAssemblies) + { + DeclareLoadedAssembly(assembly); + } + } + } + + // Must be called under the LoadLock + private void DeclareLoadedAssembly(IVMAssembly loadedAssembly) + { + // If table is empty, then no mvid dependencies have been declared, so we don't need to record this information + if (_assemblySimpleNameMvidCheckHash.Count == 0) + { + return; + } + + loadedAssembly.GetMDImport().GetScopeProps(out Guid mvid); + string simpleName = loadedAssembly.SimpleName; + + ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrNullRef(_assemblySimpleNameMvidCheckHash, simpleName); + if (Unsafe.IsNullRef(ref entry)) + { + entry = new SimpleNameToExpectedMVIDAndRequiringAssembly + { + Mvid = mvid, + CompositeComponent = false, + AssemblyRequirementName = null + }; + } + else + { + // Elem already exists. Determine if the existing elem is another one with the same mvid, in which case do nothing. Everything is fine here. + // If the existing elem has a different mvid, but isn't a dependency on exact mvid elem, then set the mvid to all 0. + // If the existing elem has a different mvid, and is a dependency on exact mvid elem, then we've hit a fatal error. + if (entry.Mvid == mvid) + { + // Mvid matches exactly. + } + else if (entry.AssemblyRequirementName == null) + { + // Another loaded assembly, set the stored Mvid to all zeroes to indicate that it isn't a unique mvid + entry.Mvid = Guid.Empty; + } + else + { + MvidMismatchFatalError(entry.Mvid, mvid, simpleName, entry.CompositeComponent, entry.AssemblyRequirementName); + } + } + } + //#endif // FEATURE_READYTORUN + + private struct SimpleNameToExpectedMVIDAndRequiringAssembly + { + // When an assembly is loaded, this Mvid value will be set to the mvid of the assembly. If there are multiple assemblies + // with different mvid's loaded with the same simple name, then the Mvid value will be set to all zeroes. + public Guid Mvid; + + // If an assembly of this simple name is not yet loaded, but a depedency on an exact mvid is registered, then this field will + // be filled in with the simple assembly name of the first assembly loaded with an mvid dependency. + public string? AssemblyRequirementName; + + // To disambiguate between component images of a composite image and requirements from a non-composite --inputbubble assembly, use this bool + public bool CompositeComponent; + } + + // Use a case senstive comparison here even though + // assembly name matching should be case insensitive. Case insensitive + // comparisons are slow and have throwing scenarios, and this hash table + // provides a best-effort match to prevent problems, not perfection + private readonly Dictionary _assemblySimpleNameMvidCheckHash = new Dictionary(); + private readonly List _loadedAssemblies = new List(); + + private static readonly object _loadLock = new object(); + } + + // Foo + internal interface IVMAssembly // coreclr/vm/assembly + { + public System.Reflection.MetadataImport GetMDImport(); + + public string SimpleName { get; } } } From be6ec57c655afa654625b5c4d6fc15086bae2898 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 02:26:45 +0800 Subject: [PATCH 031/136] DefaultAssemblyBinder and BindUsingHostAssemblyResolver --- .../System.Private.CoreLib.csproj | 1 + .../src/Internal/Runtime/Binder/Assembly.cs | 2 +- .../Internal/Runtime/Binder/AssemblyBinder.cs | 8 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 234 +++++++++++++++++- .../Runtime/Binder/DefaultAssemblyBinder.cs | 89 +++++++ .../Tracing/ResolutionAttemptedOperation.cs | 8 +- .../Loader/AssemblyLoadContext.CoreCLR.cs | 8 +- .../Runtime/Loader/AssemblyLoadContext.cs | 5 +- 8 files changed, 339 insertions(+), 16 deletions(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 3a215cb8af4065..53c5cfb295a840 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -127,6 +127,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 588f4d8f99f818..305f48ec8c7cb0 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -14,7 +14,7 @@ internal sealed class Assembly public AssemblyName AssemblyName { get; } - // private IntPtr _pBinder; // PTR_AssemblyBinder + public AssemblyBinder? Binder { get; set; } public bool IsInTPA { get; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 99bbc09e0f5ac4..eb245cfcf62ee0 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -9,7 +9,7 @@ namespace Internal.Runtime.Binder { // System.Reflection.TypeLoading.AssemblyNameData - internal unsafe readonly struct AssemblyNameData + internal readonly unsafe struct AssemblyNameData { public readonly void* Name; public readonly void* Culture; @@ -30,14 +30,14 @@ internal unsafe readonly struct AssemblyNameData internal abstract class AssemblyBinder { - public int BindAssemblyByName(in AssemblyNameData pAssemblyNameData, out Assembly assembly) + public int BindAssemblyByName(in AssemblyNameData pAssemblyNameData, out Assembly? assembly) { return BindUsingAssemblyName(new AssemblyName(pAssemblyNameData), out assembly); } public abstract int BindUsingPEImage(IntPtr pPEImage, bool excludeAppPaths, out Assembly assembly); - public abstract int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly assembly); + public abstract int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly); /// /// Get LoaderAllocator for binders that contain it. For other binders, return NULL. @@ -46,7 +46,7 @@ public int BindAssemblyByName(in AssemblyNameData pAssemblyNameData, out Assembl public abstract bool IsDefault { get; } - public ApplicationContext AppContext { get; } + public ApplicationContext AppContext { get; } = new ApplicationContext(); // A GC handle to the managed AssemblyLoadContext. // It is a long weak handle for collectible AssemblyLoadContexts and strong handle for non-collectible ones. diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 4631812085f294..e0233afb3219a7 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -8,6 +8,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Loader; using Internal.Runtime.Binder.Tracing; namespace Internal.Runtime.Binder @@ -34,6 +35,8 @@ internal static partial class AssemblyBinderCommon [MethodImpl(MethodImplOptions.InternalCall)] public static extern unsafe IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); + // Foo + [LibraryImport("Foo", StringMarshalling = StringMarshalling.Utf8)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); @@ -43,6 +46,21 @@ internal static partial class AssemblyBinderCommon [MethodImpl(MethodImplOptions.InternalCall)] private static extern void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool PEAssembly_HasHostAssembly(IntPtr pPEAssembly); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern Assembly PEAssembly_GetHostAssembly(IntPtr pPEAssembly); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern System.Reflection.LoaderAllocator DomainAssembly_GetLoaderAllocator(IntPtr pDomainAssembly); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern System.Reflection.LoaderAllocator LoaderAllocator_EnsureReference(System.Reflection.LoaderAllocator LA, System.Reflection.LoaderAllocator pOtherLA); + public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; @@ -198,7 +216,7 @@ public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, ApplicationContext applicationContext = binder.AppContext; // Tracing happens outside the binder lock to avoid calling into managed code within the lock - using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, managedALC: 0, ref hr); + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, pManagedALC: default, ref hr); Retry: lock (applicationContext.ContextCriticalSection) @@ -740,7 +758,217 @@ private static int OtherBindInterferred(ApplicationContext applicationContext, B return HResults.S_FALSE; } - // BindUsingHostAssemblyResolver + public static int BindUsingHostAssemblyResolver( + GCHandle pManagedAssemblyLoadContextToBindWithin, + AssemblyName assemblyName, + DefaultAssemblyBinder? defaultBinder, + AssemblyBinder binder, + out Assembly? loadedAssembly) + { + int hr = HResults.E_FAIL; + loadedAssembly = null; + Assembly? resolvedAssembly = null; + + Debug.Assert(pManagedAssemblyLoadContextToBindWithin.IsAllocated); + + // body of RuntimeInvokeHostAssemblyResolver + bool fResolvedAssembly = false; + System.Reflection.Assembly? refLoadedAssembly = null; + using var tracer = new ResolutionAttemptedOperation(assemblyName, null, pManagedAssemblyLoadContextToBindWithin, ref hr); + + // Allocate an AssemblyName managed object + System.Reflection.AssemblyName refAssemblyName; + + // Initialize the AssemblyName object + // AssemblySpec::InitializeAssemblyNameRef + unsafe + { + string culture = string.Empty; + + if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) + { + culture = assemblyName.IsNeutralCulture ? string.Empty : assemblyName.CultureOrLanguage; + } + + fixed (char* pName = assemblyName.SimpleName) + fixed (char* pCulture = culture) + fixed (byte* pPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB) + { + var nativeAssemblyNameParts = new System.Reflection.NativeAssemblyNameParts + { + _pName = pName, + _pCultureName = pCulture, + _major = (ushort)assemblyName.Version.Major, + _minor = (ushort)assemblyName.Version.Minor, + _build = (ushort)assemblyName.Version.Build, + _revision = (ushort)assemblyName.Version.Revision, + _pPublicKeyOrToken = pPublicKeyOrToken, + _cbPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB.Length, + }; + + if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0) + nativeAssemblyNameParts._flags |= System.Reflection.AssemblyNameFlags.PublicKey; + + // Architecture unused + + // Retargetable + if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE) != 0) + nativeAssemblyNameParts._flags |= System.Reflection.AssemblyNameFlags.Retargetable; + + // Content type unused + + refAssemblyName = new System.Reflection.AssemblyName(&nativeAssemblyNameParts); + } + } + + bool isSatelliteAssemblyRequest = !assemblyName.IsNeutralCulture; + try + { + if (defaultBinder != null) + { + // Step 2 (of CustomAssemblyBinder::BindAssemblyByName) - Invoke Load method + // This is not invoked for TPA Binder since it always returns NULL. + tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextLoad); + + refLoadedAssembly = AssemblyLoadContext.Resolve((IntPtr)pManagedAssemblyLoadContextToBindWithin, refAssemblyName); + if (refLoadedAssembly != null) + { + fResolvedAssembly = true; + } + + hr = fResolvedAssembly ? HResults.S_OK : HResults.COR_E_FILENOTFOUND; + + // Step 3 (of CustomAssemblyBinder::BindAssemblyByName) + if (!fResolvedAssembly && !isSatelliteAssemblyRequest) + { + tracer.GoToStage(ResolutionAttemptedOperation.Stage.DefaultAssemblyLoadContextFallback); + + // If we could not resolve the assembly using Load method, then attempt fallback with TPA Binder. + // Since TPA binder cannot fallback to itself, this fallback does not happen for binds within TPA binder. + + hr = defaultBinder.BindUsingAssemblyName(assemblyName, out Assembly? coreCLRFoundAssembly); + if (hr >= 0) + { + Debug.Assert(coreCLRFoundAssembly != null); + resolvedAssembly = coreCLRFoundAssembly; + fResolvedAssembly = true; + } + } + } + + if (!fResolvedAssembly && isSatelliteAssemblyRequest) + { + // Step 4 (of CustomAssemblyBinder::BindAssemblyByName) + + // Attempt to resolve it using the ResolveSatelliteAssembly method. + tracer.GoToStage(ResolutionAttemptedOperation.Stage.ResolveSatelliteAssembly); + + refLoadedAssembly = AssemblyLoadContext.ResolveSatelliteAssembly((IntPtr)pManagedAssemblyLoadContextToBindWithin, refAssemblyName); + if (refLoadedAssembly != null) + { + // Set the flag indicating we found the assembly + fResolvedAssembly = true; + } + + hr = fResolvedAssembly ? HResults.S_OK : HResults.COR_E_FILENOTFOUND; + } + + if (!fResolvedAssembly) + { + // Step 5 (of CustomAssemblyBinder::BindAssemblyByName) + + // If we couldn't resolve the assembly using TPA LoadContext as well, then + // attempt to resolve it using the Resolving event. + tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextResolvingEvent); + + refLoadedAssembly = AssemblyLoadContext.ResolveUsingResolvingEvent((IntPtr)pManagedAssemblyLoadContextToBindWithin, refAssemblyName); + if (refLoadedAssembly != null) + { + // Set the flag indicating we found the assembly + fResolvedAssembly = true; + } + + hr = fResolvedAssembly ? HResults.S_OK : HResults.COR_E_FILENOTFOUND; + } + + if (fResolvedAssembly && resolvedAssembly == null) + { + // If we are here, assembly was successfully resolved via Load or Resolving events. + + // We were able to get the assembly loaded. Now, get its name since the host could have + // performed the resolution using an assembly with different name. + + System.Reflection.RuntimeAssembly? rtAssembly = + AssemblyLoadContext.GetRuntimeAssembly(refLoadedAssembly) + ?? throw new InvalidOperationException(SR.Arg_MustBeRuntimeAssembly); + + IntPtr pDomainAssembly = rtAssembly.GetUnderlyingNativeHandle(); + IntPtr pLoadedPEAssembly = IntPtr.Zero; + bool fFailLoad = false; + if (pDomainAssembly == IntPtr.Zero) + { + // Reflection emitted assemblies will not have a domain assembly. + fFailLoad = true; + } + else + { + pLoadedPEAssembly = DomainAssembly_GetPEAssembly(pDomainAssembly); + if (!PEAssembly_HasHostAssembly(pLoadedPEAssembly)) + { + // Reflection emitted assemblies will not have a domain assembly. + fFailLoad = true; + } + } + + // The loaded assembly's BINDER_SPACE::Assembly* is saved as HostAssembly in PEAssembly + if (fFailLoad) + { + // string name = assemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_ALL); + throw new InvalidOperationException("Dynamically emitted assemblies are unsupported during host-based resolution."); // IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED + } + + // For collectible assemblies, ensure that the parent loader allocator keeps the assembly's loader allocator + // alive for all its lifetime. + if (rtAssembly.IsCollectible) + { + System.Reflection.LoaderAllocator resultAssemblyLoaderAllocator = DomainAssembly_GetLoaderAllocator(pDomainAssembly); + System.Reflection.LoaderAllocator? parentLoaderAllocator = binder.GetLoaderAllocator(); + if (parentLoaderAllocator == null) + { + // The AssemblyLoadContext for which we are resolving the Assembly is not collectible. + throw new NotSupportedException(SR.NotSupported_CollectibleBoundNonCollectible); + } + + Debug.Assert(resultAssemblyLoaderAllocator != null); + LoaderAllocator_EnsureReference(parentLoaderAllocator, resultAssemblyLoaderAllocator); + } + + resolvedAssembly = PEAssembly_GetHostAssembly(pLoadedPEAssembly); + } + + if (fResolvedAssembly) + { + Debug.Assert(resolvedAssembly != null); + + // Get the BINDER_SPACE::Assembly reference to return back to. + loadedAssembly = resolvedAssembly; + hr = HResults.S_OK; + + tracer.SetFoundAssembly(resolvedAssembly); + } + else + { + hr = HResults.COR_E_FILENOTFOUND; + } + } + catch (Exception ex) + { + tracer.SetException(ex); + throw; + } + + return hr; + } public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) { @@ -754,7 +982,7 @@ public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyN ApplicationContext applicationContext = binder.AppContext; // Tracing happens outside the binder lock to avoid calling into managed code within the lock - using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, managedALC: 0, ref hr); + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, pManagedALC: default, ref hr); Retry: bool mvidMismatch = false; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs new file mode 100644 index 00000000000000..f9d306d3d2558b --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs @@ -0,0 +1,89 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.Loader; + +namespace Internal.Runtime.Binder +{ + internal sealed class DefaultAssemblyBinder : AssemblyBinder + { + // TODO: AdHoc + internal static DefaultAssemblyBinder Default { get; } = new DefaultAssemblyBinder(); + + public override bool IsDefault => true; + + // Helper functions + private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly, bool excludeAppPaths) + { + // CoreLib should be bound using BindToSystem + Debug.Assert(!assemblyName.IsCoreLib); + + int hr = AssemblyBinderCommon.BindAssembly(this, assemblyName, excludeAppPaths, out coreCLRFoundAssembly); + + if (hr >= 0) + { + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder = this; + } + + return hr; + } + + public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) + { + assembly = null; + + int hr = BindAssemblyByNameWorker(assemblyName, out Assembly? coreCLRFoundAssembly, excludeAppPaths: false); + + if (hr is HResults.E_FILENOTFOUND or AssemblyBinderCommon.FUSION_E_APP_DOMAIN_LOCKED or HResults.FUSION_E_REF_DEF_MISMATCH) + { + // If we are here, one of the following is possible: + // + // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR + // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def + // mismatch (either due to version difference or strong-name difference). + // + // Attempt to resolve the assembly via managed ALC instance. This can either fail the bind or return reference to an existing + // assembly that has been loaded + GCHandle pManagedAssemblyLoadContext = ManagedAssemblyLoadContext; + if (!pManagedAssemblyLoadContext.IsAllocated) + { + // For satellite assemblies, the managed ALC has additional resolution logic (defined by the runtime) which + // should be run even if the managed default ALC has not yet been used. (For non-satellite assemblies, any + // additional logic comes through a user-defined event handler which would have initialized the managed ALC, + // so if the managed ALC is not set yet, there is no additional logic to run) + if (!assemblyName.IsNeutralCulture) + { + // Make sure the managed default ALC is initialized. + AssemblyLoadContext.InitializeDefaultContext(); + } + + pManagedAssemblyLoadContext = ManagedAssemblyLoadContext; + Debug.Assert(pManagedAssemblyLoadContext.IsAllocated); + } + + if (pManagedAssemblyLoadContext.IsAllocated) + { + hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, assemblyName, null, this, out coreCLRFoundAssembly); + + if (hr >= 0) + { + // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. + // In such a case, we will not overwrite the binding context (which would be wrong since it would not + // be present in the cache of the current binding context). + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder ??= this; + } + } + } + + if (hr >= 0) + assembly = coreCLRFoundAssembly; + + return hr; + } + } +} diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index 4198a4c502a535..ae4ca5e9924e8b 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -5,6 +5,8 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Loader; namespace Internal.Runtime.Binder.Tracing { @@ -66,14 +68,14 @@ internal static bool IsEnabled() } // One of native bindContext or binder is expected to be non-zero. If the managed ALC is set, binder is ignored. - public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? binder, IntPtr managedALC, ref int hResult) + public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? binder, GCHandle pManagedALC, ref int hResult) { _hr = ref hResult; _stage = Stage.NotYetStarted; _tracingEnabled = IsEnabled(); _assemblyNameObject = assemblyName; - Debug.Assert(binder != null || managedALC != 0); + Debug.Assert(binder != null || pManagedALC.IsAllocated); if (!_tracingEnabled) return; @@ -83,7 +85,7 @@ public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? if (_assemblyNameObject != null) _assemblyName = _assemblyNameObject.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); - if (managedALC != 0) + if (pManagedALC.Target is AssemblyLoadContext managedALC) { // AssemblyBinder::GetNameForDiagnosticsFromManagedALC(managedALC, m_assemblyLoadContextName); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index b3b05a381218c4..c189daff85b05a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -103,7 +103,7 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) // This method is invoked by the VM to resolve a satellite assembly reference // after trying assembly resolution via Load override without success. - private static Assembly? ResolveSatelliteAssembly(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + internal static Assembly? ResolveSatelliteAssembly(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) { AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; @@ -129,7 +129,7 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass // This method is invoked by the VM to resolve an assembly reference using the Resolving event // after trying assembly resolution via Load override and TPA load context without success. - private static Assembly? ResolveUsingResolvingEvent(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + internal static Assembly? ResolveUsingResolvingEvent(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) { AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; // Invoke the AssemblyResolve event callbacks if wired up @@ -179,7 +179,7 @@ public void StartProfileOptimization(string? profile) InternalStartProfile(profile, _nativeAssemblyLoadContext); } - private static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) + internal static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) { return asm == null ? null : @@ -215,7 +215,7 @@ private static void StopAssemblyLoad(ref Guid activityId) /// /// Called by the runtime to make sure the default ALC is initialized /// - private static void InitializeDefaultContext() + internal static void InitializeDefaultContext() { _ = Default; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 59123e42fb52a2..c579a9c5b5d98d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -102,6 +102,9 @@ private protected AssemblyLoadContext(bool representsTPALoadContext, bool isColl var thisHandlePtr = GCHandle.ToIntPtr(thisHandle); _nativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, representsTPALoadContext, isCollectible); + // TODO: AdHoc + Internal.Runtime.Binder.DefaultAssemblyBinder.Default.ManagedAssemblyLoadContext = thisHandle; + // Add this instance to the list of alive ALC Dictionary> allContexts = AllContexts; lock (allContexts) @@ -609,7 +612,7 @@ public void Dispose() #if !NATIVEAOT // This method is invoked by the VM when using the host-provided assembly load context // implementation. - private static Assembly? Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + internal static Assembly? Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) { AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; From 0c74a2a072b52b7d31cd75fffe6224aebe4608a1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 02:51:10 +0800 Subject: [PATCH 032/136] Complete most of DefaltAssemblyBinder --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 2 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 1 + .../Runtime/Binder/DefaultAssemblyBinder.cs | 66 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index eb245cfcf62ee0..c32a3654692d4f 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -35,7 +35,7 @@ public int BindAssemblyByName(in AssemblyNameData pAssemblyNameData, out Assembl return BindUsingAssemblyName(new AssemblyName(pAssemblyNameData), out assembly); } - public abstract int BindUsingPEImage(IntPtr pPEImage, bool excludeAppPaths, out Assembly assembly); + public abstract int BindUsingPEImage(IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly); public abstract int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index e0233afb3219a7..c3e963159da172 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -206,6 +206,7 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) public const int CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH = unchecked((int)0x80132001); public const int CLR_E_BIND_ASSEMBLY_NOT_FOUND = unchecked((int)0x80132004); public const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); + public const int CLR_E_BIND_ARCHITECTURE_MISMATCH = unchecked((int)0x80132006); public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) { diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs index f9d306d3d2558b..6b47cabfee3cff 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs @@ -15,6 +15,9 @@ internal sealed class DefaultAssemblyBinder : AssemblyBinder public override bool IsDefault => true; + // Not supported by this binder + public override System.Reflection.LoaderAllocator? GetLoaderAllocator() => null; + // Helper functions private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly, bool excludeAppPaths) { @@ -85,5 +88,68 @@ public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembl return hr; } + + public override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) + { + assembly = null; + int hr; + + try + { + Assembly? coreCLRFoundAssembly; + AssemblyName assemblyName = new AssemblyName(pPEImage); + + // Validate architecture + if (!AssemblyBinderCommon.IsValidArchitecture(assemblyName.ProcessorArchitecture)) + return AssemblyBinderCommon.CLR_E_BIND_ARCHITECTURE_MISMATCH; + + // Easy out for CoreLib + if (assemblyName.IsCoreLib) + return HResults.E_FILENOTFOUND; + + { + // Ensure we are not being asked to bind to a TPA assembly + + Debug.Assert(AppContext.TrustedPlatformAssemblyMap != null); + + if (AppContext.TrustedPlatformAssemblyMap.ContainsKey(assemblyName.SimpleName)) + { + // The simple name of the assembly being requested to be bound was found in the TPA list. + // Now, perform the actual bind to see if the assembly was really in the TPA assembly list or not. + hr = BindAssemblyByNameWorker(assemblyName, out coreCLRFoundAssembly, excludeAppPaths: true); + if (hr >= 0) + { + Debug.Assert(coreCLRFoundAssembly != null); + if (coreCLRFoundAssembly.IsInTPA) + { + assembly = coreCLRFoundAssembly; + return hr; + } + } + } + } + + hr = AssemblyBinderCommon.BindUsingPEImage(this, assemblyName, pPEImage, excludeAppPaths, out coreCLRFoundAssembly); + if (hr == HResults.S_OK) + { + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder = this; + assembly = coreCLRFoundAssembly; + } + } + catch (Exception ex) + { + return ex.HResult; + } + + return hr; + } + + public void SetupBindingPaths(string trustedPlatformAssemblies, string platformResourceRoots, string appPaths) + { + AppContext.SetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPaths, acquireLock: true); + } + + // BindToSystem } } From d6cbc65a658ce679d8fa3ba233d8da765dcb0ac3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 03:22:26 +0800 Subject: [PATCH 033/136] CustomAssemblyBinder --- .../System.Private.CoreLib.csproj | 1 + .../Internal/Runtime/Binder/AssemblyBinder.cs | 2 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 3 + .../Runtime/Binder/CustomAssemblyBinder.cs | 193 ++++++++++++++++++ 4 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 53c5cfb295a840..f9107f2e60c2c3 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -127,6 +127,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index c32a3654692d4f..5ce65c978afec3 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -69,7 +69,7 @@ public void AddLoadedAssembly(IVMAssembly loadedAssembly) } // void GetNameForDiagnostics(/*out*/ SString& alcName); - // + // static void GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName); // static void GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ SString& alcName); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index c3e963159da172..488aea5381a1d5 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -61,6 +61,9 @@ internal static partial class AssemblyBinderCommon [MethodImpl(MethodImplOptions.InternalCall)] private static extern System.Reflection.LoaderAllocator LoaderAllocator_EnsureReference(System.Reflection.LoaderAllocator LA, System.Reflection.LoaderAllocator pOtherLA); + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void LoaderAllocator_RegisterBinder(System.Reflection.LoaderAllocator LA, AssemblyBinder binder); + public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs new file mode 100644 index 00000000000000..8525dc0f7a8139 --- /dev/null +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs @@ -0,0 +1,193 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Internal.Runtime.Binder +{ + internal sealed class CustomAssemblyBinder : AssemblyBinder + { + private readonly DefaultAssemblyBinder _defaultBinder; + private System.Reflection.LoaderAllocator? _loaderAllocator; + private GCHandle _loaderAllocatorHandle; + + // A strong GC handle to the managed AssemblyLoadContext. This handle is set when the unload of the AssemblyLoadContext is initiated + // to keep the managed AssemblyLoadContext alive until the unload is finished. + // We still keep the weak handle pointing to the same managed AssemblyLoadContext so that native code can use the handle above + // to refer to it during the whole lifetime of the AssemblyLoadContext. + private GCHandle _ptrManagedStrongAssemblyLoadContext; + + public override bool IsDefault => false; + + public override System.Reflection.LoaderAllocator? GetLoaderAllocator() => _loaderAllocator; + + public CustomAssemblyBinder( + DefaultAssemblyBinder defaultBinder, + System.Reflection.LoaderAllocator? loaderAllocator, + GCHandle loaderAllocatorHandle, + GCHandle ptrAssemblyLoadContext) + { + // Save reference to the DefaultBinder that is required to be present. + _defaultBinder = defaultBinder; + + // Save the reference to the IntPtr for GCHandle for the managed + // AssemblyLoadContext instance + ManagedAssemblyLoadContext = ptrAssemblyLoadContext; + + if (loaderAllocator != null) + { + // Link to LoaderAllocator, keep a reference to it + // VERIFY(pLoaderAllocator->AddReferenceIfAlive()); + AssemblyBinderCommon.LoaderAllocator_RegisterBinder(loaderAllocator, this); + } + + _loaderAllocator = loaderAllocator; + _loaderAllocatorHandle = loaderAllocatorHandle; + } + + public void PrepareForLoadContextRelease(GCHandle ptrManagedStrongAssemblyLoadContext) + { + // Add a strong handle so that the managed assembly load context stays alive until the + // CustomAssemblyBinder::ReleaseLoadContext is called. + // We keep the weak handle as well since this method can be running on one thread (e.g. the finalizer one) + // and other thread can be using the weak handle. + _ptrManagedStrongAssemblyLoadContext = ptrManagedStrongAssemblyLoadContext; + + Debug.Assert(_loaderAllocator != null); + Debug.Assert(_loaderAllocatorHandle.IsAllocated); + + // We cannot delete the binder here as it is used indirectly when comparing assemblies with the same binder + // It will be deleted when the LoaderAllocator will be deleted + // We need to keep the LoaderAllocator pointer set as it still may be needed for creating references between the + // native LoaderAllocators of two collectible contexts in case the AssemblyLoadContext.Unload was called on the current + // context before returning from its AssemblyLoadContext.Load override or the context's Resolving event. + // But we need to release the LoaderAllocator so that it doesn't prevent completion of the final phase of unloading in + // some cases. It is safe to do as the AssemblyLoaderAllocator is guaranteed to be alive at least until the + // CustomAssemblyBinder::ReleaseLoadContext is called, where we NULL this pointer. + + _loaderAllocator = null!; + + // Destroy the strong handle to the LoaderAllocator in order to let it reach its finalizer + _loaderAllocatorHandle.Free(); + _loaderAllocatorHandle = default; + } + + public void ReleaseLoadContext() + { + Debug.Assert(ManagedAssemblyLoadContext.IsAllocated); + Debug.Assert(_ptrManagedStrongAssemblyLoadContext.IsAllocated); + + // This method is called to release the weak and strong handles on the managed AssemblyLoadContext + // once the Unloading event has been fired + ManagedAssemblyLoadContext.Free(); + _ptrManagedStrongAssemblyLoadContext.Free(); + ManagedAssemblyLoadContext = default; + + // The AssemblyLoaderAllocator is in a process of shutdown and should not be used + // after this point. + _ptrManagedStrongAssemblyLoadContext.Free(); + } + + private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly) + { + // CoreLib should be bound using BindToSystem + Debug.Assert(!assemblyName.IsCoreLib); + + int hr = AssemblyBinderCommon.BindAssembly(this, assemblyName, excludeAppPaths: false, out coreCLRFoundAssembly); + + if (hr >= 0) + { + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder = this; + } + + return hr; + } + + public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) + { + int hr; + Assembly? coreCLRFoundAssembly; + + // When LoadContext needs to resolve an assembly reference, it will go through the following lookup order: + // + // 1) Lookup the assembly within the LoadContext itself. If assembly is found, use it. + // 2) Invoke the LoadContext's Load method implementation. If assembly is found, use it. + // 3) Lookup the assembly within DefaultBinder (except for satellite requests). If assembly is found, use it. + // 4) Invoke the LoadContext's ResolveSatelliteAssembly method (for satellite requests). If assembly is found, use it. + // 5) Invoke the LoadContext's Resolving event. If assembly is found, use it. + // 6) Raise exception. + // + // This approach enables a LoadContext to override assemblies that have been loaded in TPA context by loading + // a different (or even the same!) version. + + { + // Step 1 - Try to find the assembly within the LoadContext. + hr = BindAssemblyByNameWorker(assemblyName, out coreCLRFoundAssembly); + if (hr is HResults.E_FILENOTFOUND or AssemblyBinderCommon.FUSION_E_APP_DOMAIN_LOCKED or HResults.FUSION_E_REF_DEF_MISMATCH) + { + // If we are here, one of the following is possible: + // + // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR + // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def + // mismatch (either due to version difference or strong-name difference). + // + // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call + // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly + // that has been loaded. + + hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(ManagedAssemblyLoadContext, assemblyName, _defaultBinder, this, out coreCLRFoundAssembly); + + if (hr >= 0) + { + // We maybe returned an assembly that was bound to a different AssemblyBinder instance. + // In such a case, we will not overwrite the binder (which would be wrong since the assembly would not + // be present in the cache of the current binding context). + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder ??= this; + } + } + } + + assembly = hr < 0 ? null : coreCLRFoundAssembly; + return hr; + } + + public override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) + { + assembly = null; + int hr; + + try + { + Assembly? coreCLRFoundAssembly; + AssemblyName assemblyName = new AssemblyName(pPEImage); + + // Validate architecture + if (!AssemblyBinderCommon.IsValidArchitecture(assemblyName.ProcessorArchitecture)) + return AssemblyBinderCommon.CLR_E_BIND_ARCHITECTURE_MISMATCH; + + // Disallow attempt to bind to the core library. Aside from that, + // the LoadContext can load any assembly (even if it was in a different LoadContext like TPA). + if (assemblyName.IsCoreLib) + return HResults.E_FILENOTFOUND; + + hr = AssemblyBinderCommon.BindUsingPEImage(this, assemblyName, pPEImage, excludeAppPaths, out coreCLRFoundAssembly); + if (hr == HResults.S_OK) + { + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder = this; + assembly = coreCLRFoundAssembly; + } + } + catch (Exception ex) + { + return ex.HResult; + } + + return hr; + } + } +} From bfff7c2d5f046d24c78f143c42938fb103658426 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 18:33:06 +0800 Subject: [PATCH 034/136] Fix ALC compilation --- .../src/System/Runtime/Loader/AssemblyLoadContext.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index c579a9c5b5d98d..d7355cc9312f9b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -102,8 +102,10 @@ private protected AssemblyLoadContext(bool representsTPALoadContext, bool isColl var thisHandlePtr = GCHandle.ToIntPtr(thisHandle); _nativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, representsTPALoadContext, isCollectible); +#if CORECLR // TODO: AdHoc Internal.Runtime.Binder.DefaultAssemblyBinder.Default.ManagedAssemblyLoadContext = thisHandle; +#endif // Add this instance to the list of alive ALC Dictionary> allContexts = AllContexts; From 4e29ef799215ccc62dbbc3f91eaafbfda83be544 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 19:52:30 +0800 Subject: [PATCH 035/136] Interop with LoaderAllocator --- .../Internal/Runtime/Binder/AssemblyBinderCommon.cs | 8 +------- .../Internal/Runtime/Binder/CustomAssemblyBinder.cs | 5 ++++- .../src/System/Reflection/LoaderAllocator.cs | 8 ++++++++ src/coreclr/vm/loaderallocator.cpp | 11 +++++++++++ src/coreclr/vm/loaderallocator.hpp | 1 + src/coreclr/vm/qcallentrypoints.cpp | 1 + 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 488aea5381a1d5..28c599412904eb 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -58,12 +58,6 @@ internal static partial class AssemblyBinderCommon [MethodImpl(MethodImplOptions.InternalCall)] private static extern System.Reflection.LoaderAllocator DomainAssembly_GetLoaderAllocator(IntPtr pDomainAssembly); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern System.Reflection.LoaderAllocator LoaderAllocator_EnsureReference(System.Reflection.LoaderAllocator LA, System.Reflection.LoaderAllocator pOtherLA); - - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void LoaderAllocator_RegisterBinder(System.Reflection.LoaderAllocator LA, AssemblyBinder binder); - public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; @@ -944,7 +938,7 @@ public static int BindUsingHostAssemblyResolver( } Debug.Assert(resultAssemblyLoaderAllocator != null); - LoaderAllocator_EnsureReference(parentLoaderAllocator, resultAssemblyLoaderAllocator); + parentLoaderAllocator.EnsureReference(resultAssemblyLoaderAllocator); } resolvedAssembly = PEAssembly_GetHostAssembly(pLoadedPEAssembly); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs index 8525dc0f7a8139..d8575f001353fd 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Reflection; using System.Runtime.InteropServices; namespace Internal.Runtime.Binder @@ -40,7 +41,9 @@ public CustomAssemblyBinder( { // Link to LoaderAllocator, keep a reference to it // VERIFY(pLoaderAllocator->AddReferenceIfAlive()); - AssemblyBinderCommon.LoaderAllocator_RegisterBinder(loaderAllocator, this); + + // ((AssemblyLoaderAllocator*)pLoaderAllocator)->RegisterBinder(pBinder); + loaderAllocator.m_binderToRelease = this; } _loaderAllocator = loaderAllocator; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index 166485dc95b88b..1f81ff38c329e3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -60,5 +60,13 @@ private LoaderAllocator() internal CerHashtable m_methodInstantiations; private int m_slotsUsed; #pragma warning restore CA1823, 414, 169 + + internal Internal.Runtime.Binder.AssemblyBinder? m_binderToRelease; + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_EnsureReference")] + + internal static partial void EnsureReference(IntPtr nativeLoaderAllocator, IntPtr otherNativeLoaderAllocator); + + internal void EnsureReference(LoaderAllocator otherLA) => EnsureReference(m_scout.m_nativeLoaderAllocator, otherLA.m_scout.m_nativeLoaderAllocator); } } diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 604aa8218b683d..29a343d0accc96 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -253,6 +253,17 @@ BOOL LoaderAllocator::EnsureReference(LoaderAllocator *pOtherLA) return CheckAddReference_Unlocked(pOtherLA); } +extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocatorHandle pLA, QCall::LoaderAllocatorHandle pOtherLA) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pLA->EnsureReference(pOtherLA); + + END_QCALL; +} + BOOL LoaderAllocator::EnsureInstantiation(Module *pDefiningModule, Instantiation inst) { CONTRACTL diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 365063b0b5220c..3b6a4efcca01d0 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -837,6 +837,7 @@ class LoaderAllocator typedef VPTR(LoaderAllocator) PTR_LoaderAllocator; extern "C" BOOL QCALLTYPE LoaderAllocator_Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator); +extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocatorHandle pLA, QCall::LoaderAllocatorHandle pOtherLA); class GlobalLoaderAllocator : public LoaderAllocator { diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 2a0ac5df3787d6..b2b024af5c197b 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -197,6 +197,7 @@ static const Entry s_QCall[] = DllImportEntry(MultiCoreJIT_InternalStartProfile) #endif DllImportEntry(LoaderAllocator_Destroy) + DllImportEntry(LoaderAllocator_EnsureReference) DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) DllImportEntry(ThreadNative_InformThreadNameChange) From cd37220fdbaeeebcbf663c62031657a17aa16b29 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 23:11:42 +0800 Subject: [PATCH 036/136] Fix CollectionsMarshal usage --- .../src/Internal/Runtime/Binder/AssemblyBinder.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 5ce65c978afec3..5422a6a8241f36 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -101,8 +101,8 @@ public void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool composite addAllLoadedModules = true; } - ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrNullRef(_assemblySimpleNameMvidCheckHash, simpleName); - if (Unsafe.IsNullRef(ref entry)) + ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); + if (!found) { entry = new SimpleNameToExpectedMVIDAndRequiringAssembly { @@ -151,8 +151,8 @@ private void DeclareLoadedAssembly(IVMAssembly loadedAssembly) loadedAssembly.GetMDImport().GetScopeProps(out Guid mvid); string simpleName = loadedAssembly.SimpleName; - ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrNullRef(_assemblySimpleNameMvidCheckHash, simpleName); - if (Unsafe.IsNullRef(ref entry)) + ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); + if (!found) { entry = new SimpleNameToExpectedMVIDAndRequiringAssembly { From 167be6ce9fe84ffb75fefe8c49171771bf68981d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 8 Sep 2023 23:34:19 +0800 Subject: [PATCH 037/136] Name tracing for binder --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 19 ++++++++++++++++--- .../Tracing/ResolutionAttemptedOperation.cs | 3 ++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 5422a6a8241f36..c708a4fd662d07 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -3,8 +3,9 @@ using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; +using System.Diagnostics; using System.Runtime.InteropServices; +using System.Runtime.Loader; namespace Internal.Runtime.Binder { @@ -68,9 +69,21 @@ public void AddLoadedAssembly(IVMAssembly loadedAssembly) } } - // void GetNameForDiagnostics(/*out*/ SString& alcName); + public string GetNameForDiagnostics() => IsDefault ? "Default" : GetNameForDiagnosticsFromManagedALC(ManagedAssemblyLoadContext); + + public static string GetNameForDiagnosticsFromManagedALC(GCHandle managedALC) + { + //if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) + //{ + // alcName.Set(W("Default")); + // return; + //} + + var alc = managedALC.Target as AssemblyLoadContext; + Debug.Assert(alc != null); + return alc.ToString(); + } - // static void GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName); // static void GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ SString& alcName); //# ifdef FEATURE_READYTORUN diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index ae4ca5e9924e8b..d351ee01770df4 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -88,10 +88,11 @@ public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? if (pManagedALC.Target is AssemblyLoadContext managedALC) { // AssemblyBinder::GetNameForDiagnosticsFromManagedALC(managedALC, m_assemblyLoadContextName); + _assemblyLoadContextName = AssemblyBinder.GetNameForDiagnosticsFromManagedALC(pManagedALC); } else { - // binder->GetNameForDiagnostics(m_assemblyLoadContextName); + _assemblyLoadContextName = binder.GetNameForDiagnostics(); } } From a426eac8e0920fe5c99b9ad2c3230abf5185c54a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 00:16:52 +0800 Subject: [PATCH 038/136] Store default binder in AppDomain --- .../Runtime/Binder/DefaultAssemblyBinder.cs | 6 ++++ src/coreclr/vm/appdomain.cpp | 30 ++++++++++++------- src/coreclr/vm/appdomain.hpp | 6 ++-- src/coreclr/vm/assemblybinder.cpp | 4 +-- src/coreclr/vm/corelib.h | 5 ++++ src/coreclr/vm/corhost.cpp | 20 +++++++------ src/coreclr/vm/managedbindernative.h | 29 ++++++++++++++++++ src/coreclr/vm/metasig.h | 2 ++ src/coreclr/vm/namespace.h | 1 + 9 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 src/coreclr/vm/managedbindernative.h diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs index 6b47cabfee3cff..267853c938a027 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs @@ -150,6 +150,12 @@ public void SetupBindingPaths(string trustedPlatformAssemblies, string platformR AppContext.SetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPaths, acquireLock: true); } + // called by VM + public unsafe void SetupBindingPaths(char* trustedPlatformAssemblies, char* platformResourceRoots, char* appPaths) + { + SetupBindingPaths(new string(trustedPlatformAssemblies), new string(platformResourceRoots), new string(appPaths)); + } + // BindToSystem } } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 3ae68e8d460341..1af2fb64f4b740 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -572,7 +572,7 @@ BaseDomain::BaseDomain() } CONTRACTL_END; - m_pDefaultBinder = NULL; + m_pManagedDefaultBinder = NULL; // Make sure the container is set to NULL so that it gets loaded when it is used. m_pPinnedHeapHandleTable = NULL; @@ -683,10 +683,10 @@ void BaseDomain::ClearBinderContext() } CONTRACTL_END; - if (m_pDefaultBinder) + if (m_pManagedDefaultBinder != NULL) { - delete m_pDefaultBinder; - m_pDefaultBinder = NULL; + DestroyHandle(m_pManagedDefaultBinder); + m_pManagedDefaultBinder = NULL; } } @@ -3877,9 +3877,9 @@ AppDomain::RaiseUnhandledExceptionEvent(OBJECTREF *pThrowable, BOOL isTerminatin } -DefaultAssemblyBinder *AppDomain::CreateDefaultBinder() +OBJECTHANDLE AppDomain::CreateDefaultBinder() { - CONTRACT(DefaultAssemblyBinder *) + CONTRACT(OBJECTHANDLE) { GC_TRIGGERS; THROWS; @@ -3889,17 +3889,25 @@ DefaultAssemblyBinder *AppDomain::CreateDefaultBinder() } CONTRACT_END; - if (!m_pDefaultBinder) + if (!m_pManagedDefaultBinder) { ETWOnStartup (FusionAppCtx_V1, FusionAppCtxEnd_V1); - GCX_PREEMP(); + GCX_COOP(); + + OBJECTREF managedBinder = AllocateObject(CoreLibBinder::GetClass(CLASS__BINDER_DEFAULTASSEMBLYBINDER)); + + GCPROTECT_BEGIN(managedBinder); + + MethodDescCallSite ctor(METHOD__BINDER_DEFAULTASSEMBLYBINDER__CTOR); + ctor.Call((ARG_SLOT*)NULL); + + m_pManagedDefaultBinder = CreateHandle(managedBinder); - // Initialize the assembly binder for the default context loads for CoreCLR. - IfFailThrow(BINDER_SPACE::AssemblyBinderCommon::CreateDefaultBinder(&m_pDefaultBinder)); + GCPROTECT_END(); } - RETURN m_pDefaultBinder; + RETURN m_pManagedDefaultBinder; } diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index 7633fb9f2881bf..4f8f8103fea216 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1080,7 +1080,7 @@ class BaseDomain #endif // DACCESS_COMPILE - DefaultAssemblyBinder *GetDefaultBinder() {LIMITED_METHOD_CONTRACT; return m_pDefaultBinder; } + OBJECTHANDLE GetDefaultBinder() { LIMITED_METHOD_CONTRACT; return m_pManagedDefaultBinder; } CrstExplicitInit * GetLoaderAllocatorReferencesLock() { @@ -1129,7 +1129,7 @@ class BaseDomain ListLock m_ILStubGenLock; ListLock m_NativeTypeLoadLock; - DefaultAssemblyBinder *m_pDefaultBinder; // Reference to the binding context that holds TPA list details + OBJECTHANDLE m_pManagedDefaultBinder; IGCHandleStore* m_handleStore; @@ -1973,7 +1973,7 @@ class AppDomain : public BaseDomain RCWRefCache *GetRCWRefCache(); #endif // FEATURE_COMWRAPPERS - DefaultAssemblyBinder *CreateDefaultBinder(); + OBJECTHANDLE CreateDefaultBinder(); void SetIgnoreUnhandledExceptions() { diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index 36c07df10b2f4e..f3322b196d3ee1 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -168,11 +168,11 @@ void AssemblyBinder::AddLoadedAssembly(Assembly* loadedAssembly) void AssemblyBinder::GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName) { - if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) + /*if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) { alcName.Set(W("Default")); return; - } + }*/ OBJECTREF* alc = reinterpret_cast(managedALC); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 0dd79fb124f820..38793d8b18a277 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1194,6 +1194,11 @@ DEFINE_METHOD(EH, RH_RETHROW, RhRethrow, SM_RefExInfo_RefExInfo_RetVoid) DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) #endif // FOR_ILLINK +// Managed binder types +DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) +DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) +DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, gsig_IM_PtrChar_PtrChar_PtrChar_RetVoid) + DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes) DEFINE_FIELD_U(_totalAvailableMemoryBytes, GCMemoryInfoData, totalAvailableMemoryBytes) diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index bb32e93cd0961a..e758f826303bac 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -618,16 +618,18 @@ HRESULT CorHost2::CreateAppDomainWithManager( pDomain->SetNativeDllSearchDirectories(pwzNativeDllSearchDirectories); { - SString sTrustedPlatformAssemblies(pwzTrustedPlatformAssemblies); - SString sPlatformResourceRoots(pwzPlatformResourceRoots); - SString sAppPaths(pwzAppPaths); - - DefaultAssemblyBinder *pBinder = pDomain->GetDefaultBinder(); + ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pDomain->GetDefaultBinder()); _ASSERTE(pBinder != NULL); - IfFailThrow(pBinder->SetupBindingPaths( - sTrustedPlatformAssemblies, - sPlatformResourceRoots, - sAppPaths)); + + MethodDescCallSite methSetupBindingPaths(METHOD__BINDER_DEFAULTASSEMBLYBINDER__SETUP_BINDING_PATHS); + ARG_SLOT args[3] = + { + PtrToArgSlot(pwzTrustedPlatformAssemblies), + PtrToArgSlot(pwzPlatformResourceRoots), + PtrToArgSlot(pwzAppPaths) + }; + + methSetupBindingPaths.Call(args); } #if defined(TARGET_UNIX) diff --git a/src/coreclr/vm/managedbindernative.h b/src/coreclr/vm/managedbindernative.h new file mode 100644 index 00000000000000..193cf0e3e515a8 --- /dev/null +++ b/src/coreclr/vm/managedbindernative.h @@ -0,0 +1,29 @@ +#include "object.h" + +// managed Internal.Runtime.Binder.Assembly +class BinderAssemblyObject : public Object +{ +public: + PEImage* m_PEImage; +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF BINDERASSEMBLYREF; +#else // USE_CHECKED_OBJECTREFS +typedef DPTR(BinderAssemblyObject) PTR_BinderAssemblyObject; +typedef PTR_BinderAssemblyObject BINDERASSEMBLYREF; +#endif // USE_CHECKED_OBJECTREFS + + +// managed Internal.Runtime.Binder.AssemblyBinder +class AssemblyBinderObject : public Object +{ + +}; + +#ifdef USE_CHECKED_OBJECTREFS +typedef REF ASSEMBLYBINDERREF; +#else // USE_CHECKED_OBJECTREFS +typedef DPTR(AssemblyBinderObject) PTR_AssemblyBinderObject; +typedef AssemblyBinderObject ASSEMBLYBINDERREF; +#endif // USE_CHECKED_OBJECTREFS diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index dc2173f0440211..5eefa37dff09e8 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -616,6 +616,8 @@ DEFINE_METASIG(SM(PtrByte_RetStr, P(b), s)) DEFINE_METASIG(SM(Str_RetPtrByte, s, P(b))) DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) +DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) + // Undefine macros in case we include the file again in the compilation unit #undef DEFINE_METASIG diff --git a/src/coreclr/vm/namespace.h b/src/coreclr/vm/namespace.h index 8b51f9ca623915..7e17cc6b2b5024 100644 --- a/src/coreclr/vm/namespace.h +++ b/src/coreclr/vm/namespace.h @@ -70,3 +70,4 @@ #define g_ExceptionServicesNS g_RuntimeNS ".ExceptionServices" #define g_LoaderNS g_RuntimeNS ".Loader" +#define g_InternalLoaderNS "Internal.Runtime.Loader" From 6f4de1b8d09b1a1b3eabd42049412f974d2136b2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 12:09:09 +0800 Subject: [PATCH 039/136] Store custom assembly binder in ALC --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 9 ++--- .../Runtime/Binder/DefaultAssemblyBinder.cs | 3 -- .../Loader/AssemblyLoadContext.CoreCLR.cs | 39 +++++++++++++++++++ src/coreclr/vm/assemblynative.cpp | 15 +++++++ src/coreclr/vm/assemblynative.hpp | 2 + src/coreclr/vm/qcallentrypoints.cpp | 1 + .../Runtime/Loader/AssemblyLoadContext.cs | 10 +++-- 7 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index c708a4fd662d07..e1380093b8a1ec 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -73,11 +73,10 @@ public void AddLoadedAssembly(IVMAssembly loadedAssembly) public static string GetNameForDiagnosticsFromManagedALC(GCHandle managedALC) { - //if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) - //{ - // alcName.Set(W("Default")); - // return; - //} + if (managedALC.Target == GCHandle.FromIntPtr(AssemblyLoadContext.GetDefaultAssemblyBinder()).Target) + { + return "Default"; + } var alc = managedALC.Target as AssemblyLoadContext; Debug.Assert(alc != null); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs index 267853c938a027..078fe4f30a067a 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs @@ -10,9 +10,6 @@ namespace Internal.Runtime.Binder { internal sealed class DefaultAssemblyBinder : AssemblyBinder { - // TODO: AdHoc - internal static DefaultAssemblyBinder Default { get; } = new DefaultAssemblyBinder(); - public override bool IsDefault => true; // Not supported by this binder diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index c189daff85b05a..0c73ef5af22698 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Reflection; @@ -11,9 +12,47 @@ namespace System.Runtime.Loader { public partial class AssemblyLoadContext { + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] + internal static partial IntPtr GetDefaultAssemblyBinder(); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_InitializeAssemblyLoadContext")] private static partial IntPtr InitializeAssemblyLoadContext(IntPtr ptrAssemblyLoadContext, [MarshalAs(UnmanagedType.Bool)] bool fRepresentsTPALoadContext, [MarshalAs(UnmanagedType.Bool)] bool isCollectible); + private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadContext(GCHandle ptrAssemblyLoadContext, bool representsTPALoadContext, bool isCollectible) + { + // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and + // only one thread is ever executing a ctor for a given instance. + + // Initialize the assembly binder instance in the VM + GCHandle pDefaultBinder = GCHandle.FromIntPtr(GetDefaultAssemblyBinder()); + var defaultBinder = pDefaultBinder.Target as Internal.Runtime.Binder.DefaultAssemblyBinder; + Debug.Assert(defaultBinder != null); + if (!representsTPALoadContext) + { + // Initialize a custom assembly binder + + LoaderAllocator? loaderAllocator = null; + GCHandle loaderAllocatorHandle = default; + + if (isCollectible) + { + // Create a new AssemblyLoaderAllocator for an AssemblyLoadContext + } + + return new Internal.Runtime.Binder.CustomAssemblyBinder(defaultBinder, loaderAllocator, loaderAllocatorHandle, ptrAssemblyLoadContext); + } + else + { + // We are initializing the managed instance of Assembly Load Context that would represent the TPA binder. + // First, confirm we do not have an existing managed ALC attached to the TPA binder. + Debug.Assert(!defaultBinder.ManagedAssemblyLoadContext.IsAllocated); + + // Attach the managed TPA binding context with the native one. + defaultBinder.ManagedAssemblyLoadContext = ptrAssemblyLoadContext; + return defaultBinder; + } + } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_PrepareForAssemblyLoadContextRelease")] private static partial void PrepareForAssemblyLoadContextRelease(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyLoadContextStrong); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 340096c919e989..8d81ffd3a2a723 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1252,6 +1252,21 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PT return ptrNativeAssemblyBinder; } +extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder() +{ + QCALL_CONTRACT; + + INT_PTR ptrDefaultAssemblyBinder = NULL; + + BEGIN_QCALL; + + ptrDefaultAssemblyBinder = (INT_PTR)GetAppDomain()->GetDefaultBinder(); + + END_QCALL; + + return ptrDefaultAssemblyBinder; +} + /*static*/ extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext) { diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 5c08c7a8edb319..4390cf03995b65 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -113,6 +113,8 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH extern "C" BOOL QCALLTYPE AssemblyNative_GetIsCollectible(QCall::AssemblyHandle pAssembly); +extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder(); + extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible); extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index b2b024af5c197b..dd8281e3394279 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -177,6 +177,7 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_InternalTryGetRawMetadata) DllImportEntry(AssemblyNative_ApplyUpdate) DllImportEntry(AssemblyNative_IsApplyUpdateSupported) + DllImportEntry(AssemblyNative_GetDefaultAssemblyBinder) DllImportEntry(AssemblyNative_InitializeAssemblyLoadContext) DllImportEntry(AssemblyNative_PrepareForAssemblyLoadContextRelease) DllImportEntry(AssemblyNative_LoadFromPath) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index d7355cc9312f9b..126466d6bee8c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -46,7 +46,11 @@ private enum InternalState // Contains the reference to VM's representation of the AssemblyLoadContext private readonly IntPtr _nativeAssemblyLoadContext; -#endregion + #endregion + +#if CORECLR + private readonly Internal.Runtime.Binder.AssemblyBinder _assemblyBinder; +#endif // synchronization primitive to protect against usage of this instance while unloading private readonly object _unloadLock; @@ -103,8 +107,8 @@ private protected AssemblyLoadContext(bool representsTPALoadContext, bool isColl _nativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, representsTPALoadContext, isCollectible); #if CORECLR - // TODO: AdHoc - Internal.Runtime.Binder.DefaultAssemblyBinder.Default.ManagedAssemblyLoadContext = thisHandle; + // AssemblyNative_InitializeAssemblyLoadContext + _assemblyBinder = InitializeAssemblyLoadContext(thisHandle, representsTPALoadContext, isCollectible); #endif // Add this instance to the list of alive ALC From 20593a27a4f1b9498119cb2230c759c70f79d1e2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 13:02:16 +0800 Subject: [PATCH 040/136] Fix compilation --- .../Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs | 1 + .../src/System/Reflection/LoaderAllocator.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index d351ee01770df4..3db41b7f189f1e 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -92,6 +92,7 @@ public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? } else { + Debug.Assert(binder != null); _assemblyLoadContextName = binder.GetNameForDiagnostics(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index 1f81ff38c329e3..cb1d913f8e7a63 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -44,7 +44,7 @@ internal sealed partial class LoaderAllocatorScout } } - internal sealed class LoaderAllocator + internal sealed partial class LoaderAllocator { private LoaderAllocator() { From e95960050d14f914c799f0f9f8c041a41014b918 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 15:23:06 +0800 Subject: [PATCH 041/136] Use managed binder in ALC --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 6 + .../Runtime/Binder/AssemblyBinderCommon.cs | 2 +- .../src/System/Reflection/LoaderAllocator.cs | 4 + .../Loader/AssemblyLoadContext.CoreCLR.cs | 185 +++++++++++++++--- .../Runtime/Loader/AssemblyLoadContext.cs | 17 +- 5 files changed, 180 insertions(+), 34 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index e1380093b8a1ec..e45899440fdb31 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -225,5 +225,11 @@ internal interface IVMAssembly // coreclr/vm/assembly public System.Reflection.MetadataImport GetMDImport(); public string SimpleName { get; } + + public System.Reflection.RuntimeAssembly GetExposedObject(); + + public IntPtr GetPEAssembly_GetPEImage(); + + public unsafe void GetModule_SetSymbolBytes(byte* ptrSymbolArray, int cbSymbolArrayLength); } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 28c599412904eb..e81f365f5c5bee 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -41,7 +41,7 @@ internal static partial class AssemblyBinderCommon private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void ReleasePEImage(IntPtr pPEImage); + internal static extern void ReleasePEImage(IntPtr pPEImage); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index cb1d913f8e7a63..58ff51a39f6094 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -68,5 +68,9 @@ private LoaderAllocator() internal static partial void EnsureReference(IntPtr nativeLoaderAllocator, IntPtr otherNativeLoaderAllocator); internal void EnsureReference(LoaderAllocator otherLA) => EnsureReference(m_scout.m_nativeLoaderAllocator, otherLA.m_scout.m_nativeLoaderAllocator); + + // Foo + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern bool IsCollectible(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 0c73ef5af22698..b630314513d8a7 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -15,8 +15,24 @@ public partial class AssemblyLoadContext [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] internal static partial IntPtr GetDefaultAssemblyBinder(); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_InitializeAssemblyLoadContext")] - private static partial IntPtr InitializeAssemblyLoadContext(IntPtr ptrAssemblyLoadContext, [MarshalAs(UnmanagedType.Bool)] bool fRepresentsTPALoadContext, [MarshalAs(UnmanagedType.Bool)] bool isCollectible); + // Foo + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern IntPtr PEImage_OpenImage(string pwzILPath, int mdInternalImportFlags, Internal.Runtime.Binder.BundleFileLocation bundleFileLocation = default); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool PEImage_CheckILFormat(IntPtr pPEImage); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool PEImage_IsILOnly(IntPtr pPEImage); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string PEImage_GetPathForErrorMessage(IntPtr pPEImage); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern Internal.Runtime.Binder.IVMAssembly AssemblyNative_LoadFromPEImage(Internal.Runtime.Binder.AssemblyBinder pBinder, IntPtr pPEImage, bool excludeAppPaths = false); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern unsafe IntPtr PEImage_CreateFromByteArray(byte* ptrAssemblyArray, int cbAssemblyArrayLength); private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadContext(GCHandle ptrAssemblyLoadContext, bool representsTPALoadContext, bool isCollectible) { @@ -53,12 +69,65 @@ private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadCont } } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_PrepareForAssemblyLoadContextRelease")] - private static partial void PrepareForAssemblyLoadContextRelease(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyLoadContextStrong); + private static void PrepareForAssemblyLoadContextRelease(Internal.Runtime.Binder.AssemblyBinder ptrNativeAssemblyBinder, GCHandle ptrAssemblyLoadContextStrong) + { + ((Internal.Runtime.Binder.CustomAssemblyBinder)ptrNativeAssemblyBinder).PrepareForLoadContextRelease(ptrAssemblyLoadContextStrong); + } + + private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, byte* ptrAssemblyArray, int iAssemblyArrayLen, byte* ptrSymbols, int iSymbolArrayLen) + { + IntPtr pILImage = 0; - [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromStream")] - private static partial void LoadFromStream(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyArray, int iAssemblyArrayLen, IntPtr ptrSymbols, int iSymbolArrayLen, ObjectHandleOnStack retAssembly); + try + { + pILImage = PEImage_CreateFromByteArray(ptrAssemblyArray, iAssemblyArrayLen); + + // Need to verify that this is a valid CLR assembly. + if (!PEImage_CheckILFormat(pILImage)) + throw new BadImageFormatException(SR.BadImageFormat_BadILFormat); + + LoaderAllocator? loaderAllocator = assemblyBinder.GetLoaderAllocator(); + if (loaderAllocator != null && loaderAllocator.IsCollectible() && !PEImage_IsILOnly(pILImage)) + { + // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed + throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{PEImage_GetPathForErrorMessage(pILImage)}' is invalid."); + } + + // Pass the stream based assembly as IL in an attempt to bind and load it + Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); + RuntimeAssembly retAssembly = loadedAssembly.GetExposedObject(); + + // LOG((LF_CLASSLOADER, + // LL_INFO100, + // "\tLoaded assembly from a file\n")); + + // In order to assign the PDB image (if present), + // the resulting assembly's image needs to be exactly the one + // we created above. We need pointer comparison instead of pe image equivalence + // to avoid mixed binaries/PDB pairs of other images. + // This applies to both Desktop CLR and CoreCLR, with or without fusion. + bool isSameAssembly = loadedAssembly.GetPEAssembly_GetPEImage() == pILImage; + + // Setting the PDB info is only applicable for our original assembly. + // This applies to both Desktop CLR and CoreCLR, with or without fusion. + if (isSameAssembly) + { + // #ifdef DEBUGGING_SUPPORTED + if (ptrSymbols != null) + { + loadedAssembly.GetModule_SetSymbolBytes(ptrAssemblyArray, iSymbolArrayLen); + } + // #endif + } + + return retAssembly; + } + finally + { + if (pILImage != 0) + Internal.Runtime.Binder.AssemblyBinderCommon.ReleasePEImage(pILImage); + } + } [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MultiCoreJIT_InternalSetProfileRoot", StringMarshalling = StringMarshalling.Utf16)] internal static partial void InternalSetProfileRoot(string directoryPath); @@ -66,9 +135,53 @@ private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadCont [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MultiCoreJIT_InternalStartProfile", StringMarshalling = StringMarshalling.Utf16)] internal static partial void InternalStartProfile(string? profile, IntPtr ptrNativeAssemblyBinder); + // Foo + [MethodImpl(MethodImplOptions.InternalCall)] + internal static extern void InternalStartProfile(string? profile, Internal.Runtime.Binder.AssemblyBinder ptrNativeAssemblyBinder); + [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromPath", StringMarshalling = StringMarshalling.Utf16)] - private static partial void LoadFromPath(IntPtr ptrNativeAssemblyBinder, string? ilPath, string? niPath, ObjectHandleOnStack retAssembly); +#pragma warning disable IDE0060 // niPath is unused + private static RuntimeAssembly LoadFromPath(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, string? ilPath, string? niPath) +#pragma warning restore IDE0060 + { + // Form the PEImage for the ILAssembly. In case of an exception, the holder will ensure + // the release of the image. + IntPtr pILImage = 0; + + try + { + if (ilPath != null) + { + pILImage = PEImage_OpenImage(ilPath, 0, default); + + // Need to verify that this is a valid CLR assembly. + if (!PEImage_CheckILFormat(pILImage)) + throw new BadImageFormatException($"{SR.BadImageFormat_BadILFormat} The format of the file '{PEImage_GetPathForErrorMessage(pILImage)}' is invalid."); + + LoaderAllocator? loaderAllocator = assemblyBinder.GetLoaderAllocator(); + if (loaderAllocator != null && loaderAllocator.IsCollectible() && !PEImage_IsILOnly(pILImage)) + { + // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed + throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{PEImage_GetPathForErrorMessage(pILImage)}' is invalid."); + } + + Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); + return loadedAssembly.GetExposedObject(); + + // LOG((LF_CLASSLOADER, + // LL_INFO100, + // "\tLoaded assembly from a file\n")); + } + + // The behavior was inherited from native implementation. + return null!; + } + finally + { + if (pILImage != 0) + Internal.Runtime.Binder.AssemblyBinderCommon.ReleasePEImage(pILImage); + } + } [MethodImpl(MethodImplOptions.InternalCall)] internal static extern Assembly[] GetLoadedAssemblies(); @@ -95,29 +208,52 @@ private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadCont [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] private RuntimeAssembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) { - RuntimeAssembly? loadedAssembly = null; - LoadFromPath(_nativeAssemblyLoadContext, assemblyPath, nativeImagePath, ObjectHandleOnStack.Create(ref loadedAssembly)); - return loadedAssembly!; + return LoadFromPath(_assemblyBinder, assemblyPath, nativeImagePath); } [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySpan arrSymbols) { - RuntimeAssembly? loadedAssembly = null; - fixed (byte* ptrAssembly = arrAssembly, ptrSymbols = arrSymbols) { - LoadFromStream(_nativeAssemblyLoadContext, new IntPtr(ptrAssembly), arrAssembly.Length, - new IntPtr(ptrSymbols), arrSymbols.Length, ObjectHandleOnStack.Create(ref loadedAssembly)); + return LoadFromStream(_assemblyBinder, ptrAssembly, arrAssembly.Length, + ptrSymbols, arrSymbols.Length); } - - return loadedAssembly!; } #if TARGET_WINDOWS - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromInMemoryModule")] - private static partial IntPtr LoadFromInMemoryModuleInternal(IntPtr ptrNativeAssemblyBinder, IntPtr hModule, ObjectHandleOnStack retAssembly); + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern unsafe IntPtr PEImage_CreateFromHMODULE(IntPtr hMod); + + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern bool PEImage_HasCorHeader(IntPtr pPEImage); + + private static RuntimeAssembly LoadFromInMemoryModuleInternal(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, IntPtr hModule) + { + IntPtr pILImage = 0; + try + { + pILImage = PEImage_CreateFromHMODULE(hModule); + + // Need to verify that this is a valid CLR assembly. + if (!PEImage_HasCorHeader(pILImage)) + throw new BadImageFormatException(SR.BadImageFormat_BadILFormat); + + // Pass the in memory module as IL in an attempt to bind and load it + Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); + return loadedAssembly.GetExposedObject(); + + // LOG((LF_CLASSLOADER, + // LL_INFO100, + // "\tLoaded assembly from a file\n")); + } + finally + { + if (pILImage != 0) + Internal.Runtime.Binder.AssemblyBinderCommon.ReleasePEImage(pILImage); + } + } /// /// Load a module that has already been loaded into memory by the OS loader as a .NET assembly. @@ -130,12 +266,7 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) { VerifyIsAlive(); - RuntimeAssembly? loadedAssembly = null; - LoadFromInMemoryModuleInternal( - _nativeAssemblyLoadContext, - moduleHandle, - ObjectHandleOnStack.Create(ref loadedAssembly)); - return loadedAssembly!; + return LoadFromInMemoryModuleInternal(_assemblyBinder, moduleHandle); } } #endif @@ -215,7 +346,7 @@ public void SetProfileOptimizationRoot(string directoryPath) // Start profile optimization for the specified profile name. public void StartProfileOptimization(string? profile) { - InternalStartProfile(profile, _nativeAssemblyLoadContext); + InternalStartProfile(profile, _assemblyBinder); } internal static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 126466d6bee8c7..4fc00005956019 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -39,18 +39,18 @@ private enum InternalState Interlocked.CompareExchange(ref s_allContexts, new Dictionary>(), null) ?? s_allContexts; -#region private data members + #region private data members +#if CORECLR + private readonly Internal.Runtime.Binder.AssemblyBinder _assemblyBinder; +#else // If you modify this field, you must also update the // AssemblyLoadContextBaseObject structure in object.h // and MonoManagedAssemblyLoadContext in object-internals.h // Contains the reference to VM's representation of the AssemblyLoadContext private readonly IntPtr _nativeAssemblyLoadContext; - #endregion - -#if CORECLR - private readonly Internal.Runtime.Binder.AssemblyBinder _assemblyBinder; #endif + #endregion // synchronization primitive to protect against usage of this instance while unloading private readonly object _unloadLock; @@ -104,11 +104,12 @@ private protected AssemblyLoadContext(bool representsTPALoadContext, bool isColl // If this is a collectible ALC, we are creating a weak handle tracking resurrection otherwise we use a strong handle var thisHandle = GCHandle.Alloc(this, IsCollectible ? GCHandleType.WeakTrackResurrection : GCHandleType.Normal); var thisHandlePtr = GCHandle.ToIntPtr(thisHandle); - _nativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, representsTPALoadContext, isCollectible); #if CORECLR // AssemblyNative_InitializeAssemblyLoadContext _assemblyBinder = InitializeAssemblyLoadContext(thisHandle, representsTPALoadContext, isCollectible); +#else + _nativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, representsTPALoadContext, isCollectible); #endif // Add this instance to the list of alive ALC @@ -157,7 +158,11 @@ private void InitiateUnload() var thisStrongHandlePtr = GCHandle.ToIntPtr(thisStrongHandle); // The underlying code will transform the original weak handle // created by InitializeLoadContext to a strong handle +#if CORECLR + PrepareForAssemblyLoadContextRelease(_assemblyBinder, thisStrongHandle); +#else PrepareForAssemblyLoadContextRelease(_nativeAssemblyLoadContext, thisStrongHandlePtr); +#endif _state = InternalState.Unloading; } From e0733235364fb3841a60122bc3416ef1750b2a6d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 16:46:48 +0800 Subject: [PATCH 042/136] PEImage QCalls --- .../Runtime/Binder/AssemblyBinderCommon.cs | 12 +- .../Loader/AssemblyLoadContext.CoreCLR.cs | 62 ++++++---- src/coreclr/vm/peimage.cpp | 115 ++++++++++++++++++ src/coreclr/vm/peimage.h | 14 +++ src/coreclr/vm/qcallentrypoints.cpp | 10 ++ 5 files changed, 177 insertions(+), 36 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index e81f365f5c5bee..bf5971e0299598 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -40,12 +40,6 @@ internal static partial class AssemblyBinderCommon [LibraryImport("Foo", StringMarshalling = StringMarshalling.Utf8)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void ReleasePEImage(IntPtr pPEImage); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); @@ -666,7 +660,7 @@ or RO_E_METADATA_NAME_NOT_FOUND finally { // SAFE_RELEASE(pPEImage); - ReleasePEImage(pPEImage); + AssemblyLoadContext.PEImage_Release(pPEImage); } } @@ -1018,8 +1012,8 @@ public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyN try { - PEImage_GetMVID(pPEImage, out incomingMVID); - PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); + AssemblyLoadContext.PEImage_GetMVID(pPEImage, out incomingMVID); + AssemblyLoadContext.PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); } catch (Exception ex) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index b630314513d8a7..3353e4a205e096 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -16,24 +16,9 @@ public partial class AssemblyLoadContext internal static partial IntPtr GetDefaultAssemblyBinder(); // Foo - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr PEImage_OpenImage(string pwzILPath, int mdInternalImportFlags, Internal.Runtime.Binder.BundleFileLocation bundleFileLocation = default); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool PEImage_CheckILFormat(IntPtr pPEImage); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool PEImage_IsILOnly(IntPtr pPEImage); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string PEImage_GetPathForErrorMessage(IntPtr pPEImage); - [MethodImpl(MethodImplOptions.InternalCall)] private static extern Internal.Runtime.Binder.IVMAssembly AssemblyNative_LoadFromPEImage(Internal.Runtime.Binder.AssemblyBinder pBinder, IntPtr pPEImage, bool excludeAppPaths = false); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe IntPtr PEImage_CreateFromByteArray(byte* ptrAssemblyArray, int cbAssemblyArrayLength); - private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadContext(GCHandle ptrAssemblyLoadContext, bool representsTPALoadContext, bool isCollectible) { // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and @@ -90,7 +75,7 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass if (loaderAllocator != null && loaderAllocator.IsCollectible() && !PEImage_IsILOnly(pILImage)) { // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed - throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{PEImage_GetPathForErrorMessage(pILImage)}' is invalid."); + throw new BadImageFormatException("Cannot load a mixed assembly into a collectible AssemblyLoadContext"); } // Pass the stream based assembly as IL in an attempt to bind and load it @@ -125,7 +110,7 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass finally { if (pILImage != 0) - Internal.Runtime.Binder.AssemblyBinderCommon.ReleasePEImage(pILImage); + PEImage_Release(pILImage); } } @@ -156,13 +141,13 @@ private static RuntimeAssembly LoadFromPath(Internal.Runtime.Binder.AssemblyBind // Need to verify that this is a valid CLR assembly. if (!PEImage_CheckILFormat(pILImage)) - throw new BadImageFormatException($"{SR.BadImageFormat_BadILFormat} The format of the file '{PEImage_GetPathForErrorMessage(pILImage)}' is invalid."); + throw new BadImageFormatException($"{SR.BadImageFormat_BadILFormat} The format of the file '{ilPath}' is invalid."); LoaderAllocator? loaderAllocator = assemblyBinder.GetLoaderAllocator(); if (loaderAllocator != null && loaderAllocator.IsCollectible() && !PEImage_IsILOnly(pILImage)) { // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed - throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{PEImage_GetPathForErrorMessage(pILImage)}' is invalid."); + throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{ilPath}' is invalid."); } Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); @@ -179,7 +164,7 @@ private static RuntimeAssembly LoadFromPath(Internal.Runtime.Binder.AssemblyBind finally { if (pILImage != 0) - Internal.Runtime.Binder.AssemblyBinderCommon.ReleasePEImage(pILImage); + PEImage_Release(pILImage); } } @@ -222,12 +207,6 @@ internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySp } #if TARGET_WINDOWS - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe IntPtr PEImage_CreateFromHMODULE(IntPtr hMod); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool PEImage_HasCorHeader(IntPtr pPEImage); - private static RuntimeAssembly LoadFromInMemoryModuleInternal(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, IntPtr hModule) { IntPtr pILImage = 0; @@ -251,7 +230,7 @@ private static RuntimeAssembly LoadFromInMemoryModuleInternal(Internal.Runtime.B finally { if (pILImage != 0) - Internal.Runtime.Binder.AssemblyBinderCommon.ReleasePEImage(pILImage); + PEImage_Release(pILImage); } } @@ -309,6 +288,35 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetLoadContextForAssembly")] private static partial IntPtr GetLoadContextForAssembly(QCallAssembly assembly); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_OpenImage", StringMarshalling = StringMarshalling.Utf16)] + private static partial IntPtr PEImage_OpenImage(string path, int mdInternalImportFlags, Internal.Runtime.Binder.BundleFileLocation bundleFileLocation = default); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_CreateFromByteArray")] + private static unsafe partial IntPtr PEImage_CreateFromByteArray(byte* ptrArray, int size); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_CheckILFormat")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool PEImage_CheckILFormat(IntPtr pPEImage); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_IsILOnly")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool PEImage_IsILOnly(IntPtr pPEImage); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_Release")] + internal static partial void PEImage_Release(IntPtr pPEImage); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetMVID")] + internal static partial void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); + +#if TARGET_WINDOWS + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_CreateFromHMODULE")] + private static unsafe partial IntPtr PEImage_CreateFromHMODULE(IntPtr hMod); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_HasCorHeader")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool PEImage_HasCorHeader(IntPtr pPEImage); +#endif + // Returns the load context in which the specified assembly has been loaded public static AssemblyLoadContext? GetLoadContext(Assembly assembly) { diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index a355c88ab6ed7a..c3450e9b3ae1b6 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -954,4 +954,119 @@ FCIMPL2(IMDInternalImport*, PEImage::ManagedBinderAcquireImport, PEImage* pPEIma return ret; } FCIMPLEND + +extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation) +{ + QCALL_CONTRACT; + + PEImage* result = NULL; + + BEGIN_QCALL; + + result = PEImage::OpenImage(pPath, flags, bundleFileLocation); + + END_QCALL; + + return result; +} + +extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size) +{ + QCALL_CONTRACT; + + PEImage * result = NULL; + + BEGIN_QCALL; + + result = PEImage::CreateFromByteArray(array, (COUNT_T)size); + + END_QCALL; + + return result; +} + +extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BOOL result = false; + + BEGIN_QCALL; + + result = pPEImage->CheckILFormat(); + + END_QCALL; + + return result; +} + +extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BOOL result = false; + + BEGIN_QCALL; + + result = pPEImage->IsILOnly(); + + END_QCALL; + + return result; +} + +extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pPEImage->Release(); + + END_QCALL; +} + +extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pPEImage->GetMVID(pMVID); + + END_QCALL; +} + +#ifdef TARGET_WINDOWS +extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod) +{ + QCALL_CONTRACT; + + PEImage * result = NULL; + + BEGIN_QCALL; + + result = PEImage::CreateFromHMODULE(hMod); + + END_QCALL; + + return result; +} + +extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BOOL result = false; + + BEGIN_QCALL; + + result = pPEImage->HasCorHeader(); + + END_QCALL; + + return result; +} +#endif // TARGET_WINDOWS + #endif // DACCESS_COMPILE diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index ee06e9e6730f00..44f433ea5e64e3 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -19,6 +19,7 @@ #include "sstring.h" #include "holder.h" #include +#include "qcall.h" class SimpleRWLock; // -------------------------------------------------------------------------------- @@ -331,6 +332,19 @@ FORCEINLINE void PEImageRelease(PEImage *i) i->Release(); } +#ifndef DACCESS_COMPILE +extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation); +extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size); +extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage); +extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage); +extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage); +extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID); +#ifdef TARGET_WINDOWS +extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod); +extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage); +#endif // TARGET_WINDOWS +#endif // DACCESS_COMPILE + typedef Wrapper PEImageHolder; // ================================================================================ diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index dd8281e3394279..b0bd164145679b 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -193,6 +193,16 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetAssemblyCount) DllImportEntry(AssemblyNative_GetEntryAssembly) DllImportEntry(AssemblyNative_GetExecutingAssembly) + DllImportEntry(PEImage_OpenImage) + DllImportEntry(PEImage_CreateFromByteArray) + DllImportEntry(PEImage_CheckILFormat) + DllImportEntry(PEImage_IsILOnly) + DllImportEntry(PEImage_Release) + DllImportEntry(PEImage_GetMVID) +#ifdef TARGET_WINDOWS + DllImportEntry(PEImage_CreateFromHMODULE) + DllImportEntry(PEImage_HasCorHeader) +#endif #if defined(FEATURE_MULTICOREJIT) DllImportEntry(MultiCoreJIT_InternalSetProfileRoot) DllImportEntry(MultiCoreJIT_InternalStartProfile) From 57039c72784fffb55204f31d33afbd946d9a7baa Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 17:06:58 +0800 Subject: [PATCH 043/136] Make BinderAcquireImport and BinderAcquirePEImage QCall. --- .../Runtime/Binder/AssemblyBinderCommon.cs | 10 ++-- src/coreclr/vm/ecalllist.h | 5 -- src/coreclr/vm/peimage.cpp | 47 +++++++++++++++---- src/coreclr/vm/peimage.h | 6 +-- src/coreclr/vm/qcallentrypoints.cpp | 2 + 5 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index bf5971e0299598..a708e9ad2c8b41 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -32,14 +32,14 @@ internal struct BundleFileLocation internal static partial class AssemblyBinderCommon { - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern unsafe IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); - - // Foo + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquireImport")] + public static unsafe partial IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); - [LibraryImport("Foo", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf8)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); + // Foo + [MethodImpl(MethodImplOptions.InternalCall)] private static extern IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index a3280b5f8933fc..f4518beeba60ce 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -672,10 +672,6 @@ FCFuncStart(gComAwareWeakReferenceFuncs) FCFuncElement("HasInteropInfo", ComAwareWeakReferenceNative::HasInteropInfo) FCFuncEnd() -FCFuncStart(gAssemblyBinderCommonFuncs) - FCFuncElement("BinderAcquireImport", PEImage::ManagedBinderAcquireImport) -FCFuncEnd() - #ifdef FEATURE_COMINTEROP // @@ -778,7 +774,6 @@ FCClassElement("ValueType", "System", gValueTypeFuncs) FCClassElement("Variant", "System", gVariantFuncs) #endif FCClassElement("WaitHandle", "System.Threading", gWaitHandleFuncs) -FCClassElement("AssemblyBinderCommon", "Internal.Runtime.Binder", gAssemblyBinderCommonFuncs) #undef FCFuncElement #undef FCFuncElementSig diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index c3450e9b3ae1b6..5ba46e75ffac5a 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -917,19 +917,16 @@ BOOL PEImage::IsPtrInImage(PTR_CVOID data) } #ifndef DACCESS_COMPILE -FCIMPL2(IMDInternalImport*, PEImage::ManagedBinderAcquireImport, PEImage* pPEImage, DWORD* pdwPAFlags) +extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags) { - FCALL_CONTRACT; - - _ASSERTE(pPEImage != NULL); - _ASSERTE(pdwPAFlags != NULL); + QCALL_CONTRACT; IMDInternalImport* ret = NULL; + BEGIN_QCALL; + // The same logic of BinderAcquireImport - - HELPER_METHOD_FRAME_BEGIN_RET_0(); - + PEImageLayout* pLayout = pPEImage->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); // CheckCorHeader includes check of NT headers too @@ -949,11 +946,41 @@ FCIMPL2(IMDInternalImport*, PEImage::ManagedBinderAcquireImport, PEImage* pPEIma // No AddRef - HELPER_METHOD_FRAME_END(); + END_QCALL; return ret; } -FCIMPLEND + +extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation) +{ + QCALL_CONTRACT; + + HRESULT hr = S_OK; + + BEGIN_QCALL; + + EX_TRY + { + PEImageHolder pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default, bundleFileLocation); + + // Make sure that the IL image can be opened. + hr = pImage->TryOpenFile(); + if (FAILED(hr)) + { + goto Exit; + } + + if (pImage) + *ppPEImage = pImage.Extract(); + } + EX_CATCH_HRESULT(hr); + +Exit: + + END_QCALL; + + return hr; +} extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation) { diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index 44f433ea5e64e3..5be69eedba6444 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -266,10 +266,6 @@ class PEImage final static PTR_LoaderHeap GetDllThunkHeap(void* pBase); static void UnloadIJWModule(void* pBase); -#ifndef DACCESS_COMPILE - static FCDECL2(IMDInternalImport*, ManagedBinderAcquireImport, PEImage*, DWORD*); -#endif - private: // ------------------------------------------------------------ @@ -333,6 +329,8 @@ FORCEINLINE void PEImageRelease(PEImage *i) } #ifndef DACCESS_COMPILE +extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags); +extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation); extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation); extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size); extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index b0bd164145679b..6049ee12732019 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -193,6 +193,8 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetAssemblyCount) DllImportEntry(AssemblyNative_GetEntryAssembly) DllImportEntry(AssemblyNative_GetExecutingAssembly) + DllImportEntry(PEImage_BinderAcquireImport) + DllImportEntry(PEImage_BinderAcquirePEImage) DllImportEntry(PEImage_OpenImage) DllImportEntry(PEImage_CreateFromByteArray) DllImportEntry(PEImage_CheckILFormat) From 8eb96cf9bad50cc24554bb8fadd49c662f214aac Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 17:27:50 +0800 Subject: [PATCH 044/136] Move QCalls to assemblynative and fix compilation --- src/coreclr/vm/assemblynative.cpp | 174 ++++++++++++++++++++++++++++ src/coreclr/vm/assemblynative.hpp | 22 ++++ src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/peimage.cpp | 182 ------------------------------ src/coreclr/vm/peimage.h | 16 --- 5 files changed, 197 insertions(+), 199 deletions(-) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 8d81ffd3a2a723..6dfc3b3e97aa2e 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1456,3 +1456,177 @@ extern "C" BOOL QCALLTYPE AssemblyNative_IsApplyUpdateSupported() return result; } + +extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags) +{ + QCALL_CONTRACT; + + IMDInternalImport* ret = NULL; + + BEGIN_QCALL; + + // The same logic of BinderAcquireImport + + PEImageLayout* pLayout = pPEImage->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); + + // CheckCorHeader includes check of NT headers too + if (!pLayout->CheckCorHeader()) + ThrowHR(COR_E_ASSEMBLYEXPECTED); + + if (!pLayout->CheckFormat()) + ThrowHR(COR_E_BADIMAGEFORMAT); + + pPEImage->GetPEKindAndMachine(&pdwPAFlags[0], &pdwPAFlags[1]); + + ret = pPEImage->GetMDImport(); + if (!ret) + { + ThrowHR(COR_E_BADIMAGEFORMAT); + } + + // No AddRef + + END_QCALL; + + return ret; +} + +extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation) +{ + QCALL_CONTRACT; + + HRESULT hr = S_OK; + + BEGIN_QCALL; + + EX_TRY + { + PEImageHolder pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default, bundleFileLocation); + + // Make sure that the IL image can be opened. + hr = pImage->TryOpenFile(); + if (SUCCEEDED(hr)) + { + *ppPEImage = pImage.Extract(); + } + } + EX_CATCH_HRESULT(hr); + + END_QCALL; + + return hr; +} + +extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation) +{ + QCALL_CONTRACT; + + PEImage* result = NULL; + + BEGIN_QCALL; + + result = PEImage::OpenImage(pPath, flags, bundleFileLocation); + + END_QCALL; + + return result; +} + +extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size) +{ + QCALL_CONTRACT; + + PEImage * result = NULL; + + BEGIN_QCALL; + + result = PEImage::CreateFromByteArray(array, (COUNT_T)size); + + END_QCALL; + + return result; +} + +extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BOOL result = false; + + BEGIN_QCALL; + + result = pPEImage->CheckILFormat(); + + END_QCALL; + + return result; +} + +extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BOOL result = false; + + BEGIN_QCALL; + + result = pPEImage->IsILOnly(); + + END_QCALL; + + return result; +} + +extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pPEImage->Release(); + + END_QCALL; +} + +extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pPEImage->GetMVID(pMVID); + + END_QCALL; +} + +#ifdef TARGET_WINDOWS +extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod) +{ + QCALL_CONTRACT; + + PEImage * result = NULL; + + BEGIN_QCALL; + + result = PEImage::CreateFromHMODULE(hMod); + + END_QCALL; + + return result; +} + +extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + BOOL result = false; + + BEGIN_QCALL; + + result = pPEImage->HasCorHeader(); + + END_QCALL; + + return result; +} +#endif // TARGET_WINDOWS diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 4390cf03995b65..6a5a8bd4103ccb 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -149,4 +149,26 @@ extern "C" BOOL QCALLTYPE AssemblyNative_IsApplyUpdateSupported(); extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, BaseAssemblySpec* pAssemblySpec); +extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags); + +extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation); + +extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation); + +extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size); + +extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage); + +extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage); + +extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage); + +extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID); + +#ifdef TARGET_WINDOWS +extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod); + +extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage); +#endif // TARGET_WINDOWS + #endif diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 38793d8b18a277..546e1f2e2a802d 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1197,7 +1197,7 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) // Managed binder types DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) -DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, gsig_IM_PtrChar_PtrChar_PtrChar_RetVoid) +DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes) diff --git a/src/coreclr/vm/peimage.cpp b/src/coreclr/vm/peimage.cpp index 5ba46e75ffac5a..656b42b8111c70 100644 --- a/src/coreclr/vm/peimage.cpp +++ b/src/coreclr/vm/peimage.cpp @@ -915,185 +915,3 @@ BOOL PEImage::IsPtrInImage(PTR_CVOID data) return FALSE; } - -#ifndef DACCESS_COMPILE -extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags) -{ - QCALL_CONTRACT; - - IMDInternalImport* ret = NULL; - - BEGIN_QCALL; - - // The same logic of BinderAcquireImport - - PEImageLayout* pLayout = pPEImage->GetOrCreateLayout(PEImageLayout::LAYOUT_ANY); - - // CheckCorHeader includes check of NT headers too - if (!pLayout->CheckCorHeader()) - ThrowHR(COR_E_ASSEMBLYEXPECTED); - - if (!pLayout->CheckFormat()) - ThrowHR(COR_E_BADIMAGEFORMAT); - - pPEImage->GetPEKindAndMachine(&pdwPAFlags[0], &pdwPAFlags[1]); - - ret = pPEImage->GetMDImport(); - if (!ret) - { - ThrowHR(COR_E_BADIMAGEFORMAT); - } - - // No AddRef - - END_QCALL; - - return ret; -} - -extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation) -{ - QCALL_CONTRACT; - - HRESULT hr = S_OK; - - BEGIN_QCALL; - - EX_TRY - { - PEImageHolder pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default, bundleFileLocation); - - // Make sure that the IL image can be opened. - hr = pImage->TryOpenFile(); - if (FAILED(hr)) - { - goto Exit; - } - - if (pImage) - *ppPEImage = pImage.Extract(); - } - EX_CATCH_HRESULT(hr); - -Exit: - - END_QCALL; - - return hr; -} - -extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation) -{ - QCALL_CONTRACT; - - PEImage* result = NULL; - - BEGIN_QCALL; - - result = PEImage::OpenImage(pPath, flags, bundleFileLocation); - - END_QCALL; - - return result; -} - -extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size) -{ - QCALL_CONTRACT; - - PEImage * result = NULL; - - BEGIN_QCALL; - - result = PEImage::CreateFromByteArray(array, (COUNT_T)size); - - END_QCALL; - - return result; -} - -extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BOOL result = false; - - BEGIN_QCALL; - - result = pPEImage->CheckILFormat(); - - END_QCALL; - - return result; -} - -extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BOOL result = false; - - BEGIN_QCALL; - - result = pPEImage->IsILOnly(); - - END_QCALL; - - return result; -} - -extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - pPEImage->Release(); - - END_QCALL; -} - -extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - pPEImage->GetMVID(pMVID); - - END_QCALL; -} - -#ifdef TARGET_WINDOWS -extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod) -{ - QCALL_CONTRACT; - - PEImage * result = NULL; - - BEGIN_QCALL; - - result = PEImage::CreateFromHMODULE(hMod); - - END_QCALL; - - return result; -} - -extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BOOL result = false; - - BEGIN_QCALL; - - result = pPEImage->HasCorHeader(); - - END_QCALL; - - return result; -} -#endif // TARGET_WINDOWS - -#endif // DACCESS_COMPILE diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index 5be69eedba6444..6101e163b993d7 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -19,7 +19,6 @@ #include "sstring.h" #include "holder.h" #include -#include "qcall.h" class SimpleRWLock; // -------------------------------------------------------------------------------- @@ -328,21 +327,6 @@ FORCEINLINE void PEImageRelease(PEImage *i) i->Release(); } -#ifndef DACCESS_COMPILE -extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags); -extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation); -extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation); -extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size); -extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage); -extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage); -extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage); -extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID); -#ifdef TARGET_WINDOWS -extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod); -extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage); -#endif // TARGET_WINDOWS -#endif // DACCESS_COMPILE - typedef Wrapper PEImageHolder; // ================================================================================ From 163b51cf97fb4ed0dc9b8ee359ef85581676e04a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 20:49:41 +0800 Subject: [PATCH 045/136] Store managed binder in PEAssembly --- .../src/Internal/Runtime/Binder/Assembly.cs | 10 +++- src/coreclr/vm/assembly.cpp | 2 +- src/coreclr/vm/assembly.hpp | 2 +- src/coreclr/vm/assemblynative.cpp | 9 ++- src/coreclr/vm/common.h | 2 + src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/managedbindernative.h | 29 --------- src/coreclr/vm/object.h | 34 ++++++++++- src/coreclr/vm/peassembly.cpp | 60 ++++++++++++------- src/coreclr/vm/peassembly.h | 21 +++---- src/coreclr/vm/peassembly.inl | 4 +- 11 files changed, 100 insertions(+), 75 deletions(-) delete mode 100644 src/coreclr/vm/managedbindernative.h diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 305f48ec8c7cb0..2f9c5b2c61e5c8 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -10,11 +10,17 @@ namespace Internal.Runtime.Binder // We also store whether it was bound using TPA list internal sealed class Assembly { + // fields used by VM public IntPtr PEImage; + private AssemblyBinder? m_binder; - public AssemblyName AssemblyName { get; } + public AssemblyBinder? Binder + { + get => m_binder; + set => m_binder = value; + } - public AssemblyBinder? Binder { get; set; } + public AssemblyName AssemblyName { get; } public bool IsInTPA { get; } diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index d196eee3fd9504..408ee8b06d23b4 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -368,7 +368,7 @@ Assembly * Assembly::Create( return pAssembly; } // Assembly::Create -Assembly *Assembly::CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive) +Assembly *Assembly::CreateDynamic(OBJECTHANDLE pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive) { // WARNING: not backout clean CONTRACT(Assembly *) diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index c70c85861b54fd..d104b552e67b35 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -66,7 +66,7 @@ class Assembly BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->IsSystem(); } - static Assembly* CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive); + static Assembly* CreateDynamic(OBJECTHANDLE pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive); MethodDesc *GetEntryPoint(); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 6dfc3b3e97aa2e..33bbeb0ef3ad14 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -43,15 +43,14 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p DomainAssembly * pParentAssembly = NULL; Assembly * pRefAssembly = NULL; - AssemblyBinder *pBinder = NULL; + ASSEMBLYBINDERREF pBinder = NULL; - { - GCX_COOP(); + GCX_COOP(); + { if (assemblyLoadContext.Get() != NULL) { - INT_PTR nativeAssemblyBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); - pBinder = reinterpret_cast(nativeAssemblyBinder); + pBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); } // Compute parent assembly diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index 6ebe0205951b88..5223608af31bf4 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -101,6 +101,8 @@ typedef VPTR(class AppDomain) PTR_AppDomain; typedef DPTR(class ArrayBase) PTR_ArrayBase; typedef DPTR(class Assembly) PTR_Assembly; typedef DPTR(class AssemblyBaseObject) PTR_AssemblyBaseObject; +typedef DPTR(class AssemblyBinderObject) PTR_AssemblyBinderObject; +typedef DPTR(class BinderAssemblyObject) PTR_BinderAssemblyObject; typedef DPTR(class AssemblyLoadContextBaseObject) PTR_AssemblyLoadContextBaseObject; typedef DPTR(class AssemblyBinder) PTR_AssemblyBinder; typedef DPTR(class AssemblyNameBaseObject) PTR_AssemblyNameBaseObject; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 546e1f2e2a802d..0833a80a0f9c21 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -884,7 +884,7 @@ DEFINE_FIELD_U(_resolvingUnmanagedDll, AssemblyLoadContextBaseObject, _reso DEFINE_FIELD_U(_resolving, AssemblyLoadContextBaseObject, _resolving) DEFINE_FIELD_U(_unloading, AssemblyLoadContextBaseObject, _unloading) DEFINE_FIELD_U(_name, AssemblyLoadContextBaseObject, _name) -DEFINE_FIELD_U(_nativeAssemblyLoadContext, AssemblyLoadContextBaseObject, _nativeAssemblyLoadContext) +DEFINE_FIELD_U(_assemblyBinder, AssemblyLoadContextBaseObject, _assemblyBinder) DEFINE_FIELD_U(_id, AssemblyLoadContextBaseObject, _id) DEFINE_FIELD_U(_state, AssemblyLoadContextBaseObject, _state) DEFINE_FIELD_U(_isCollectible, AssemblyLoadContextBaseObject, _isCollectible) diff --git a/src/coreclr/vm/managedbindernative.h b/src/coreclr/vm/managedbindernative.h deleted file mode 100644 index 193cf0e3e515a8..00000000000000 --- a/src/coreclr/vm/managedbindernative.h +++ /dev/null @@ -1,29 +0,0 @@ -#include "object.h" - -// managed Internal.Runtime.Binder.Assembly -class BinderAssemblyObject : public Object -{ -public: - PEImage* m_PEImage; -}; - -#ifdef USE_CHECKED_OBJECTREFS -typedef REF BINDERASSEMBLYREF; -#else // USE_CHECKED_OBJECTREFS -typedef DPTR(BinderAssemblyObject) PTR_BinderAssemblyObject; -typedef PTR_BinderAssemblyObject BINDERASSEMBLYREF; -#endif // USE_CHECKED_OBJECTREFS - - -// managed Internal.Runtime.Binder.AssemblyBinder -class AssemblyBinderObject : public Object -{ - -}; - -#ifdef USE_CHECKED_OBJECTREFS -typedef REF ASSEMBLYBINDERREF; -#else // USE_CHECKED_OBJECTREFS -typedef DPTR(AssemblyBinderObject) PTR_AssemblyBinderObject; -typedef AssemblyBinderObject ASSEMBLYBINDERREF; -#endif // USE_CHECKED_OBJECTREFS diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index bb6459a340c650..544d2ad6de5172 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1440,6 +1440,28 @@ class AssemblyBaseObject : public Object NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive); #define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive)) +// managed Internal.Runtime.Binder.AssemblyBinder +class AssemblyBinderObject : public Object +{ + +}; + +#ifdef USE_CHECKED_OBJECTREFS + +#else + +#endif + +class PEImage; + +// managed Internal.Runtime.Binder.Assembly +class BinderAssemblyObject : public Object +{ +public: + PEImage* m_PEImage; + OBJECTREF m_binder; +}; + // AssemblyLoadContextBaseObject // This class is the base class for AssemblyLoadContext // @@ -1460,7 +1482,7 @@ class AssemblyLoadContextBaseObject : public Object OBJECTREF _resolving; OBJECTREF _unloading; OBJECTREF _name; - INT_PTR _nativeAssemblyLoadContext; + OBJECTREF _assemblyBinder; int64_t _id; // On 64-bit platforms this is a value type so it is placed after references and pointers DWORD _state; CLR_BOOL _isCollectible; @@ -1471,7 +1493,7 @@ class AssemblyLoadContextBaseObject : public Object OBJECTREF _resolving; OBJECTREF _unloading; OBJECTREF _name; - INT_PTR _nativeAssemblyLoadContext; + OBJECTREF _assemblyBinder; DWORD _state; CLR_BOOL _isCollectible; #endif // TARGET_64BIT @@ -1481,7 +1503,7 @@ class AssemblyLoadContextBaseObject : public Object ~AssemblyLoadContextBaseObject() { LIMITED_METHOD_CONTRACT; } public: - INT_PTR GetNativeAssemblyBinder() { LIMITED_METHOD_CONTRACT; return _nativeAssemblyLoadContext; } + OBJECTREF GetNativeAssemblyBinder() { LIMITED_METHOD_CONTRACT; return _assemblyBinder; } }; #if defined(TARGET_X86) && !defined(TARGET_UNIX) #include "poppack.h" @@ -1525,6 +1547,10 @@ typedef REF THREADBASEREF; typedef REF ASSEMBLYREF; +typedef REF ASSEMBLYBINDERREF; + +typedef REF BINDERASSEMBLYREF; + typedef REF ASSEMBLYLOADCONTEXTREF; typedef REF ASSEMBLYNAMEREF; @@ -1569,6 +1595,8 @@ typedef PTR_ReflectMethodObject REFLECTMETHODREF; typedef PTR_ReflectFieldObject REFLECTFIELDREF; typedef PTR_ThreadBaseObject THREADBASEREF; typedef PTR_AssemblyBaseObject ASSEMBLYREF; +typedef PTR_AssemblyBinderObject ASSEMBLYBINDERREF; +typedef PTR_BinderAssemblyObject BINDERASSEMBLYREF; typedef PTR_AssemblyLoadContextBaseObject ASSEMBLYLOADCONTEXTREF; typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index c7c618b4852831..cca7d1c465489a 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -125,8 +125,10 @@ BOOL PEAssembly::Equals(PEAssembly *pPEAssembly) // because another thread beats it; the losing thread will pick up the PEAssembly in the cache. if (pPEAssembly->HasHostAssembly() && this->HasHostAssembly()) { - AssemblyBinder* otherBinder = pPEAssembly->GetHostAssembly()->GetBinder(); - AssemblyBinder* thisBinder = this->GetHostAssembly()->GetBinder(); + GCX_COOP(); + + ASSEMBLYBINDERREF otherBinder = ((BINDERASSEMBLYREF)ObjectFromHandle(pPEAssembly->GetHostAssembly()))->m_binder; + ASSEMBLYBINDERREF thisBinder = ((BINDERASSEMBLYREF)ObjectFromHandle(this->GetHostAssembly()))->m_binder; if (otherBinder != thisBinder || otherBinder == NULL) return FALSE; @@ -653,11 +655,11 @@ ULONG PEAssembly::GetPEImageTimeDateStamp() #ifndef DACCESS_COMPILE PEAssembly::PEAssembly( - BINDER_SPACE::Assembly* pBindResultInfo, + BINDERASSEMBLYREF pBindResultInfo, IMetaDataEmit* pEmit, BOOL isSystem, PEImage * pPEImage /*= NULL*/, - BINDER_SPACE::Assembly * pHostAssembly /*= NULL*/) + BINDERASSEMBLYREF pHostAssembly /*= NULL*/) { CONTRACTL { @@ -681,7 +683,7 @@ PEAssembly::PEAssembly( m_pHostAssembly = nullptr; m_pFallbackBinder = nullptr; - pPEImage = pBindResultInfo ? pBindResultInfo->GetPEImage() : pPEImage; + pPEImage = (pBindResultInfo != NULL) ? pBindResultInfo->m_PEImage : pPEImage; if (pPEImage) { _ASSERTE(pPEImage->CheckUniqueInstance()); @@ -718,17 +720,16 @@ PEAssembly::PEAssembly( // Set the host assembly and binding context as the AssemblySpec initialization // for CoreCLR will expect to have it set. - if (pHostAssembly != nullptr) + if (pHostAssembly != NULL) { - m_pHostAssembly = clr::SafeAddRef(pHostAssembly); + m_pHostAssembly = GetAppDomain()->CreateHandle(pHostAssembly); } - if(pBindResultInfo != nullptr) + if (pBindResultInfo != NULL) { // Cannot have both pHostAssembly and a coreclr based bind - _ASSERTE(pHostAssembly == nullptr); - pBindResultInfo = clr::SafeAddRef(pBindResultInfo); - m_pHostAssembly = pBindResultInfo; + _ASSERTE(m_pHostAssembly == NULL); + m_pHostAssembly = GetAppDomain()->CreateHandle(pBindResultInfo); } #ifdef LOGGING @@ -741,16 +742,16 @@ PEAssembly::PEAssembly( PEAssembly *PEAssembly::Open( PEImage * pPEImageIL, - BINDER_SPACE::Assembly * pHostAssembly) + BINDERASSEMBLYREF pManagedHostAssembly) { STANDARD_VM_CONTRACT; PEAssembly * pPEAssembly = new PEAssembly( - nullptr, // BindResult + NULL, // BindResult nullptr, // IMetaDataEmit FALSE, // isSystem pPEImageIL, - pHostAssembly); + pManagedHostAssembly); return pPEAssembly; } @@ -791,7 +792,16 @@ PEAssembly::~PEAssembly() m_PEImage->Release(); if (m_pHostAssembly != NULL) - m_pHostAssembly->Release(); + { + DestroyHandle(m_pHostAssembly); + m_pHostAssembly = NULL; + } + + if (m_pFallbackBinder != NULL) + { + DestroyHandle(m_pFallbackBinder); + m_pFallbackBinder = NULL; + } } /* static */ @@ -836,9 +846,9 @@ PEAssembly *PEAssembly::DoOpenSystem() RETURN new PEAssembly(pBoundAssembly, NULL, TRUE); } -PEAssembly* PEAssembly::Open(BINDER_SPACE::Assembly* pBindResult) +PEAssembly* PEAssembly::Open(BINDERASSEMBLYREF pManagedBindResult) { - return new PEAssembly(pBindResult,NULL,/*isSystem*/ false); + return new PEAssembly(pManagedBindResult,NULL,/*isSystem*/ false); }; /* static */ @@ -1090,16 +1100,22 @@ TADDR PEAssembly::GetMDInternalRWAddress() #endif // Returns the AssemblyBinder* instance associated with the PEAssembly -PTR_AssemblyBinder PEAssembly::GetAssemblyBinder() +ASSEMBLYBINDERREF PEAssembly::GetAssemblyBinder() { LIMITED_METHOD_CONTRACT; + + CONTRACTL + { + MODE_COOPERATIVE; + } + CONTRACTL_END - PTR_AssemblyBinder pBinder = NULL; + ASSEMBLYBINDERREF pBinder = NULL; - PTR_BINDER_SPACE_Assembly pHostAssembly = GetHostAssembly(); + OBJECTHANDLE pHostAssembly = GetHostAssembly(); if (pHostAssembly) { - pBinder = pHostAssembly->GetBinder(); + pBinder = (ASSEMBLYBINDERREF)((BINDERASSEMBLYREF)ObjectFromHandle(pHostAssembly))->m_binder; } else { @@ -1108,7 +1124,7 @@ PTR_AssemblyBinder PEAssembly::GetAssemblyBinder() // binder reference. if (IsDynamic()) { - pBinder = GetFallbackBinder(); + pBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(GetFallbackBinder()); } } diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index 5df296c4e55942..5703bedd174e81 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -301,7 +301,7 @@ class PEAssembly final } // Returns a non-AddRef'ed BINDER_SPACE::Assembly* - PTR_BINDER_SPACE_Assembly GetHostAssembly() + OBJECTHANDLE GetHostAssembly() { STATIC_CONTRACT_LIMITED_METHOD; return m_pHostAssembly; @@ -310,10 +310,10 @@ class PEAssembly final // Returns the AssemblyBinder* instance associated with the PEAssembly // which owns the context into which the current PEAssembly was loaded. // For Dynamic assemblies this is the fallback binder. - PTR_AssemblyBinder GetAssemblyBinder(); + ASSEMBLYBINDERREF GetAssemblyBinder(); #ifndef DACCESS_COMPILE - void SetFallbackBinder(PTR_AssemblyBinder pFallbackBinder) + void SetFallbackBinder(OBJECTHANDLE pFallbackBinder) { LIMITED_METHOD_CONTRACT; m_pFallbackBinder = pFallbackBinder; @@ -323,7 +323,7 @@ class PEAssembly final ULONG HashIdentity(); - PTR_AssemblyBinder GetFallbackBinder() + OBJECTHANDLE GetFallbackBinder() { LIMITED_METHOD_CONTRACT; @@ -336,12 +336,12 @@ class PEAssembly final static PEAssembly* Open( PEImage* pPEImageIL, - BINDER_SPACE::Assembly* pHostAssembly); + BINDERASSEMBLYREF pHostAssembly); // This opens the canonical System.Private.CoreLib.dll static PEAssembly* OpenSystem(); - static PEAssembly* Open(BINDER_SPACE::Assembly* pBindResult); + static PEAssembly* Open(BINDERASSEMBLYREF pBindResult); static PEAssembly* Create(IMetaDataAssemblyEmit* pEmit); @@ -370,12 +370,13 @@ class PEAssembly final ~PEAssembly() {}; PEAssembly() = default; #else + PEAssembly( - BINDER_SPACE::Assembly* pBindResultInfo, + BINDERASSEMBLYREF pBindResultInfo, IMetaDataEmit* pEmit, BOOL isSystem, PEImage* pPEImageIL = NULL, - BINDER_SPACE::Assembly* pHostAssembly = NULL + BINDERASSEMBLYREF pHostAssembly = NULL ); ~PEAssembly(); @@ -426,7 +427,7 @@ class PEAssembly final Volatile m_refCount; bool m_isSystem; - PTR_BINDER_SPACE_Assembly m_pHostAssembly; + OBJECTHANDLE m_pHostAssembly; // For certain assemblies, we do not have m_pHostAssembly since they are not bound using an actual binder. // An example is Ref-Emitted assemblies. Thus, when such assemblies trigger load of their dependencies, @@ -435,7 +436,7 @@ class PEAssembly final // To enable this, we maintain a concept of "FallbackBinder", which will be set to the Binder of the // assembly that created the dynamic assembly. If the creator assembly is dynamic itself, then its fallback // load context would be propagated to the assembly being dynamically generated. - PTR_AssemblyBinder m_pFallbackBinder; + OBJECTHANDLE m_pFallbackBinder; }; // class PEAssembly diff --git a/src/coreclr/vm/peassembly.inl b/src/coreclr/vm/peassembly.inl index e438f927f9e9e7..ce03546b3e17b1 100644 --- a/src/coreclr/vm/peassembly.inl +++ b/src/coreclr/vm/peassembly.inl @@ -92,7 +92,9 @@ inline ULONG PEAssembly::HashIdentity() GC_TRIGGERS; } CONTRACTL_END; - return m_pHostAssembly->GetAssemblyName()->Hash(BINDER_SPACE::AssemblyName::INCLUDE_VERSION); + //return m_pHostAssembly->GetAssemblyName()->Hash(BINDER_SPACE::AssemblyName::INCLUDE_VERSION); + // TODO: call managed implementation in some way + return 83079; } inline void PEAssembly::ValidateForExecution() From 6a693d03c828f8ac3fa15ca816801ee9f5ce5ff3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 21:46:58 +0800 Subject: [PATCH 046/136] Call GetLoaderAllocator --- src/coreclr/vm/assembly.cpp | 14 +++++++++++--- src/coreclr/vm/corelib.h | 3 +++ src/coreclr/vm/object.h | 6 ++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 408ee8b06d23b4..fb414cead891ad 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -454,14 +454,22 @@ Assembly *Assembly::CreateDynamic(OBJECTHANDLE pBinder, NativeAssemblyNameParts* BOOL createdNewAssemblyLoaderAllocator = FALSE; { - GCX_PREEMP(); - AssemblyLoaderAllocator* pBinderLoaderAllocator = nullptr; if (pBinder != nullptr) { - pBinderLoaderAllocator = pBinder->GetLoaderAllocator(); + ASSEMBLYBINDERREF binderObj = (ASSEMBLYBINDERREF)ObjectFromHandle(pBinder); + MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); + ARG_SLOT args[1] = + { + ObjToArgSlot(binderObj) + }; + LOADERALLOCATORREF managedLA = (LOADERALLOCATORREF)methGetLoaderAllocator.Call_RetOBJECTREF(args); + + pBinderLoaderAllocator = (AssemblyLoaderAllocator*)managedLA->GetNativeLoaderAllocator(); } + GCX_PREEMP(); + // Create a new LoaderAllocator if appropriate if ((access & ASSEMBLY_ACCESS_COLLECT) != 0) { diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 0833a80a0f9c21..405bf42e661001 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1195,6 +1195,9 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) #endif // FOR_ILLINK // Managed binder types +DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetObj) + DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 544d2ad6de5172..eed410029b4774 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -2273,6 +2273,12 @@ class LoaderAllocatorObject : public Object m_pLoaderAllocatorScout->m_nativeLoaderAllocator = pLoaderAllocator; } + LoaderAllocator* GetNativeLoaderAllocator() + { + LIMITED_METHOD_CONTRACT; + return m_pLoaderAllocatorScout->m_nativeLoaderAllocator; + } + // README: // If you modify the order of these fields, make sure to update the definition in // BCL for this object. From 6cf329f73227863eba5170cb05d6bc226cb1ed09 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 9 Sep 2023 22:00:49 +0800 Subject: [PATCH 047/136] Set DomainAssembly --- .../src/Internal/Runtime/Binder/Assembly.cs | 4 +++- src/coreclr/vm/domainassembly.cpp | 6 ++++-- src/coreclr/vm/object.h | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 2f9c5b2c61e5c8..15c9d75bfd5a6b 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -11,8 +11,11 @@ namespace Internal.Runtime.Binder internal sealed class Assembly { // fields used by VM +#pragma warning disable CA1823, 414, 169 public IntPtr PEImage; + private IntPtr m_pDomainAssembly; private AssemblyBinder? m_binder; +#pragma warning restore CA1823, 414, 169 public AssemblyBinder? Binder { @@ -24,7 +27,6 @@ public AssemblyBinder? Binder public bool IsInTPA { get; } - // private IntPtr _domainAssembly; // DomainAssembly* public Assembly(nint pPEImage, bool isInTPA) { diff --git a/src/coreclr/vm/domainassembly.cpp b/src/coreclr/vm/domainassembly.cpp index 52a9b5bcbe01d2..7f5bec72c0f0e9 100644 --- a/src/coreclr/vm/domainassembly.cpp +++ b/src/coreclr/vm/domainassembly.cpp @@ -731,7 +731,8 @@ void DomainAssembly::RegisterWithHostAssembly() if (GetPEAssembly()->HasHostAssembly()) { - GetPEAssembly()->GetHostAssembly()->SetDomainAssembly(this); + GCX_COOP(); + ((BINDERASSEMBLYREF)ObjectFromHandle(GetPEAssembly()->GetHostAssembly()))->m_pDomainAssembly = this; } } @@ -747,7 +748,8 @@ void DomainAssembly::UnregisterFromHostAssembly() if (GetPEAssembly()->HasHostAssembly()) { - GetPEAssembly()->GetHostAssembly()->SetDomainAssembly(nullptr); + GCX_COOP(); + ((BINDERASSEMBLYREF)ObjectFromHandle(GetPEAssembly()->GetHostAssembly()))->m_pDomainAssembly = nullptr; } } diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index eed410029b4774..f78a97d75c0cdb 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1459,6 +1459,7 @@ class BinderAssemblyObject : public Object { public: PEImage* m_PEImage; + DomainAssembly* m_pDomainAssembly; OBJECTREF m_binder; }; From 14490790e0bd450a19134790cd4a42f43233e8aa Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 10 Sep 2023 01:35:19 +0800 Subject: [PATCH 048/136] Use binder in native --- src/coreclr/binder/bindertracing.cpp | 2 +- src/coreclr/vm/appdomain.cpp | 7 +++++-- src/coreclr/vm/assemblybinder.cpp | 2 +- src/coreclr/vm/excep.cpp | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index 062f934828e681..f9afba7e4e0417 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -95,7 +95,7 @@ namespace _ASSERTE(pPEAssembly != nullptr); pPEAssembly->GetDisplayName(request.RequestingAssembly); - AssemblyBinder *binder = pPEAssembly->GetAssemblyBinder(); + AssemblyBinder *binder = /*pPEAssembly->GetAssemblyBinder()*/ NULL; binder->GetNameForDiagnostics(request.RequestingAssemblyLoadContext); } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 1af2fb64f4b740..6b965c98f7e521 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3079,7 +3079,9 @@ DomainAssembly * AppDomain::FindAssembly(PEAssembly * pPEAssembly, FindAssemblyO if (pPEAssembly->HasHostAssembly()) { - DomainAssembly * pDA = pPEAssembly->GetHostAssembly()->GetDomainAssembly(); + GCX_COOP(); + + DomainAssembly * pDA = ((BINDERASSEMBLYREF)ObjectFromHandle(pPEAssembly->GetHostAssembly()))->m_pDomainAssembly; if (pDA != nullptr && (pDA->IsLoaded() || (includeFailedToLoad && pDA->IsError()))) { return pDA; @@ -5073,7 +5075,8 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB pParentLoaderAllocator->EnsureReference(pResultAssemblyLoaderAllocator); } - pResolvedAssembly = pLoadedPEAssembly->GetHostAssembly(); + // unused with managed binder + // pResolvedAssembly = pLoadedPEAssembly->GetHostAssembly(); } if (fResolvedAssembly) diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index f3322b196d3ee1..e9a103f78678f7 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -32,7 +32,7 @@ NativeImage* AssemblyBinder::LoadNativeImage(Module* componentModule, LPCUTF8 na STANDARD_VM_CONTRACT; BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); - AssemblyBinder* binder = componentModule->GetPEAssembly()->GetAssemblyBinder(); + AssemblyBinder* binder = /* componentModule->GetPEAssembly()->GetAssemblyBinder() */ NULL; PTR_LoaderAllocator moduleLoaderAllocator = componentModule->GetLoaderAllocator(); bool isNewNativeImage; diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 1c22e7f182a5a9..aad981362cfadd 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -11708,7 +11708,8 @@ VOID GetAssemblyDetailInfo(SString &sType, SString detailsUtf8; SString sAlcName; - pPEAssembly->GetAssemblyBinder()->GetNameForDiagnostics(sAlcName); + // TODO: print managed alc name + // pPEAssembly->GetAssemblyBinder()->GetNameForDiagnostics(sAlcName); SString assemblyPath{ pPEAssembly->GetPath() }; if (assemblyPath.IsEmpty()) { From 0a021edd0db0323764331cd72042222f5516e0ea Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 14 Sep 2023 21:22:03 +0800 Subject: [PATCH 049/136] Use more in native --- src/coreclr/vm/appdomain.cpp | 47 ++++++++++++++++++++++++------- src/coreclr/vm/assemblybinder.cpp | 2 +- src/coreclr/vm/assemblyspec.hpp | 8 +++--- src/coreclr/vm/baseassemblyspec.h | 6 ++-- src/coreclr/vm/ceeload.cpp | 10 ++++--- src/coreclr/vm/ceeload.h | 4 +-- src/coreclr/vm/corelib.h | 1 + 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 6b965c98f7e521..d447f14cb4028f 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -2662,16 +2662,18 @@ DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec, Exception* pEx = GET_EXCEPTION(); if (!pEx->IsTransient()) { + GCX_COOP(); + // Setup the binder reference in AssemblySpec from the PEAssembly if one is not already set. - AssemblyBinder* pCurrentBinder = pSpec->GetBinder(); - AssemblyBinder* pBinderFromPEAssembly = pPEAssembly->GetAssemblyBinder(); + ASSEMBLYBINDERREF pCurrentBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pSpec->GetBinder()); + ASSEMBLYBINDERREF pBinderFromPEAssembly = pPEAssembly->GetAssemblyBinder(); if (pCurrentBinder == NULL) { // Set the binding context we got from the PEAssembly if AssemblySpec does not // have that information _ASSERTE(pBinderFromPEAssembly != NULL); - pSpec->SetBinder(pBinderFromPEAssembly); + pSpec->SetBinder(CreateHandle(pBinderFromPEAssembly)); } #if defined(_DEBUG) else @@ -2729,15 +2731,32 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (result == NULL) { + LoaderAllocator *pLoaderAllocator = NULL; - AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); - // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if - // marked as collectible - pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator(); - if (pLoaderAllocator == NULL) { - pLoaderAllocator = this->GetLoaderAllocator(); + GCX_COOP(); + ASSEMBLYBINDERREF pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); + + // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if + // marked as collectible + + MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); + ARG_SLOT args[1] = + { + ObjToArgSlot(pAssemblyBinder) + }; + + LOADERALLOCATORREF pManagedLA = (LOADERALLOCATORREF)methGetLoaderAllocator.Call_RetOBJECTREF(args); + if (pManagedLA != NULL) + { + pLoaderAllocator = pManagedLA->GetNativeLoaderAllocator(); + } + + if (pLoaderAllocator == NULL) + { + pLoaderAllocator = this->GetLoaderAllocator(); + } } // Allocate the DomainAssembly a bit early to avoid GC mode problems. We could potentially avoid @@ -2790,7 +2809,15 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (registerNewAssembly) { - pPEAssembly->GetAssemblyBinder()->AddLoadedAssembly(pDomainAssembly->GetAssembly()); + GCX_COOP(); + + MethodDescCallSite methAddLoadedAssem(METHOD__BINDER_ASSEMBLYBINDER__ADDLOADEDASSEMBLY); + ARG_SLOT args[2] = + { + ObjToArgSlot(pPEAssembly->GetAssemblyBinder()), + PtrToArgSlot(pDomainAssembly->GetAssembly()) + }; + methAddLoadedAssem.Call(args); } } else diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index e9a103f78678f7..b0fa63b2417c6b 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -212,7 +212,7 @@ void AssemblyBinder::GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ S _ASSERTE(spec != nullptr); AppDomain* domain = spec->GetAppDomain(); - AssemblyBinder* binder = spec->GetBinder(); + AssemblyBinder* binder = /* spec->GetBinder() */ NULL; if (binder == nullptr) binder = spec->GetBinderFromParentAssembly(domain); diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index a39b7123597118..dd34b8e49c8242 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -31,7 +31,7 @@ class AssemblySpec : public BaseAssemblySpec DomainAssembly *m_pParentAssembly; // Contains the reference to the fallback load context associated with RefEmitted assembly requesting the load of another assembly (static or dynamic) - AssemblyBinder *m_pFallbackBinder; + OBJECTHANDLE m_pFallbackBinder; // Flag to indicate if we should prefer the fallback load context binder for binding or not. bool m_fPreferFallbackBinder; @@ -46,7 +46,7 @@ class AssemblySpec : public BaseAssemblySpec mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride, BOOL fDoNotUtilizeExtraChecks, - AssemblyBinder *pBinderForLoadedAssembly); + OBJECTHANDLE pBinderForLoadedAssembly); public: @@ -116,14 +116,14 @@ class AssemblySpec : public BaseAssemblySpec m_pParentAssembly = pAssembly; } - void SetFallbackBinderForRequestingAssembly(AssemblyBinder *pFallbackBinder) + void SetFallbackBinderForRequestingAssembly(OBJECTHANDLE pFallbackBinder) { LIMITED_METHOD_CONTRACT; m_pFallbackBinder = pFallbackBinder; } - AssemblyBinder* GetFallbackBinderForRequestingAssembly() + OBJECTHANDLE GetFallbackBinderForRequestingAssembly() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/baseassemblyspec.h b/src/coreclr/vm/baseassemblyspec.h index 77180a3db980e8..d216d97eeeb493 100644 --- a/src/coreclr/vm/baseassemblyspec.h +++ b/src/coreclr/vm/baseassemblyspec.h @@ -26,7 +26,7 @@ class BaseAssemblySpec DWORD m_cbPublicKeyOrToken; DWORD m_dwFlags; // CorAssemblyFlags int m_ownedFlags; - AssemblyBinder *m_pBinder; + OBJECTHANDLE m_pBinder; public: enum @@ -60,14 +60,14 @@ class BaseAssemblySpec VOID CloneFields(); VOID CloneFieldsToLoaderHeap(LoaderHeap *pHeap, AllocMemTracker *pamTracker); - inline void SetBinder(AssemblyBinder *pBinder) + inline void SetBinder(OBJECTHANDLE pBinder) { LIMITED_METHOD_CONTRACT; m_pBinder = pBinder; } - inline AssemblyBinder* GetBinder() + inline OBJECTHANDLE GetBinder() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index f3e3a882d3878a..392980744e68dc 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -2838,7 +2838,7 @@ Module::GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride, // = NULL BOOL fDoNotUtilizeExtraChecks, // = FALSE - AssemblyBinder *pBinderForLoadedAssembly // = NULL + OBJECTHANDLE pBinderForLoadedAssembly // = NULL ) { CONTRACT(Assembly *) @@ -3023,20 +3023,22 @@ DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) // Set the binding context in the AssemblySpec if one is available. This can happen if the LoadAssembly ended up // invoking the custom AssemblyLoadContext implementation that returned a reference to an assembly bound to a different // AssemblyLoadContext implementation. - AssemblyBinder *pBinder = pPEAssembly->GetAssemblyBinder(); + GCX_COOP(); + ASSEMBLYBINDERREF pBinder = pPEAssembly->GetAssemblyBinder(); if (pBinder != NULL) { - spec.SetBinder(pBinder); + spec.SetBinder(GetDomain()->CreateHandle(pBinder)); } pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); } if (pDomainAssembly != NULL) { + GCX_COOP(); _ASSERTE( pDomainAssembly->IsSystem() || // GetAssemblyIfLoaded will not find CoreLib (see AppDomain::FindCachedFile) !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies - GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetPEAssembly()->GetHostAssembly()->GetBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases + GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, GetDomain()->CreateHandle(((BINDERASSEMBLYREF)ObjectFromHandle(pDomainAssembly->GetPEAssembly()->GetHostAssembly()))->m_binder)) != NULL); // GetAssemblyIfLoaded should find all remaining cases if (pDomainAssembly->GetAssembly() != NULL) { diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index 4d714d2024196d..88d974f30f2744 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -558,7 +558,7 @@ class ModuleBase mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride = NULL, BOOL fDoNotUtilizeExtraChecks = FALSE, - AssemblyBinder *pBinderForLoadedAssembly = NULL + OBJECTHANDLE pBinderForLoadedAssembly = NULL ) { LIMITED_METHOD_DAC_CONTRACT; @@ -1184,7 +1184,7 @@ class Module : public ModuleBase mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride = NULL, BOOL fDoNotUtilizeExtraChecks = FALSE, - AssemblyBinder *pBinderForLoadedAssembly = NULL + OBJECTHANDLE pBinderForLoadedAssembly = NULL ) final; protected: diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 405bf42e661001..a9e8024a82d56b 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1197,6 +1197,7 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) // Managed binder types DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetObj) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_VoidPtr_RetVoid) DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) From 1fecd662eb02150d5179edbdf3091820cc9bfc60 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 16 Sep 2023 19:58:09 +0800 Subject: [PATCH 050/136] Use more in native --- src/coreclr/vm/appdomain.cpp | 29 ++++++++++++++------------ src/coreclr/vm/assemblynative.cpp | 34 +++++++++++++++++++++---------- src/coreclr/vm/assemblynative.hpp | 2 +- src/coreclr/vm/assemblyspec.cpp | 8 ++++---- src/coreclr/vm/assemblyspec.hpp | 2 +- src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/metasig.h | 1 + src/coreclr/vm/peassembly.cpp | 5 +++-- 8 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index d447f14cb4028f..67249712187ee8 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -2735,22 +2735,25 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, LoaderAllocator *pLoaderAllocator = NULL; { - GCX_COOP(); - ASSEMBLYBINDERREF pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); + if (!pPEAssembly->IsSystem()) + { + GCX_COOP(); + ASSEMBLYBINDERREF pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); - // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if - // marked as collectible + // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if + // marked as collectible - MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); - ARG_SLOT args[1] = - { - ObjToArgSlot(pAssemblyBinder) - }; + MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); + ARG_SLOT args[1] = + { + ObjToArgSlot(pAssemblyBinder) + }; - LOADERALLOCATORREF pManagedLA = (LOADERALLOCATORREF)methGetLoaderAllocator.Call_RetOBJECTREF(args); - if (pManagedLA != NULL) - { - pLoaderAllocator = pManagedLA->GetNativeLoaderAllocator(); + LOADERALLOCATORREF pManagedLA = (LOADERALLOCATORREF)methGetLoaderAllocator.Call_RetOBJECTREF(args); + if (pManagedLA != NULL) + { + pLoaderAllocator = pManagedLA->GetNativeLoaderAllocator(); + } } if (pLoaderAllocator == NULL) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 33bbeb0ef3ad14..c1ce0cacb891c3 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -122,19 +122,19 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p } /* static */ -Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths) +Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pImage, bool excludeAppPaths) { CONTRACT(Assembly*) { STANDARD_VM_CHECK; - PRECONDITION(CheckPointer(pBinder)); + PRECONDITION(pBinder != NULL); PRECONDITION(pImage != NULL); POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; Assembly *pLoadedAssembly = NULL; - ReleaseHolder pAssembly; + BINDERASSEMBLYREF pAssembly; // Set the caller's assembly to be CoreLib DomainAssembly *pCallersAssembly = SystemDomain::System()->SystemAssembly()->GetDomainAssembly(); @@ -142,13 +142,22 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma // Initialize the AssemblySpec AssemblySpec spec; spec.InitializeSpec(TokenFromRid(1, mdtAssembly), pImage->GetMDImport(), pCallersAssembly); - spec.SetBinder(pBinder); + spec.SetBinder(GetAppDomain()->CreateHandle(pBinder)); BinderTracing::AssemblyBindOperation bindOperation(&spec, pImage->GetPath()); HRESULT hr = S_OK; PTR_AppDomain pCurDomain = GetAppDomain(); - hr = pBinder->BindUsingPEImage(pImage, excludeAppPaths, &pAssembly); + + MethodDescCallSite methBind(METHOD__BINDER_ASSEMBLYBINDER__BINDUSINGPEIMAGE); + ARG_SLOT args[4] = + { + ObjToArgSlot(pBinder), + PtrToArgSlot(pImage), + BoolToArgSlot(excludeAppPaths), + PtrToArgSlot(&pAssembly) + }; + hr = methBind.Call_RetHR(args); if (hr != S_OK) { @@ -170,13 +179,14 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma } } - PEAssemblyHolder pPEAssembly(PEAssembly::Open(pAssembly->GetPEImage(), pAssembly)); + PEAssemblyHolder pPEAssembly(PEAssembly::Open(pAssembly->m_PEImage, pAssembly)); bindOperation.SetResult(pPEAssembly.GetValue()); DomainAssembly *pDomainAssembly = pCurDomain->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); RETURN pDomainAssembly->GetAssembly(); } +// unused extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; @@ -211,7 +221,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB } } - Assembly *pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); + Assembly *pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; { GCX_COOP(); @@ -226,6 +236,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB } /*static */ +// unused extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly) @@ -256,7 +267,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl } // Pass the stream based assembly as IL in an attempt to bind and load it - Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); + Assembly* pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; { GCX_COOP(); retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); @@ -292,6 +303,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl #ifdef TARGET_WINDOWS /*static */ +// unused extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; @@ -312,7 +324,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativ AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); // Pass the in memory module as IL in an attempt to bind and load it - Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); + Assembly* pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; { GCX_COOP(); retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); @@ -1179,7 +1191,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH } /*static*/ - +// unused extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible) { QCALL_CONTRACT; @@ -1194,7 +1206,7 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PT // Initialize the assembly binder instance in the VM PTR_AppDomain pCurDomain = AppDomain::GetCurrentDomain(); - DefaultAssemblyBinder *pDefaultBinder = pCurDomain->GetDefaultBinder(); + DefaultAssemblyBinder *pDefaultBinder = /*pCurDomain->GetDefaultBinder()*/ NULL; if (!fRepresentsTPALoadContext) { // Initialize a custom assembly binder diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 6a5a8bd4103ccb..3e2ea6fffe1375 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -25,7 +25,7 @@ class AssemblyNative public: - static Assembly* LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths = false); + static Assembly* LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pImage, bool excludeAppPaths = false); // static FCALLs static FCDECL0(FC_BOOL_RET, IsTracingEnabled); diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index abad61ac7d5d36..0a7c98ff4b8c23 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -365,7 +365,7 @@ Assembly *AssemblySpec::LoadAssembly(FileLoadLevel targetLevel, BOOL fThrowOnFil return pDomainAssembly->GetAssembly(); } -AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) +ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) { CONTRACTL { @@ -376,7 +376,7 @@ AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) } CONTRACTL_END; - AssemblyBinder *pParentAssemblyBinder = NULL; + ASSEMBLYBINDERREF pParentAssemblyBinder = NULL; DomainAssembly *pParentDomainAssembly = GetParentAssembly(); if(pParentDomainAssembly != NULL) @@ -408,7 +408,7 @@ AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) // // For (3), fetch the fallback load context binder reference. - pParentAssemblyBinder = GetFallbackBinderForRequestingAssembly(); + pParentAssemblyBinder = ObjectFromHandle(GetFallbackBinderForRequestingAssembly()); } if (!pParentAssemblyBinder) @@ -418,7 +418,7 @@ AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) // // In such a case, the parent assembly (semantically) is CoreLibrary and thus, the default binding context should be // used as the parent assembly binder. - pParentAssemblyBinder = static_cast(pDomain->GetDefaultBinder()); + pParentAssemblyBinder = ObjectFromHandle(pDomain->GetDefaultBinder()); } return pParentAssemblyBinder; diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index dd34b8e49c8242..4028eebca4cb11 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -75,7 +75,7 @@ class AssemblySpec : public BaseAssemblySpec DomainAssembly* GetParentAssembly(); - AssemblyBinder* GetBinderFromParentAssembly(AppDomain *pDomain); + ASSEMBLYBINDERREF GetBinderFromParentAssembly(AppDomain *pDomain); bool HasParentAssembly() { WRAPPER_NO_CONTRACT; return GetParentAssembly() != NULL; } diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index a9e8024a82d56b..ed5e8002d1aabd 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1198,6 +1198,7 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetObj) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_VoidPtr_RetVoid) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefObj_RetInt) DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 5eefa37dff09e8..a4b2547e1e50b5 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -617,6 +617,7 @@ DEFINE_METASIG(SM(Str_RetPtrByte, s, P(b))) DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) +DEFINE_METASIG(IM(IntPtr_Bool_RefObj_RetInt, I F r(j), i)) // Undefine macros in case we include the file again in the compilation unit diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index cca7d1c465489a..03341fd19a46fc 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -841,9 +841,10 @@ PEAssembly *PEAssembly::DoOpenSystem() ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1); ReleaseHolder pBoundAssembly; - IfFailThrow(GetAppDomain()->GetDefaultBinder()->BindToSystem(&pBoundAssembly)); + IfFailThrow(((DefaultAssemblyBinder*)NULL)->BindToSystem(&pBoundAssembly)); - RETURN new PEAssembly(pBoundAssembly, NULL, TRUE); + // TODO: Is HostAssembly ever used for CoreLib? + RETURN new PEAssembly(NULL, NULL, TRUE); } PEAssembly* PEAssembly::Open(BINDERASSEMBLYREF pManagedBindResult) From c37ec2ec6e7172b492a2e60a12d2c753f8d316eb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Sep 2023 00:53:45 +0800 Subject: [PATCH 051/136] AssemblySpec --- .../src/Internal/Runtime/Binder/Assembly.cs | 3 + .../Internal/Runtime/Binder/AssemblyBinder.cs | 4 +- .../Internal/Runtime/Binder/AssemblyName.cs | 22 +- src/coreclr/vm/appdomain.cpp | 10 +- src/coreclr/vm/assemblybinder.cpp | 6 +- src/coreclr/vm/assemblyspec.cpp | 415 +++++++++--------- src/coreclr/vm/assemblyspec.hpp | 2 +- src/coreclr/vm/coreassemblyspec.cpp | 21 +- src/coreclr/vm/corelib.h | 4 + src/coreclr/vm/metasig.h | 1 + src/coreclr/vm/object.h | 1 + 11 files changed, 256 insertions(+), 233 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 15c9d75bfd5a6b..a99fda17e42d7b 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -15,6 +15,7 @@ internal sealed class Assembly public IntPtr PEImage; private IntPtr m_pDomainAssembly; private AssemblyBinder? m_binder; + private bool m_isCoreLib; #pragma warning restore CA1823, 414, 169 public AssemblyBinder? Binder @@ -36,6 +37,8 @@ public Assembly(nint pPEImage, bool isInTPA) IsDefinition = true }; + m_isCoreLib = AssemblyName.IsCoreLib; + // validate architecture if (!AssemblyBinderCommon.IsValidArchitecture(AssemblyName.ProcessorArchitecture)) { diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index e45899440fdb31..6f58fda257428d 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -31,9 +31,9 @@ internal readonly unsafe struct AssemblyNameData internal abstract class AssemblyBinder { - public int BindAssemblyByName(in AssemblyNameData pAssemblyNameData, out Assembly? assembly) + public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) { - return BindUsingAssemblyName(new AssemblyName(pAssemblyNameData), out assembly); + return BindUsingAssemblyName(new AssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); } public abstract int BindUsingPEImage(IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index adb6798132eb2c..99e030f8764031 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -165,20 +165,20 @@ public AssemblyName(IntPtr pPEImage) } } - public AssemblyName(in AssemblyNameData data) + public unsafe AssemblyName(AssemblyNameData* data) { - AssemblyIdentityFlags flags = data.IdentityFlags; - SimpleName = new MdUtf8String(data.Name).ToString(); + AssemblyIdentityFlags flags = data->IdentityFlags; + SimpleName = new MdUtf8String(data->Name).ToString(); Version = new AssemblyVersion { - Major = data.MajorVersion, - Minor = data.MinorVersion, - Build = data.BuildNumber, - Revision = data.RevisionNumber + Major = data->MajorVersion, + Minor = data->MinorVersion, + Build = data->BuildNumber, + Revision = data->RevisionNumber }; - CultureOrLanguage = new MdUtf8String(data.Culture).ToString(); + CultureOrLanguage = new MdUtf8String(data->Culture).ToString(); - PublicKeyOrTokenBLOB = new ReadOnlySpan(data.PublicKeyOrToken, data.PublicKeyOrTokenLength).ToArray(); + PublicKeyOrTokenBLOB = new ReadOnlySpan(data->PublicKeyOrToken, data->PublicKeyOrTokenLength).ToArray(); if ((flags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0) { // Convert public key to token @@ -191,8 +191,8 @@ public AssemblyName(in AssemblyNameData data) flags |= AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN; } - ProcessorArchitecture = data.ProcessorArchitecture; - ContentType = data.ContentType; + ProcessorArchitecture = data->ProcessorArchitecture; + ContentType = data->ContentType; IdentityFlags = flags; } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 67249712187ee8..eb8ec1db80eb1d 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3561,12 +3561,12 @@ PEAssembly * AppDomain::BindAssemblySpec( { { - ReleaseHolder boundAssembly; + BINDERASSEMBLYREF boundAssembly; hrBindResult = pSpec->Bind(this, &boundAssembly); - if (boundAssembly) + if (boundAssembly != NULL) { - if (SystemDomain::SystemPEAssembly() && boundAssembly->GetAssemblyName()->IsCoreLib()) + if (SystemDomain::SystemPEAssembly() && boundAssembly->m_isCoreLib) { // Avoid rebinding to another copy of CoreLib result = SystemDomain::SystemPEAssembly(); @@ -3579,9 +3579,9 @@ PEAssembly * AppDomain::BindAssemblySpec( } // Setup the reference to the binder, which performed the bind, into the AssemblySpec - AssemblyBinder* pBinder = result->GetAssemblyBinder(); + ASSEMBLYBINDERREF pBinder = result->GetAssemblyBinder(); _ASSERTE(pBinder != NULL); - pSpec->SetBinder(pBinder); + pSpec->SetBinder(CreateHandle(pBinder)); // Failure to add simply means someone else beat us to it. In that case // the FindCachedFile call below (after catch block) will update result diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index b0fa63b2417c6b..6e1f96eb5bb08a 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -213,10 +213,10 @@ void AssemblyBinder::GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ S AppDomain* domain = spec->GetAppDomain(); AssemblyBinder* binder = /* spec->GetBinder() */ NULL; - if (binder == nullptr) - binder = spec->GetBinderFromParentAssembly(domain); + //if (binder == nullptr) + // binder = spec->GetBinderFromParentAssembly(domain); - binder->GetNameForDiagnostics(alcName); + //binder->GetNameForDiagnostics(alcName); } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 0a7c98ff4b8c23..be9eca0f26b695 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -205,13 +205,13 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) InitializeSpec(a, pImport, NULL); // Set the binding context for the AssemblySpec - AssemblyBinder* pCurrentBinder = GetBinder(); + OBJECTHANDLE pCurrentBinder = GetBinder(); if (pCurrentBinder == NULL) { - AssemblyBinder* pExpectedBinder = pFile->GetAssemblyBinder(); + ASSEMBLYBINDERREF pExpectedBinder = pFile->GetAssemblyBinder(); // We should always have the binding context in the PEAssembly. _ASSERTE(pExpectedBinder != NULL); - SetBinder(pExpectedBinder); + SetBinder(GetAppDomain()->CreateHandle(pExpectedBinder)); } } @@ -511,7 +511,7 @@ Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath) if (!pILImage->CheckILFormat()) THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue()); - RETURN AssemblyNative::LoadFromPEImage(AppDomain::GetCurrentDomain()->GetDefaultBinder(), pILImage, true /* excludeAppPaths */); + RETURN AssemblyNative::LoadFromPEImage((ASSEMBLYBINDERREF)ObjectFromHandle(AppDomain::GetCurrentDomain()->GetDefaultBinder()), pILImage, true /* excludeAppPaths */); } HRESULT AssemblySpec::CheckFriendAssemblyName() @@ -687,46 +687,48 @@ AssemblySpecBindingCache::AssemblyBinding* AssemblySpecBindingCache::LookupInter } CONTRACTL_END; - UPTR key = (UPTR)pSpec->Hash(); + return (AssemblyBinding *) INVALIDENTRY; - AssemblyBinder *pBinderForLookup = NULL; - bool fGetBindingContextFromParent = true; + //UPTR key = (UPTR)pSpec->Hash(); - // Check if the AssemblySpec already has specified its binding context. This will be set for assemblies that are - // attempted to be explicitly bound using AssemblyLoadContext LoadFrom* methods. - pBinderForLookup = pSpec->GetBinder(); + //AssemblyBinder *pBinderForLookup = NULL; + //bool fGetBindingContextFromParent = true; - if (pBinderForLookup != NULL) - { - // We are working with the actual binding context in which the assembly was expected to be loaded. - // Thus, we don't need to get it from the parent assembly. - fGetBindingContextFromParent = false; - } + //// Check if the AssemblySpec already has specified its binding context. This will be set for assemblies that are + //// attempted to be explicitly bound using AssemblyLoadContext LoadFrom* methods. + //pBinderForLookup = pSpec->GetBinder(); - if (fGetBindingContextFromParent) - { - pBinderForLookup = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); - pSpec->SetBinder(pBinderForLookup); - } + //if (pBinderForLookup != NULL) + //{ + // // We are working with the actual binding context in which the assembly was expected to be loaded. + // // Thus, we don't need to get it from the parent assembly. + // fGetBindingContextFromParent = false; + //} - if (pBinderForLookup) - { - key = key ^ (UPTR)pBinderForLookup; - } + //if (fGetBindingContextFromParent) + //{ + // pBinderForLookup = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); + // pSpec->SetBinder(pBinderForLookup); + //} - AssemblyBinding* pEntry = (AssemblyBinding *)m_map.LookupValue(key, pSpec); + //if (pBinderForLookup) + //{ + // key = key ^ (UPTR)pBinderForLookup; + //} - // Reset the binding context if one was originally never present in the AssemblySpec and we didnt find any entry - // in the cache. - if (fGetBindingContextFromParent) - { - if (pEntry == (AssemblyBinding *) INVALIDENTRY) - { - pSpec->SetBinder(NULL); - } - } + //AssemblyBinding* pEntry = (AssemblyBinding *)m_map.LookupValue(key, pSpec); + + //// Reset the binding context if one was originally never present in the AssemblySpec and we didnt find any entry + //// in the cache. + //if (fGetBindingContextFromParent) + //{ + // if (pEntry == (AssemblyBinding *) INVALIDENTRY) + // { + // pSpec->SetBinder(NULL); + // } + //} - return pEntry; + //return pEntry; } BOOL AssemblySpecBindingCache::Contains(AssemblySpec *pSpec) @@ -918,63 +920,64 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly } CONTRACT_END; - UPTR key = (UPTR)pSpec->Hash(); - - AssemblyBinder* pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); - key = key ^ (UPTR)pBinderContextForLookup; - - if (!pSpec->GetBinder()) - { - pSpec->SetBinder(pBinderContextForLookup); - } - - AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); - - if (entry == (AssemblyBinding *) INVALIDENTRY) - { - AssemblyBindingHolder abHolder; - - LoaderHeap* pHeap = m_pHeap; - if (pAssembly->IsCollectible()) - { - pHeap = pAssembly->GetLoaderAllocator()->GetHighFrequencyHeap(); - } - - entry = abHolder.CreateAssemblyBinding(pHeap); - entry->Init(pSpec,pAssembly->GetPEAssembly(),pAssembly,NULL,pHeap, abHolder.GetPamTracker()); - - m_map.InsertValue(key, entry); - - abHolder.SuppressRelease(); - - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreAssembly): Add cached entry (%p) with PEAssembly %p",entry,pAssembly->GetPEAssembly()); - RETURN TRUE; - } - else - { - if (!entry->IsError()) - { - if (entry->GetAssembly() != NULL) - { - // OK if this is a duplicate - if (entry->GetAssembly() == pAssembly) - RETURN TRUE; - } - else - { - // OK if we have a matching PEAssembly - if (entry->GetFile() != NULL - && pAssembly->GetPEAssembly()->Equals(entry->GetFile())) - { - entry->SetAssembly(pAssembly); - RETURN TRUE; - } - } - } - - // Invalid cache transition (see above note about state transitions) - RETURN FALSE; - } + //UPTR key = (UPTR)pSpec->Hash(); + + //AssemblyBinder* pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + //key = key ^ (UPTR)pBinderContextForLookup; + + //if (!pSpec->GetBinder()) + //{ + // pSpec->SetBinder(pBinderContextForLookup); + //} + + //AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); + + //if (entry == (AssemblyBinding *) INVALIDENTRY) + //{ + // AssemblyBindingHolder abHolder; + + // LoaderHeap* pHeap = m_pHeap; + // if (pAssembly->IsCollectible()) + // { + // pHeap = pAssembly->GetLoaderAllocator()->GetHighFrequencyHeap(); + // } + + // entry = abHolder.CreateAssemblyBinding(pHeap); + // entry->Init(pSpec,pAssembly->GetPEAssembly(),pAssembly,NULL,pHeap, abHolder.GetPamTracker()); + + // m_map.InsertValue(key, entry); + + // abHolder.SuppressRelease(); + + // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreAssembly): Add cached entry (%p) with PEAssembly %p",entry,pAssembly->GetPEAssembly()); + // RETURN TRUE; + //} + //else + //{ + // if (!entry->IsError()) + // { + // if (entry->GetAssembly() != NULL) + // { + // // OK if this is a duplicate + // if (entry->GetAssembly() == pAssembly) + // RETURN TRUE; + // } + // else + // { + // // OK if we have a matching PEAssembly + // if (entry->GetFile() != NULL + // && pAssembly->GetPEAssembly()->Equals(entry->GetFile())) + // { + // entry->SetAssembly(pAssembly); + // RETURN TRUE; + // } + // } + // } + + // // Invalid cache transition (see above note about state transitions) + // RETURN FALSE; + //} + RETURN TRUE; } // Note that this routine may be called outside a lock, so may be racing with another thread. @@ -994,67 +997,68 @@ BOOL AssemblySpecBindingCache::StorePEAssembly(AssemblySpec *pSpec, PEAssembly * } CONTRACT_END; - UPTR key = (UPTR)pSpec->Hash(); - - AssemblyBinder* pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); - key = key ^ (UPTR)pBinderContextForLookup; - - if (!pSpec->GetBinder()) - { - pSpec->SetBinder(pBinderContextForLookup); - } - - AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); - - if (entry == (AssemblyBinding *) INVALIDENTRY) - { - AssemblyBindingHolder abHolder; - - LoaderHeap* pHeap = m_pHeap; - - if (pBinderContextForLookup != NULL) - { - LoaderAllocator* pLoaderAllocator = pBinderContextForLookup->GetLoaderAllocator(); - - // Assemblies loaded with AssemblyLoadContext need to use a different heap if - // marked as collectible - if (pLoaderAllocator) - { - pHeap = pLoaderAllocator->GetHighFrequencyHeap(); - } - } - - entry = abHolder.CreateAssemblyBinding(pHeap); - - entry->Init(pSpec, pPEAssembly,NULL,NULL,pHeap, abHolder.GetPamTracker()); - - m_map.InsertValue(key, entry); - abHolder.SuppressRelease(); - - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly: Add cached entry (%p) with PEAssembly %p\n", entry, pPEAssembly); - - RETURN TRUE; - } - else - { - if (!entry->IsError()) - { - // OK if this is a duplicate - if (entry->GetFile() != NULL - && pPEAssembly->Equals(entry->GetFile())) - RETURN TRUE; - } - else - if (entry->IsPostBindError()) - { - // Another thread has reported what's going to happen later. - entry->ThrowIfError(); - - } - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"Incompatible cached entry found (%p) when adding PEAssembly %p\n", entry, pPEAssembly); - // Invalid cache transition (see above note about state transitions) - RETURN FALSE; - } + //UPTR key = (UPTR)pSpec->Hash(); + + //AssemblyBinder* pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); + //key = key ^ (UPTR)pBinderContextForLookup; + + //if (!pSpec->GetBinder()) + //{ + // pSpec->SetBinder(pBinderContextForLookup); + //} + + //AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); + + //if (entry == (AssemblyBinding *) INVALIDENTRY) + //{ + // AssemblyBindingHolder abHolder; + + // LoaderHeap* pHeap = m_pHeap; + + // if (pBinderContextForLookup != NULL) + // { + // LoaderAllocator* pLoaderAllocator = pBinderContextForLookup->GetLoaderAllocator(); + + // // Assemblies loaded with AssemblyLoadContext need to use a different heap if + // // marked as collectible + // if (pLoaderAllocator) + // { + // pHeap = pLoaderAllocator->GetHighFrequencyHeap(); + // } + // } + + // entry = abHolder.CreateAssemblyBinding(pHeap); + + // entry->Init(pSpec, pPEAssembly,NULL,NULL,pHeap, abHolder.GetPamTracker()); + + // m_map.InsertValue(key, entry); + // abHolder.SuppressRelease(); + + // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly: Add cached entry (%p) with PEAssembly %p\n", entry, pPEAssembly); + + // RETURN TRUE; + //} + //else + //{ + // if (!entry->IsError()) + // { + // // OK if this is a duplicate + // if (entry->GetFile() != NULL + // && pPEAssembly->Equals(entry->GetFile())) + // RETURN TRUE; + // } + // else + // if (entry->IsPostBindError()) + // { + // // Another thread has reported what's going to happen later. + // entry->ThrowIfError(); + + // } + // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"Incompatible cached entry found (%p) when adding PEAssembly %p\n", entry, pPEAssembly); + // // Invalid cache transition (see above note about state transitions) + // RETURN FALSE; + //} + RETURN TRUE; } BOOL AssemblySpecBindingCache::StoreException(AssemblySpec *pSpec, Exception* pEx) @@ -1070,57 +1074,58 @@ BOOL AssemblySpecBindingCache::StoreException(AssemblySpec *pSpec, Exception* pE } CONTRACT_END; - UPTR key = (UPTR)pSpec->Hash(); - - AssemblyBinding *entry = LookupInternal(pSpec, TRUE); - if (entry == (AssemblyBinding *) INVALIDENTRY) - { - // TODO: Merge this with the failure lookup in the binder - // - // Since no entry was found for this assembly in any binding context, save the failure - // in the DefaultBinder context - AssemblyBinder* pBinderToSaveException = NULL; - pBinderToSaveException = pSpec->GetBinder(); - if (pBinderToSaveException == NULL) - { - pBinderToSaveException = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); - key = key ^ (UPTR)pBinderToSaveException; - } - } - - if (entry == (AssemblyBinding *) INVALIDENTRY) { - AssemblyBindingHolder abHolder; - entry = abHolder.CreateAssemblyBinding(m_pHeap); - - entry->Init(pSpec,NULL,NULL,pEx,m_pHeap, abHolder.GetPamTracker()); - - m_map.InsertValue(key, entry); - abHolder.SuppressRelease(); - - STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreException): Add cached entry (%p) with exception %p",entry,pEx); - RETURN TRUE; - } - else - { - // OK if this is a duplicate - if (entry->IsError()) - { - if (entry->GetHR() == pEx->GetHR()) - RETURN TRUE; - } - else - { - // OK to transition to error if we don't have an Assembly yet - if (entry->GetAssembly() == NULL) - { - entry->InitException(pEx); - RETURN TRUE; - } - } - - // Invalid cache transition (see above note about state transitions) - RETURN FALSE; - } + //UPTR key = (UPTR)pSpec->Hash(); + + //AssemblyBinding *entry = LookupInternal(pSpec, TRUE); + //if (entry == (AssemblyBinding *) INVALIDENTRY) + //{ + // // TODO: Merge this with the failure lookup in the binder + // // + // // Since no entry was found for this assembly in any binding context, save the failure + // // in the DefaultBinder context + // AssemblyBinder* pBinderToSaveException = NULL; + // pBinderToSaveException = pSpec->GetBinder(); + // if (pBinderToSaveException == NULL) + // { + // pBinderToSaveException = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); + // key = key ^ (UPTR)pBinderToSaveException; + // } + //} + + //if (entry == (AssemblyBinding *) INVALIDENTRY) { + // AssemblyBindingHolder abHolder; + // entry = abHolder.CreateAssemblyBinding(m_pHeap); + + // entry->Init(pSpec,NULL,NULL,pEx,m_pHeap, abHolder.GetPamTracker()); + + // m_map.InsertValue(key, entry); + // abHolder.SuppressRelease(); + + // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreException): Add cached entry (%p) with exception %p",entry,pEx); + // RETURN TRUE; + //} + //else + //{ + // // OK if this is a duplicate + // if (entry->IsError()) + // { + // if (entry->GetHR() == pEx->GetHR()) + // RETURN TRUE; + // } + // else + // { + // // OK to transition to error if we don't have an Assembly yet + // if (entry->GetAssembly() == NULL) + // { + // entry->InitException(pEx); + // RETURN TRUE; + // } + // } + + // // Invalid cache transition (see above note about state transitions) + // RETURN FALSE; + //} + RETURN TRUE; } BOOL AssemblySpecBindingCache::RemoveAssembly(DomainAssembly* pAssembly) diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index 4028eebca4cb11..6079b403eee080 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -171,7 +171,7 @@ class AssemblySpec : public BaseAssemblySpec HRESULT Bind( AppDomain* pAppDomain, - BINDER_SPACE::Assembly** ppAssembly); + BINDERASSEMBLYREF* ppAssembly); Assembly *LoadAssembly(FileLoadLevel targetLevel, BOOL fThrowOnFileNotFound = TRUE); diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 2fc79fab37ab98..13b2f6fa40c362 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -28,7 +28,7 @@ #include "../binder/inc/assemblybindercommon.hpp" #include "../binder/inc/applicationcontext.hpp" -HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDER_SPACE::Assembly** ppAssembly) +HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly) { CONTRACTL { @@ -43,9 +43,9 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDER_SPACE::Assembly** ppAs HRESULT hr=S_OK; // Have a default binding context setup - AssemblyBinder *pBinder = GetBinderFromParentAssembly(pAppDomain); + ASSEMBLYBINDERREF pBinder = GetBinderFromParentAssembly(pAppDomain); - ReleaseHolder pPrivAsm; + BINDERASSEMBLYREF pPrivAsm; _ASSERTE(pBinder != NULL); if (IsCoreLibSatellite()) @@ -64,13 +64,22 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDER_SPACE::Assembly** ppAs { AssemblyNameData assemblyNameData = { 0 }; PopulateAssemblyNameData(assemblyNameData); - hr = pBinder->BindAssemblyByName(&assemblyNameData, &pPrivAsm); + + MethodDescCallSite methBindAssemblyByName(METHOD__BINDER_ASSEMBLYBINDER__BINDASSEMBLYBYNAME); + ARG_SLOT args[3] = + { + ObjToArgSlot(pBinder), + PtrToArgSlot(&assemblyNameData), + PtrToArgSlot(&pPrivAsm) + }; + + hr = methBindAssemblyByName.Call_RetHR(args); } if (SUCCEEDED(hr)) { - _ASSERTE(pPrivAsm != nullptr); - *ppAssembly = pPrivAsm.Extract(); + _ASSERTE(pPrivAsm != NULL); + *ppAssembly = pPrivAsm; } return hr; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index ed5e8002d1aabd..f59812d9e62342 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1199,11 +1199,15 @@ DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetObj) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_VoidPtr_RetVoid) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefObj_RetInt) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefObj_RetInt) DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) +DEFINE_CLASS(BINDER_ASSEMBLY, InternalLoader, Assembly) +DEFINE_METHOD(BINDER_ASSEMBLY, ISCORELIB, get_IsCoreLib, IM_RetBool) + DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes) DEFINE_FIELD_U(_totalAvailableMemoryBytes, GCMemoryInfoData, totalAvailableMemoryBytes) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index a4b2547e1e50b5..a26ac7014d1a2a 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -618,6 +618,7 @@ DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) DEFINE_METASIG(IM(IntPtr_Bool_RefObj_RetInt, I F r(j), i)) +DEFINE_METASIG(IM(PtrVoid_RefObj_RetInt, P(v) r(j), i)) // Undefine macros in case we include the file again in the compilation unit diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index f78a97d75c0cdb..f6bc217a6e2328 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1461,6 +1461,7 @@ class BinderAssemblyObject : public Object PEImage* m_PEImage; DomainAssembly* m_pDomainAssembly; OBJECTREF m_binder; + CLR_BOOL m_isCoreLib; }; // AssemblyLoadContextBaseObject From fc916618f5e2ef34f161e2112d8eb046ebe5c409 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Sep 2023 01:51:38 +0800 Subject: [PATCH 052/136] BindToSystemSatellite --- .../Runtime/Binder/AssemblyBinderCommon.cs | 33 ++++++++++++++++++- src/coreclr/vm/coreassemblyspec.cpp | 11 ++++++- src/coreclr/vm/corelib.h | 3 ++ src/coreclr/vm/metasig.h | 1 + 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index a708e9ad2c8b41..d325d17ae3bde0 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -8,6 +8,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using System.Runtime.Loader; using Internal.Runtime.Binder.Tracing; @@ -247,7 +248,37 @@ public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, // Skipped - the managed binder can't bootstrap CoreLib // static Assembly? BindToSystem(string systemDirectory); - // static Assembly? BindToSystemSatellite(string systemDirectory, string simpleName, string cultureName); + + private static unsafe int BindToSystemSatellite(char* systemDirectory, char* simpleName, char* cultureName, out Assembly? assembly) + { + // Satellite assembly's relative path + + // append culture name + + // append satellite assembly's simple name + + // append extension + string relativePath = (string.IsNullOrEmpty(new string(cultureName)) ? new string(simpleName) : new string(cultureName)) + ".dll"; + + // Satellite assembly's path: + // * Absolute path when looking for a file on disk + // * Bundle-relative path when looking within the single-file bundle. + + // PathSource pathSource = PathSource.Bundle; + // BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /*pathIsBundleRelative */ true); + PathSource pathSource = PathSource.ApplicationAssemblies; + string sCoreLibSatellite = new string(systemDirectory) + relativePath; + + int hr = GetAssembly(sCoreLibSatellite, isInTPA: true, out assembly, default); + if (hr < 0) + { + assembly = null; + } + + NativeRuntimeEventSource.Log.KnownPathProbed(sCoreLibSatellite, (ushort)pathSource, hr); + + return hr; + } private static int BindByName( ApplicationContext applicationContext, diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 13b2f6fa40c362..c14b5769ebf775 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -58,7 +58,16 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly if (m_context.szLocale != NULL) SString(SString::Utf8Literal, m_context.szLocale).ConvertToUnicode(sCultureName); - hr = BINDER_SPACE::AssemblyBinderCommon::BindToSystemSatellite(sSystemDirectory, sSimpleName, sCultureName, &pPrivAsm); + MethodDescCallSite methSatellite(METHOD__BINDER_ASSEMBLYBINDERCOMMON__BINDTOSYSTEMSATELLITE); + ARG_SLOT args[4] = + { + PtrToArgSlot(sSystemDirectory.GetUnicode()), + PtrToArgSlot(sSimpleName.GetUnicode()), + PtrToArgSlot(sCultureName.GetUnicode()), + PtrToArgSlot(&pPrivAsm) + }; + + hr = methSatellite.Call_RetHR(args); } else { diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index f59812d9e62342..6796760b5630d1 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1208,6 +1208,9 @@ DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPat DEFINE_CLASS(BINDER_ASSEMBLY, InternalLoader, Assembly) DEFINE_METHOD(BINDER_ASSEMBLY, ISCORELIB, get_IsCoreLib, IM_RetBool) +DEFINE_CLASS(BINDER_ASSEMBLYBINDERCOMMON, InternalLoader, AssemblyBinderCommon) +DEFINE_METHOD(BINDER_ASSEMBLYBINDERCOMMON, BINDTOSYSTEMSATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefObj_RetInt) + DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes) DEFINE_FIELD_U(_totalAvailableMemoryBytes, GCMemoryInfoData, totalAvailableMemoryBytes) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index a26ac7014d1a2a..b4ab711c3a1d50 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -619,6 +619,7 @@ DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) DEFINE_METASIG(IM(IntPtr_Bool_RefObj_RetInt, I F r(j), i)) DEFINE_METASIG(IM(PtrVoid_RefObj_RetInt, P(v) r(j), i)) +DEFINE_METASIG(SM(PtrChar_PtrChar_PtrChar_RefObj_RetInt, P(u) P(u) P(u) r(j), i)) // Undefine macros in case we include the file again in the compilation unit From f3795d0025302ae3a60e5243a2ef8e997f4924dc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Sep 2023 02:16:02 +0800 Subject: [PATCH 053/136] Compilation of casting --- src/coreclr/vm/peassembly.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 03341fd19a46fc..5fb401ad01d4d6 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -127,10 +127,10 @@ BOOL PEAssembly::Equals(PEAssembly *pPEAssembly) { GCX_COOP(); - ASSEMBLYBINDERREF otherBinder = ((BINDERASSEMBLYREF)ObjectFromHandle(pPEAssembly->GetHostAssembly()))->m_binder; - ASSEMBLYBINDERREF thisBinder = ((BINDERASSEMBLYREF)ObjectFromHandle(this->GetHostAssembly()))->m_binder; + BINDERASSEMBLYREF otherAssembly = (BINDERASSEMBLYREF)ObjectFromHandle(pPEAssembly->GetHostAssembly()); + BINDERASSEMBLYREF thisAssembly = (BINDERASSEMBLYREF)ObjectFromHandle(this->GetHostAssembly()); - if (otherBinder != thisBinder || otherBinder == NULL) + if (otherAssembly->m_binder != thisAssembly->m_binder || otherAssembly->m_binder == NULL) return FALSE; } From 8ea0e39060d0a910d2833a72e58cc773521d924b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 17 Sep 2023 02:28:36 +0800 Subject: [PATCH 054/136] Remaining in appdomainnative and assemblynative --- .../src/Internal/Runtime/Binder/AssemblyBinder.cs | 11 ++++++++++- src/coreclr/vm/appdomainnative.cpp | 5 ++--- src/coreclr/vm/assemblynative.cpp | 10 ++++++---- src/coreclr/vm/object.h | 4 +++- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 6f58fda257428d..b7d657bddf7d64 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -31,6 +31,15 @@ internal readonly unsafe struct AssemblyNameData internal abstract class AssemblyBinder { + // fields used by VM + private GCHandle m_managedALC; + private bool m_isDefault; + + protected AssemblyBinder() + { + m_isDefault = IsDefault; + } + public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) { return BindUsingAssemblyName(new AssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); @@ -51,7 +60,7 @@ public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? asse // A GC handle to the managed AssemblyLoadContext. // It is a long weak handle for collectible AssemblyLoadContexts and strong handle for non-collectible ones. - public GCHandle ManagedAssemblyLoadContext { get; set; } + public GCHandle ManagedAssemblyLoadContext { get => m_managedALC; set => m_managedALC = value; } // NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); diff --git a/src/coreclr/vm/appdomainnative.cpp b/src/coreclr/vm/appdomainnative.cpp index 79012785e8ecbc..88f9ae04d4d55d 100644 --- a/src/coreclr/vm/appdomainnative.cpp +++ b/src/coreclr/vm/appdomainnative.cpp @@ -26,10 +26,9 @@ extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnS _ASSERTE(assemblyLoadContext.Get() != NULL); - INT_PTR nativeAssemblyBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); - AssemblyBinder* pBinder = reinterpret_cast(nativeAssemblyBinder); + OBJECTREF pBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); - Assembly* pAssembly = Assembly::CreateDynamic(pBinder, pAssemblyNameParts, hashAlgorithm, access, &keepAlive); + Assembly* pAssembly = Assembly::CreateDynamic(GetAppDomain()->CreateHandle(pBinder), pAssemblyNameParts, hashAlgorithm, access, &keepAlive); retAssembly.Set(pAssembly->GetExposedObject()); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index c1ce0cacb891c3..8ec068f7a7283d 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -99,7 +99,7 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p // If so, then use it to set the fallback load context binder. if (pBinder != NULL) { - spec.SetFallbackBinderForRequestingAssembly(pBinder); + spec.SetFallbackBinderForRequestingAssembly(GetAppDomain()->CreateHandle(pBinder)); spec.SetPreferFallbackBinder(); } else if (pRefAssembly != NULL) @@ -1307,12 +1307,14 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::Ass _ASSERTE(pAssembly != NULL); - AssemblyBinder* pAssemblyBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + GCX_COOP(); + + ASSEMBLYBINDERREF pAssemblyBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); - if (!pAssemblyBinder->IsDefault()) + if (!pAssemblyBinder->m_isDefault) { // Fetch the managed binder reference from the native binder instance - ptrManagedAssemblyLoadContext = pAssemblyBinder->GetManagedAssemblyLoadContext(); + ptrManagedAssemblyLoadContext = pAssemblyBinder->m_managedALC; _ASSERTE(ptrManagedAssemblyLoadContext != NULL); } diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index f6bc217a6e2328..2a48ec91425550 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1443,7 +1443,9 @@ NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembl // managed Internal.Runtime.Binder.AssemblyBinder class AssemblyBinderObject : public Object { - +public: + INT_PTR m_managedALC; + CLR_BOOL m_isDefault; }; #ifdef USE_CHECKED_OBJECTREFS From c0b851e668e75e051ed116eeaf284b058fdeef03 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 18 Sep 2023 02:13:41 +0800 Subject: [PATCH 055/136] NativeImage and DeclareDependencyOnMvid --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 4 ++++ src/coreclr/vm/assemblybinder.cpp | 4 ++-- src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/metasig.h | 1 + src/coreclr/vm/nativeimage.cpp | 8 ++++--- src/coreclr/vm/nativeimage.h | 8 +++---- src/coreclr/vm/readytoruninfo.cpp | 24 +++++++++++++++---- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index b7d657bddf7d64..ae4b5c6c36038a 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -112,6 +112,10 @@ private static void MvidMismatchFatalError(Guid mvidActual, Guid mvidExpected, s Environment.FailFast(message); } + // used by vm + internal unsafe void DeclareDependencyOnMvid(byte* simpleName, in Guid mvid, bool compositeComponent, byte* imageName) + => DeclareDependencyOnMvid(new MdUtf8String(simpleName).ToString(), mvid, compositeComponent, new MdUtf8String(imageName).ToString()); + // Must be called under the LoadLock public void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool compositeComponent, string imageName) { diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index 6e1f96eb5bb08a..3fa911bdec8fe3 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -35,8 +35,8 @@ NativeImage* AssemblyBinder::LoadNativeImage(Module* componentModule, LPCUTF8 na AssemblyBinder* binder = /* componentModule->GetPEAssembly()->GetAssemblyBinder() */ NULL; PTR_LoaderAllocator moduleLoaderAllocator = componentModule->GetLoaderAllocator(); - bool isNewNativeImage; - NativeImage* nativeImage = NativeImage::Open(componentModule, nativeImageName, binder, moduleLoaderAllocator, &isNewNativeImage); + // bool isNewNativeImage; + NativeImage* nativeImage = /*NativeImage::Open(componentModule, nativeImageName, binder, moduleLoaderAllocator, &isNewNativeImage)*/ NULL; return nativeImage; } diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 6796760b5630d1..d6e6c31c475ff9 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1200,6 +1200,7 @@ DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_ DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_VoidPtr_RetVoid) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefObj_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefObj_RetInt) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index b4ab711c3a1d50..61aaa16edf3108 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -620,6 +620,7 @@ DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) DEFINE_METASIG(IM(IntPtr_Bool_RefObj_RetInt, I F r(j), i)) DEFINE_METASIG(IM(PtrVoid_RefObj_RetInt, P(v) r(j), i)) DEFINE_METASIG(SM(PtrChar_PtrChar_PtrChar_RefObj_RetInt, P(u) P(u) P(u) r(j), i)) +DEFINE_METASIG_T(IM(PtrByte_RefGuid_Bool_PtrByte_RetVoid, P(b) r(g(GUID)) F P(b), v)) // Undefine macros in case we include the file again in the compilation unit diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp index 9eb02777e5d262..d6abd745d246e7 100644 --- a/src/coreclr/vm/nativeimage.cpp +++ b/src/coreclr/vm/nativeimage.cpp @@ -41,7 +41,7 @@ NativeImageIndexTraits::count_t NativeImageIndexTraits::Hash(LPCUTF8 a) return SString(SString::Utf8Literal, a).HashCaseInsensitive(); } -NativeImage::NativeImage(AssemblyBinder *pAssemblyBinder, PEImageLayout *pImageLayout, LPCUTF8 imageFileName) +NativeImage::NativeImage(OBJECTHANDLE pAssemblyBinder, PEImageLayout *pImageLayout, LPCUTF8 imageFileName) : m_eagerFixupsLock(CrstNativeImageEagerFixups) { CONTRACTL @@ -111,7 +111,7 @@ NativeImage::~NativeImage() NativeImage *NativeImage::Open( Module *componentModule, LPCUTF8 nativeImageFileName, - AssemblyBinder *pAssemblyBinder, + OBJECTHANDLE pAssemblyBinder, LoaderAllocator *pLoaderAllocator, /* out */ bool *isNewNativeImage) { @@ -120,8 +120,10 @@ NativeImage *NativeImage::Open( NativeImage *pExistingImage = AppDomain::GetCurrentDomain()->GetNativeImage(nativeImageFileName); if (pExistingImage != nullptr) { + GCX_COOP(); + *isNewNativeImage = false; - if (pExistingImage->GetAssemblyBinder() == pAssemblyBinder) + if (ObjectFromHandle(pExistingImage->GetAssemblyBinder()) == ObjectFromHandle(pAssemblyBinder)) { return pExistingImage; } diff --git a/src/coreclr/vm/nativeimage.h b/src/coreclr/vm/nativeimage.h index afbc1e32cd0acb..dd4411c6d59c08 100644 --- a/src/coreclr/vm/nativeimage.h +++ b/src/coreclr/vm/nativeimage.h @@ -80,7 +80,7 @@ class NativeImage // Points to the OwnerCompositeExecutable section content within the component MSIL module LPCUTF8 m_fileName; - AssemblyBinder *m_pAssemblyBinder; + OBJECTHANDLE m_pAssemblyBinder; ReadyToRunInfo *m_pReadyToRunInfo; IMDInternalImport *m_pManifestMetadata; PEImageLayout *m_pImageLayout; @@ -97,7 +97,7 @@ class NativeImage bool m_readyToRunCodeDisabled; private: - NativeImage(AssemblyBinder *pAssemblyBinder, PEImageLayout *peImageLayout, LPCUTF8 imageFileName); + NativeImage(OBJECTHANDLE pAssemblyBinder, PEImageLayout *peImageLayout, LPCUTF8 imageFileName); protected: void Initialize(READYTORUN_HEADER *header, LoaderAllocator *loaderAllocator, AllocMemTracker *pamTracker); @@ -108,7 +108,7 @@ class NativeImage static NativeImage *Open( Module *componentModule, LPCUTF8 nativeImageFileName, - AssemblyBinder *pAssemblyBinder, + OBJECTHANDLE pAssemblyBinder, LoaderAllocator *pLoaderAllocator, /* out */ bool *isNewNativeImage); @@ -122,7 +122,7 @@ class NativeImage IMDInternalImport *GetManifestMetadata() const { return m_pManifestMetadata; } uint32_t GetManifestAssemblyCount() const { return m_manifestAssemblyCount; } PTR_Assembly *GetManifestMetadataAssemblyRefMap() { return m_pNativeMetadataAssemblyRefMap; } - AssemblyBinder *GetAssemblyBinder() const { return m_pAssemblyBinder; } + OBJECTHANDLE GetAssemblyBinder() const { return m_pAssemblyBinder; } Assembly *LoadManifestAssembly(uint32_t rowid, DomainAssembly *pParentAssembly); diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index e75373db8855aa..24459fb7adf1ff 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -503,8 +503,10 @@ static NativeImage *AcquireCompositeImage(Module * pModule, PEImageLayout * pLay if (ownerCompositeExecutableName != NULL) { - AssemblyBinder *binder = pModule->GetPEAssembly()->GetAssemblyBinder(); - return binder->LoadNativeImage(pModule, ownerCompositeExecutableName); + //AssemblyBinder *binder = pModule->GetPEAssembly()->GetAssemblyBinder(); + //return binder->LoadNativeImage(pModule, ownerCompositeExecutableName); + + // TODO: implement } return NULL; @@ -756,7 +758,7 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat int32_t manifestAssemblyCount = 0; GUID emptyGuid = {0}; - AssemblyBinder* binder = pModule != NULL ? pModule->GetPEAssembly()->GetAssemblyBinder() : pNativeImage->GetAssemblyBinder(); + ASSEMBLYBINDERREF binder = pModule != NULL ? pModule->GetPEAssembly()->GetAssemblyBinder() : (ASSEMBLYBINDERREF)ObjectFromHandle(pNativeImage->GetAssemblyBinder()); auto pComponentAssemblyMvids = FindSection(ReadyToRunSectionType::ManifestAssemblyMvids); if (pComponentAssemblyMvids != NULL) { @@ -779,7 +781,21 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat LPCSTR assemblyName; IfFailThrow(pNativeMDImport->GetAssemblyRefProps(assemblyRef, NULL, NULL, &assemblyName, NULL, NULL, NULL, NULL)); - binder->DeclareDependencyOnMvid(assemblyName, *componentMvid, pNativeImage != NULL, pModule != NULL ? pModule->GetSimpleName() : pNativeImage->GetFileName()); + { + // TODO: GC mode + MethodDescCallSite methDeclareDependencyOnMvid(METHOD__BINDER_ASSEMBLYBINDER__DECLAREDEPENDENCYONMVID); + ARG_SLOT args[5] = + { + ObjToArgSlot(binder), + PtrToArgSlot(componentMvid), + PtrToArgSlot(assemblyName), + BoolToArgSlot(pNativeImage != NULL), + PtrToArgSlot(pModule != NULL ? pModule->GetSimpleName() : pNativeImage->GetFileName()) + }; + + methDeclareDependencyOnMvid.Call(args); + } + manifestAssemblyCount++; } } From 25b618737bbcb88c28af7cba682cc4da9e61f26a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Sep 2023 16:50:25 +0800 Subject: [PATCH 056/136] Make native part compiling --- src/coreclr/debug/daccess/request.cpp | 4 ++-- src/coreclr/vm/multicorejitplayer.cpp | 3 ++- src/coreclr/vm/nativelibrary.cpp | 14 ++++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index e5cc22d8c708a5..e330218694602d 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -4926,9 +4926,9 @@ HRESULT ClrDataAccess::GetAssemblyLoadContext(CLRDATA_ADDRESS methodTable, CLRDA PTR_Module pModule = pMT->GetModule(); PTR_PEAssembly pPEAssembly = pModule->GetPEAssembly(); - PTR_AssemblyBinder pBinder = pPEAssembly->GetAssemblyBinder(); + ASSEMBLYBINDERREF pBinder = pPEAssembly->GetAssemblyBinder(); - INT_PTR managedAssemblyLoadContextHandle = pBinder->GetManagedAssemblyLoadContext(); + INT_PTR managedAssemblyLoadContextHandle = pBinder->m_managedALC; TADDR managedAssemblyLoadContextAddr = 0; if (managedAssemblyLoadContextHandle != 0) diff --git a/src/coreclr/vm/multicorejitplayer.cpp b/src/coreclr/vm/multicorejitplayer.cpp index 2b8a0a1ba80992..17552197a9b990 100644 --- a/src/coreclr/vm/multicorejitplayer.cpp +++ b/src/coreclr/vm/multicorejitplayer.cpp @@ -835,7 +835,8 @@ DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName) // Set the binding context to the assembly load context. if (m_pBinder != NULL) { - spec.SetBinder(m_pBinder); + // TODO: support + // spec.SetBinder(m_pBinder); } // Bind and load the assembly. diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index 6fcfc0f9488c93..8ed9f2d5cdeb4c 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -333,13 +333,13 @@ namespace NATIVE_LIBRARY_HANDLE hmod = NULL; PEAssembly *pManifestFile = pAssembly->GetPEAssembly(); - PTR_AssemblyBinder pBinder = pManifestFile->GetAssemblyBinder(); + ASSEMBLYBINDERREF pBinder = pManifestFile->GetAssemblyBinder(); //Step 0: Check if the assembly was bound using TPA. - AssemblyBinder *pCurrentBinder = pBinder; + ASSEMBLYBINDERREF pCurrentBinder = pBinder; // For assemblies bound via default binder, we should use the standard mechanism to make the pinvoke call. - if (pCurrentBinder->IsDefault()) + if (pCurrentBinder->m_isDefault) { return NULL; } @@ -356,7 +356,7 @@ namespace GCPROTECT_BEGIN(pUnmanagedDllName); // Get the pointer to the managed assembly load context - INT_PTR ptrManagedAssemblyLoadContext = pCurrentBinder->GetManagedAssemblyLoadContext(); + INT_PTR ptrManagedAssemblyLoadContext = pCurrentBinder->m_managedALC; // Prepare to invoke System.Runtime.Loader.AssemblyLoadContext.ResolveUnmanagedDll method. PREPARE_NONVIRTUAL_CALLSITE(METHOD__ASSEMBLYLOADCONTEXT__RESOLVEUNMANAGEDDLL); @@ -377,8 +377,10 @@ namespace { STANDARD_VM_CONTRACT; - PTR_AssemblyBinder pBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); - return pBinder->GetManagedAssemblyLoadContext(); + GCX_COOP(); + + ASSEMBLYBINDERREF pBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + return pBinder->m_managedALC; } NATIVE_LIBRARY_HANDLE LoadNativeLibraryViaAssemblyLoadContextEvent(Assembly * pAssembly, PCWSTR wszLibName) From 85acdca5e56f08d8d66787b982f6aa7d54d51276 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Sep 2023 17:56:00 +0800 Subject: [PATCH 057/136] Fullfill PEAssembly QCalls --- .../Runtime/Binder/AssemblyBinderCommon.cs | 26 +++++------ .../src/System/Reflection/LoaderAllocator.cs | 11 ++--- src/coreclr/vm/assemblynative.cpp | 45 +++++++++++++++++++ src/coreclr/vm/assemblynative.hpp | 5 +++ src/coreclr/vm/loaderallocator.cpp | 15 +++++++ src/coreclr/vm/loaderallocator.hpp | 1 + src/coreclr/vm/qcallentrypoints.cpp | 4 ++ 7 files changed, 86 insertions(+), 21 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index d325d17ae3bde0..53e347bc76d44a 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -8,7 +8,6 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; using System.Runtime.Loader; using Internal.Runtime.Binder.Tracing; @@ -39,19 +38,14 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf8)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); - // Foo + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetPEAssembly")] + private static partial IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEAssembly_GetHostAssembly")] + private static partial IntPtr PEAssembly_GetHostAssembly(IntPtr pPEAssembly); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool PEAssembly_HasHostAssembly(IntPtr pPEAssembly); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern Assembly PEAssembly_GetHostAssembly(IntPtr pPEAssembly); - - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern System.Reflection.LoaderAllocator DomainAssembly_GetLoaderAllocator(IntPtr pDomainAssembly); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetLoaderAllocator")] + private static partial IntPtr DomainAssembly_GetLoaderAllocator(IntPtr pDomainAssembly); public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { @@ -936,7 +930,7 @@ public static int BindUsingHostAssemblyResolver( else { pLoadedPEAssembly = DomainAssembly_GetPEAssembly(pDomainAssembly); - if (!PEAssembly_HasHostAssembly(pLoadedPEAssembly)) + if (PEAssembly_GetHostAssembly(pLoadedPEAssembly) == IntPtr.Zero) { // Reflection emitted assemblies will not have a domain assembly. fFailLoad = true; @@ -954,7 +948,7 @@ public static int BindUsingHostAssemblyResolver( // alive for all its lifetime. if (rtAssembly.IsCollectible) { - System.Reflection.LoaderAllocator resultAssemblyLoaderAllocator = DomainAssembly_GetLoaderAllocator(pDomainAssembly); + IntPtr resultAssemblyLoaderAllocator = DomainAssembly_GetLoaderAllocator(pDomainAssembly); System.Reflection.LoaderAllocator? parentLoaderAllocator = binder.GetLoaderAllocator(); if (parentLoaderAllocator == null) { @@ -962,11 +956,11 @@ public static int BindUsingHostAssemblyResolver( throw new NotSupportedException(SR.NotSupported_CollectibleBoundNonCollectible); } - Debug.Assert(resultAssemblyLoaderAllocator != null); + Debug.Assert(resultAssemblyLoaderAllocator != IntPtr.Zero); parentLoaderAllocator.EnsureReference(resultAssemblyLoaderAllocator); } - resolvedAssembly = PEAssembly_GetHostAssembly(pLoadedPEAssembly); + resolvedAssembly = GCHandle.FromIntPtr(PEAssembly_GetHostAssembly(pLoadedPEAssembly)).Target as Assembly; } if (fResolvedAssembly) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index 58ff51a39f6094..f08b54ffb36bad 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -64,13 +64,14 @@ private LoaderAllocator() internal Internal.Runtime.Binder.AssemblyBinder? m_binderToRelease; [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_EnsureReference")] - internal static partial void EnsureReference(IntPtr nativeLoaderAllocator, IntPtr otherNativeLoaderAllocator); - internal void EnsureReference(LoaderAllocator otherLA) => EnsureReference(m_scout.m_nativeLoaderAllocator, otherLA.m_scout.m_nativeLoaderAllocator); + internal void EnsureReference(IntPtr otherNativeLA) => EnsureReference(m_scout.m_nativeLoaderAllocator, otherNativeLA); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_IsCollectible")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool IsCollectible(IntPtr nativeLoaderAllocator); - // Foo - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern bool IsCollectible(); + internal bool IsCollectible() => IsCollectible(m_scout.m_nativeLoaderAllocator); } } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 8ec068f7a7283d..a7d2ea9b63e67b 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1643,3 +1643,48 @@ extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage) return result; } #endif // TARGET_WINDOWS + +extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly) +{ + QCALL_CONTRACT; + + PEAssembly* result = NULL; + + BEGIN_QCALL; + + result = pDomainAssembly->GetPEAssembly(); + + END_QCALL; + + return result; +} + +extern "C" LoaderAllocator * QCALLTYPE DomainAssembly_GetLoaderAllocator(DomainAssembly * pDomainAssembly) +{ + QCALL_CONTRACT; + + LoaderAllocator * result = NULL; + + BEGIN_QCALL; + + result = pDomainAssembly->GetLoaderAllocator(); + + END_QCALL; + + return result; +} + +extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly) +{ + QCALL_CONTRACT; + + INT_PTR result = NULL; + + BEGIN_QCALL; + + result = (INT_PTR)pPEAssembly->GetHostAssembly(); + + END_QCALL; + + return result; +} diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 3e2ea6fffe1375..03479d851d1cb8 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -171,4 +171,9 @@ extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod); extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage); #endif // TARGET_WINDOWS +extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly); + +extern "C" LoaderAllocator * QCALLTYPE DomainAssembly_GetLoaderAllocator(DomainAssembly * pDomainAssembly); + +extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly); #endif diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 29a343d0accc96..f1ff01b59652a7 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -264,6 +264,21 @@ extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocator END_QCALL; } +extern "C" BOOL QCALLTYPE LoaderAllocator_IsCollectible(QCall::LoaderAllocatorHandle pLA) +{ + QCALL_CONTRACT; + + BOOL result = FALSE; + + BEGIN_QCALL; + + result = pLA->IsCollectible(); + + END_QCALL; + + return result; +} + BOOL LoaderAllocator::EnsureInstantiation(Module *pDefiningModule, Instantiation inst) { CONTRACTL diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 3b6a4efcca01d0..5216e0bb433b19 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -838,6 +838,7 @@ typedef VPTR(LoaderAllocator) PTR_LoaderAllocator; extern "C" BOOL QCALLTYPE LoaderAllocator_Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator); extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocatorHandle pLA, QCall::LoaderAllocatorHandle pOtherLA); +extern "C" BOOL QCALLTYPE LoaderAllocator_IsCollectible(QCall::LoaderAllocatorHandle pLA); class GlobalLoaderAllocator : public LoaderAllocator { diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 6049ee12732019..c80f4a05630fa7 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -205,12 +205,16 @@ static const Entry s_QCall[] = DllImportEntry(PEImage_CreateFromHMODULE) DllImportEntry(PEImage_HasCorHeader) #endif + DllImportEntry(DomainAssembly_GetPEAssembly) + DllImportEntry(DomainAssembly_GetLoaderAllocator) + DllImportEntry(PEAssembly_GetHostAssembly) #if defined(FEATURE_MULTICOREJIT) DllImportEntry(MultiCoreJIT_InternalSetProfileRoot) DllImportEntry(MultiCoreJIT_InternalStartProfile) #endif DllImportEntry(LoaderAllocator_Destroy) DllImportEntry(LoaderAllocator_EnsureReference) + DllImportEntry(LoaderAllocator_IsCollectible) DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) DllImportEntry(ThreadNative_InformThreadNameChange) From b1573028cd99c95ade470e254dcb80ff7d7bb1b8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Sep 2023 19:46:53 +0800 Subject: [PATCH 058/136] QCall for VMAssembly --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 36 +++++----- .../Loader/AssemblyLoadContext.CoreCLR.cs | 10 +-- src/coreclr/vm/assemblynative.cpp | 68 +++++++++++++++++++ src/coreclr/vm/assemblynative.hpp | 10 +++ src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/qcallentrypoints.cpp | 5 ++ 6 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index ae4b5c6c36038a..82f1b7437e8cd7 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Loader; @@ -29,7 +30,7 @@ internal readonly unsafe struct AssemblyNameData public readonly AssemblyIdentityFlags IdentityFlags; } - internal abstract class AssemblyBinder + internal abstract partial class AssemblyBinder { // fields used by VM private GCHandle m_managedALC; @@ -64,7 +65,8 @@ public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? asse // NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); - public void AddLoadedAssembly(IVMAssembly loadedAssembly) + // called by vm + public void AddLoadedAssembly(IntPtr loadedAssembly) { // BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); // TODO: is the lock shared outside this type? @@ -157,7 +159,7 @@ public void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool composite if (addAllLoadedModules) { - foreach (IVMAssembly assembly in _loadedAssemblies) + foreach (IntPtr assembly in _loadedAssemblies) { DeclareLoadedAssembly(assembly); } @@ -165,7 +167,7 @@ public void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool composite } // Must be called under the LoadLock - private void DeclareLoadedAssembly(IVMAssembly loadedAssembly) + private unsafe void DeclareLoadedAssembly(IntPtr loadedAssembly) { // If table is empty, then no mvid dependencies have been declared, so we don't need to record this information if (_assemblySimpleNameMvidCheckHash.Count == 0) @@ -173,8 +175,9 @@ private void DeclareLoadedAssembly(IVMAssembly loadedAssembly) return; } - loadedAssembly.GetMDImport().GetScopeProps(out Guid mvid); - string simpleName = loadedAssembly.SimpleName; + var mdImport = new System.Reflection.MetadataImport(Assembly_GetMDImport(loadedAssembly), null); + mdImport.GetScopeProps(out Guid mvid); + string simpleName = new MdUtf8String(Assembly_GetSimpleName(loadedAssembly)).ToString(); ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); if (!found) @@ -227,22 +230,23 @@ private struct SimpleNameToExpectedMVIDAndRequiringAssembly // comparisons are slow and have throwing scenarios, and this hash table // provides a best-effort match to prevent problems, not perfection private readonly Dictionary _assemblySimpleNameMvidCheckHash = new Dictionary(); - private readonly List _loadedAssemblies = new List(); + private readonly List _loadedAssemblies = new List(); private static readonly object _loadLock = new object(); - } - // Foo - internal interface IVMAssembly // coreclr/vm/assembly - { - public System.Reflection.MetadataImport GetMDImport(); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetMDImport")] + private static partial IntPtr Assembly_GetMDImport(IntPtr pAssembly); - public string SimpleName { get; } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetSimpleNameNative")] + private static unsafe partial byte* Assembly_GetSimpleName(IntPtr pAssembly); - public System.Reflection.RuntimeAssembly GetExposedObject(); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetExposedObject")] + internal static unsafe partial void Assembly_GetExposedObject(IntPtr pAssembly, ObjectHandleOnStack rtAssembly); - public IntPtr GetPEAssembly_GetPEImage(); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetPEImage")] + internal static partial IntPtr Assembly_GetPEImage(IntPtr pAssembly); - public unsafe void GetModule_SetSymbolBytes(byte* ptrSymbolArray, int cbSymbolArrayLength); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_SetSymbolBytes")] + internal static unsafe partial void Assembly_SetSymbolBytes(IntPtr pAssembly, byte* ptrSymbolArray, int cbSymbolArrayLength); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 3353e4a205e096..377c4730e7e78f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -79,8 +79,10 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass } // Pass the stream based assembly as IL in an attempt to bind and load it - Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); - RuntimeAssembly retAssembly = loadedAssembly.GetExposedObject(); + IntPtr loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); + RuntimeAssembly? retAssembly = null; + Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); + Debug.Assert(retAssembly != null); // LOG((LF_CLASSLOADER, // LL_INFO100, @@ -91,7 +93,7 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass // we created above. We need pointer comparison instead of pe image equivalence // to avoid mixed binaries/PDB pairs of other images. // This applies to both Desktop CLR and CoreCLR, with or without fusion. - bool isSameAssembly = loadedAssembly.GetPEAssembly_GetPEImage() == pILImage; + bool isSameAssembly = Internal.Runtime.Binder.AssemblyBinder.Assembly_GetPEImage(loadedAssembly) == pILImage; // Setting the PDB info is only applicable for our original assembly. // This applies to both Desktop CLR and CoreCLR, with or without fusion. @@ -100,7 +102,7 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass // #ifdef DEBUGGING_SUPPORTED if (ptrSymbols != null) { - loadedAssembly.GetModule_SetSymbolBytes(ptrAssemblyArray, iSymbolArrayLen); + Internal.Runtime.Binder.AssemblyBinder.Assembly_SetSymbolBytes(loadedAssembly, ptrAssemblyArray, iSymbolArrayLen); } // #endif } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index a7d2ea9b63e67b..5701666ac0936d 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1470,6 +1470,74 @@ extern "C" BOOL QCALLTYPE AssemblyNative_IsApplyUpdateSupported() return result; } +extern "C" IMDInternalImport * QCALLTYPE AssemblyNative_GetMDImport(Assembly * pAssembly) +{ + QCALL_CONTRACT; + + IMDInternalImport* result = NULL; + + BEGIN_QCALL; + + result = pAssembly->GetMDImport(); + + END_QCALL; + + return result; +} + +extern "C" LPCUTF8 QCALLTYPE AssemblyNative_GetSimpleNameNative(Assembly * pAssembly) +{ + QCALL_CONTRACT; + + LPCUTF8 result = NULL; + + BEGIN_QCALL; + + result = pAssembly->GetSimpleName(); + + END_QCALL; + + return result; +} + +extern "C" void QCALLTYPE AssemblyNative_GetExposedObject(Assembly * pAssembly, QCall::ObjectHandleOnStack rtAssembly) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); + rtAssembly.Set(pAssembly->GetExposedObject()); + + END_QCALL; +} + +extern "C" PEImage * QCALLTYPE AssemblyNative_GetPEImage(Assembly * pAssembly) +{ + QCALL_CONTRACT; + + PEImage* result = NULL; + + BEGIN_QCALL; + + result = pAssembly->GetPEAssembly()->GetPEImage(); + + END_QCALL; + + return result; +} + +extern "C" void QCALLTYPE AssemblyNative_SetSymbolBytes(Assembly * pAssembly, BYTE* ptrSymbolArray, int32_t cbSymbolArrayLength) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pAssembly->GetModule()->SetSymbolBytes(ptrSymbolArray, (DWORD)cbSymbolArrayLength); + + END_QCALL; +} + extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 03479d851d1cb8..adb48ea9c7ea12 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -149,6 +149,16 @@ extern "C" BOOL QCALLTYPE AssemblyNative_IsApplyUpdateSupported(); extern "C" void QCALLTYPE AssemblyName_InitializeAssemblySpec(NativeAssemblyNameParts* pAssemblyNameParts, BaseAssemblySpec* pAssemblySpec); +extern "C" IMDInternalImport * QCALLTYPE AssemblyNative_GetMDImport(Assembly * pAssembly); + +extern "C" LPCUTF8 QCALLTYPE AssemblyNative_GetSimpleNameNative(Assembly * pAssembly); + +extern "C" void QCALLTYPE AssemblyNative_GetExposedObject(Assembly * pAssembly, QCall::ObjectHandleOnStack rtAssembly); + +extern "C" PEImage * QCALLTYPE AssemblyNative_GetPEImage(Assembly * pAssembly); + +extern "C" void QCALLTYPE AssemblyNative_SetSymbolBytes(Assembly * pAssembly, BYTE* ptrSymbolArray, int32_t cbSymbolArrayLength); + extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags); extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index d6e6c31c475ff9..808ac9c97d04c0 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1197,7 +1197,7 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) // Managed binder types DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetObj) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_VoidPtr_RetVoid) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_IntPtr_RetVoid) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefObj_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefObj_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index c80f4a05630fa7..b31900e37ccd00 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -177,6 +177,11 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_InternalTryGetRawMetadata) DllImportEntry(AssemblyNative_ApplyUpdate) DllImportEntry(AssemblyNative_IsApplyUpdateSupported) + DllImportEntry(AssemblyNative_GetMDImport) + DllImportEntry(AssemblyNative_GetSimpleNameNative) + DllImportEntry(AssemblyNative_GetExposedObject) + DllImportEntry(AssemblyNative_GetPEImage) + DllImportEntry(AssemblyNative_SetSymbolBytes) DllImportEntry(AssemblyNative_GetDefaultAssemblyBinder) DllImportEntry(AssemblyNative_InitializeAssemblyLoadContext) DllImportEntry(AssemblyNative_PrepareForAssemblyLoadContextRelease) From 9073bc308432a8ab8ff640034c4a567ff95fe466 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Sep 2023 19:57:59 +0800 Subject: [PATCH 059/136] AssemblyNative_LoadFromPEImage --- .../Loader/AssemblyLoadContext.CoreCLR.cs | 21 ++++++++++++------- src/coreclr/vm/assemblynative.cpp | 18 ++++++++++++++++ src/coreclr/vm/assemblynative.hpp | 2 ++ src/coreclr/vm/qcallentrypoints.cpp | 1 + 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 377c4730e7e78f..d5f99872ce32d7 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -15,9 +15,8 @@ public partial class AssemblyLoadContext [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] internal static partial IntPtr GetDefaultAssemblyBinder(); - // Foo - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern Internal.Runtime.Binder.IVMAssembly AssemblyNative_LoadFromPEImage(Internal.Runtime.Binder.AssemblyBinder pBinder, IntPtr pPEImage, bool excludeAppPaths = false); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromPEImage")] + private static partial IntPtr LoadFromPEImage(ObjectHandleOnStack pBinder, IntPtr pPEImage, [MarshalAs(UnmanagedType.Bool)] bool excludeAppPaths = false); private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadContext(GCHandle ptrAssemblyLoadContext, bool representsTPALoadContext, bool isCollectible) { @@ -79,7 +78,7 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass } // Pass the stream based assembly as IL in an attempt to bind and load it - IntPtr loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); + IntPtr loadedAssembly = LoadFromPEImage(ObjectHandleOnStack.Create(ref assemblyBinder), pILImage); RuntimeAssembly? retAssembly = null; Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); Debug.Assert(retAssembly != null); @@ -152,8 +151,11 @@ private static RuntimeAssembly LoadFromPath(Internal.Runtime.Binder.AssemblyBind throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{ilPath}' is invalid."); } - Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); - return loadedAssembly.GetExposedObject(); + IntPtr loadedAssembly = LoadFromPEImage(ObjectHandleOnStack.Create(ref assemblyBinder), pILImage); + RuntimeAssembly? retAssembly = null; + Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); + Debug.Assert(retAssembly != null); + return retAssembly; // LOG((LF_CLASSLOADER, // LL_INFO100, @@ -222,8 +224,11 @@ private static RuntimeAssembly LoadFromInMemoryModuleInternal(Internal.Runtime.B throw new BadImageFormatException(SR.BadImageFormat_BadILFormat); // Pass the in memory module as IL in an attempt to bind and load it - Internal.Runtime.Binder.IVMAssembly loadedAssembly = AssemblyNative_LoadFromPEImage(assemblyBinder, pILImage); - return loadedAssembly.GetExposedObject(); + IntPtr loadedAssembly = LoadFromPEImage(ObjectHandleOnStack.Create(ref assemblyBinder), pILImage); + RuntimeAssembly? retAssembly = null; + Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); + Debug.Assert(retAssembly != null); + return retAssembly; // LOG((LF_CLASSLOADER, // LL_INFO100, diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 5701666ac0936d..849bd7216a1f35 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1538,6 +1538,24 @@ extern "C" void QCALLTYPE AssemblyNative_SetSymbolBytes(Assembly * pAssembly, BY END_QCALL; } +extern "C" Assembly * QCALLTYPE AssemblyNative_LoadFromPEImage(QCall::ObjectHandleOnStack pBinder, PEImage * pPEImage, BOOL excludeAppPaths) +{ + QCALL_CONTRACT; + + Assembly* result = NULL; + + BEGIN_QCALL; + + GCX_COOP(); + + ASSEMBLYBINDERREF binder = (ASSEMBLYBINDERREF)pBinder.Get(); + result = AssemblyNative::LoadFromPEImage(binder, pPEImage, excludeAppPaths); + + END_QCALL; + + return result; +} + extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index adb48ea9c7ea12..b2607fe1794885 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -159,6 +159,8 @@ extern "C" PEImage * QCALLTYPE AssemblyNative_GetPEImage(Assembly * pAssembly); extern "C" void QCALLTYPE AssemblyNative_SetSymbolBytes(Assembly * pAssembly, BYTE* ptrSymbolArray, int32_t cbSymbolArrayLength); +extern "C" Assembly * QCALLTYPE AssemblyNative_LoadFromPEImage(QCall::ObjectHandleOnStack pBinder, PEImage * pPEImage, BOOL excludeAppPaths); + extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags); extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index b31900e37ccd00..52e99d488f2ab1 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -182,6 +182,7 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetExposedObject) DllImportEntry(AssemblyNative_GetPEImage) DllImportEntry(AssemblyNative_SetSymbolBytes) + DllImportEntry(AssemblyNative_LoadFromPEImage) DllImportEntry(AssemblyNative_GetDefaultAssemblyBinder) DllImportEntry(AssemblyNative_InitializeAssemblyLoadContext) DllImportEntry(AssemblyNative_PrepareForAssemblyLoadContextRelease) From 38aee24a87585706dae26c475ecd2f16b57dce5e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 19 Sep 2023 20:38:59 +0800 Subject: [PATCH 060/136] Refine corelib metasig --- .../src/Internal/Runtime/Binder/CustomAssemblyBinder.cs | 1 - src/coreclr/vm/corelib.h | 6 +++--- src/coreclr/vm/metasig.h | 5 +++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs index d8575f001353fd..06e9cb69b3a4a3 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using System.Reflection; using System.Runtime.InteropServices; namespace Internal.Runtime.Binder diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 808ac9c97d04c0..5fd58e10c30fce 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1196,10 +1196,10 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) // Managed binder types DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetObj) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetLoaderAllocator) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_IntPtr_RetVoid) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefObj_RetInt) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefObj_RetInt) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefBinderAssembly_RetInt) +DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefBinderAssembly_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 61aaa16edf3108..8da4b41961ae6d 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -617,10 +617,11 @@ DEFINE_METASIG(SM(Str_RetPtrByte, s, P(b))) DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) -DEFINE_METASIG(IM(IntPtr_Bool_RefObj_RetInt, I F r(j), i)) -DEFINE_METASIG(IM(PtrVoid_RefObj_RetInt, P(v) r(j), i)) +DEFINE_METASIG_T(IM(IntPtr_Bool_RefBinderAssembly_RetInt, I F r(C(BINDER_ASSEMBLY)), i)) +DEFINE_METASIG_T(IM(PtrVoid_RefBinderAssembly_RetInt, P(v) r(C(BINDER_ASSEMBLY)), i)) DEFINE_METASIG(SM(PtrChar_PtrChar_PtrChar_RefObj_RetInt, P(u) P(u) P(u) r(j), i)) DEFINE_METASIG_T(IM(PtrByte_RefGuid_Bool_PtrByte_RetVoid, P(b) r(g(GUID)) F P(b), v)) +DEFINE_METASIG_T(IM(RetLoaderAllocator, ,C(LOADERALLOCATOR))) // Undefine macros in case we include the file again in the compilation unit From 2ac97193c891583fdb84bb362bbd0039d205adcc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 20 Sep 2023 20:24:29 +0800 Subject: [PATCH 061/136] CoreLib bootstrap --- .../src/System/Reflection/LoaderAllocator.cs | 3 +-- src/coreclr/vm/appdomain.cpp | 26 ++++++++++--------- src/coreclr/vm/assemblyspec.cpp | 10 ++++--- src/coreclr/vm/object.h | 5 ++-- src/coreclr/vm/peassembly.cpp | 4 +-- src/coreclr/vm/readytoruninfo.cpp | 26 ++++++++++--------- 6 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index f08b54ffb36bad..67148b564342aa 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -57,12 +57,11 @@ private LoaderAllocator() #pragma warning disable CA1823, 414, 169 private LoaderAllocatorScout m_scout; private object[] m_slots; + internal Internal.Runtime.Binder.AssemblyBinder? m_binderToRelease; internal CerHashtable m_methodInstantiations; private int m_slotsUsed; #pragma warning restore CA1823, 414, 169 - internal Internal.Runtime.Binder.AssemblyBinder? m_binderToRelease; - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_EnsureReference")] internal static partial void EnsureReference(IntPtr nativeLoaderAllocator, IntPtr otherNativeLoaderAllocator); diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 25aba2505bfae0..2aaeaf89cde406 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1161,6 +1161,8 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); + + GetAppDomain()->CreateDefaultBinder(); } #ifdef _DEBUG @@ -1777,7 +1779,7 @@ void AppDomain::Create() pDomain->InitThreadStaticBlockTypeMap(); pDomain->SetStage(AppDomain::STAGE_OPEN); - pDomain->CreateDefaultBinder(); + // pDomain->CreateDefaultBinder(); // Should be delayed after CoreLib loaded pDomain.SuppressRelease(); @@ -2810,7 +2812,7 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, result->EnsureLoadLevel(targetLevel); } - if (registerNewAssembly) + if (registerNewAssembly && !pDomainAssembly->GetAssembly()->IsSystem()) // CoreLib bootstrap { GCX_COOP(); @@ -2827,16 +2829,16 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, result->EnsureLoadLevel(targetLevel); // Cache result in all cases, since found pPEAssembly could be from a different AssemblyRef than pIdentity - if (pIdentity == NULL) - { - AssemblySpec spec; - spec.InitializeSpec(result->GetPEAssembly()); - GetAppDomain()->AddAssemblyToCache(&spec, result); - } - else - { - GetAppDomain()->AddAssemblyToCache(pIdentity, result); - } + //if (pIdentity == NULL) + //{ + // AssemblySpec spec; + // spec.InitializeSpec(result->GetPEAssembly()); + // GetAppDomain()->AddAssemblyToCache(&spec, result); + //} + //else + //{ + // GetAppDomain()->AddAssemblyToCache(pIdentity, result); + //} RETURN result; } // AppDomain::LoadDomainAssembly diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 16ab09e91da00f..1da47de72851fe 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -208,10 +208,12 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) OBJECTHANDLE pCurrentBinder = GetBinder(); if (pCurrentBinder == NULL) { - ASSEMBLYBINDERREF pExpectedBinder = pFile->GetAssemblyBinder(); - // We should always have the binding context in the PEAssembly. - _ASSERTE(pExpectedBinder != NULL); - SetBinder(GetAppDomain()->CreateHandle(pExpectedBinder)); + // unblock CoreLib bootstrap + + //ASSEMBLYBINDERREF pExpectedBinder = pFile->GetAssemblyBinder(); + //// We should always have the binding context in the PEAssembly. + //_ASSERTE(pExpectedBinder != NULL); + //SetBinder(GetAppDomain()->CreateHandle(pExpectedBinder)); } } diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 2a48ec91425550..acfd5281d93db1 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1481,23 +1481,23 @@ class AssemblyLoadContextBaseObject : public Object // Modifying the order or fields of this object may require other changes to the // classlib class definition of this object. #ifdef TARGET_64BIT + OBJECTREF _assemblyBinder; OBJECTREF _unloadLock; OBJECTREF _resolvingUnmanagedDll; OBJECTREF _resolving; OBJECTREF _unloading; OBJECTREF _name; - OBJECTREF _assemblyBinder; int64_t _id; // On 64-bit platforms this is a value type so it is placed after references and pointers DWORD _state; CLR_BOOL _isCollectible; #else // TARGET_64BIT int64_t _id; // On 32-bit platforms this 64-bit value type is larger than a pointer so JIT places it first + OBJECTREF _assemblyBinder; OBJECTREF _unloadLock; OBJECTREF _resolvingUnmanagedDll; OBJECTREF _resolving; OBJECTREF _unloading; OBJECTREF _name; - OBJECTREF _assemblyBinder; DWORD _state; CLR_BOOL _isCollectible; #endif // TARGET_64BIT @@ -2289,6 +2289,7 @@ class LoaderAllocatorObject : public Object protected: LOADERALLOCATORSCOUTREF m_pLoaderAllocatorScout; OBJECTREF m_pSlots; + ASSEMBLYBINDERREF m_binderToRelease; INT32 m_slotsUsed; OBJECTREF m_methodInstantiationsTable; }; diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 5fb401ad01d4d6..937362450cea06 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -665,7 +665,7 @@ PEAssembly::PEAssembly( { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(pEmit, NULL_OK)); - PRECONDITION(pBindResultInfo == NULL || pPEImage == NULL); + // PRECONDITION(pBindResultInfo == NULL || pPEImage == NULL); // disabled for corelib STANDARD_VM_CHECK; } CONTRACTL_END; @@ -844,7 +844,7 @@ PEAssembly *PEAssembly::DoOpenSystem() IfFailThrow(((DefaultAssemblyBinder*)NULL)->BindToSystem(&pBoundAssembly)); // TODO: Is HostAssembly ever used for CoreLib? - RETURN new PEAssembly(NULL, NULL, TRUE); + RETURN new PEAssembly(NULL, NULL, TRUE, pBoundAssembly->GetPEImage()); } PEAssembly* PEAssembly::Open(BINDERASSEMBLYREF pManagedBindResult) diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index 24459fb7adf1ff..d0190ebf9cec82 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -758,7 +758,7 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat int32_t manifestAssemblyCount = 0; GUID emptyGuid = {0}; - ASSEMBLYBINDERREF binder = pModule != NULL ? pModule->GetPEAssembly()->GetAssemblyBinder() : (ASSEMBLYBINDERREF)ObjectFromHandle(pNativeImage->GetAssemblyBinder()); + // ASSEMBLYBINDERREF binder = pModule != NULL ? pModule->GetPEAssembly()->GetAssemblyBinder() : (ASSEMBLYBINDERREF)ObjectFromHandle(pNativeImage->GetAssemblyBinder()); auto pComponentAssemblyMvids = FindSection(ReadyToRunSectionType::ManifestAssemblyMvids); if (pComponentAssemblyMvids != NULL) { @@ -782,18 +782,20 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat IfFailThrow(pNativeMDImport->GetAssemblyRefProps(assemblyRef, NULL, NULL, &assemblyName, NULL, NULL, NULL, NULL)); { + // disabled for CoreLib bootstrap + // TODO: GC mode - MethodDescCallSite methDeclareDependencyOnMvid(METHOD__BINDER_ASSEMBLYBINDER__DECLAREDEPENDENCYONMVID); - ARG_SLOT args[5] = - { - ObjToArgSlot(binder), - PtrToArgSlot(componentMvid), - PtrToArgSlot(assemblyName), - BoolToArgSlot(pNativeImage != NULL), - PtrToArgSlot(pModule != NULL ? pModule->GetSimpleName() : pNativeImage->GetFileName()) - }; - - methDeclareDependencyOnMvid.Call(args); + //MethodDescCallSite methDeclareDependencyOnMvid(METHOD__BINDER_ASSEMBLYBINDER__DECLAREDEPENDENCYONMVID); + //ARG_SLOT args[5] = + //{ + // ObjToArgSlot(binder), + // PtrToArgSlot(componentMvid), + // PtrToArgSlot(assemblyName), + // BoolToArgSlot(pNativeImage != NULL), + // PtrToArgSlot(pModule != NULL ? pModule->GetSimpleName() : pNativeImage->GetFileName()) + //}; + + //methDeclareDependencyOnMvid.Call(args); } manifestAssemblyCount++; From 77276c7ef153134d2c47805f83d2f06bf309b24b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 20 Sep 2023 20:40:58 +0800 Subject: [PATCH 062/136] Managed binder initialization --- .../src/Internal/Runtime/Binder/Assembly.cs | 1 - src/coreclr/vm/appdomain.cpp | 3 ++- src/coreclr/vm/corelib.h | 9 ++++----- src/coreclr/vm/namespace.h | 2 +- src/coreclr/vm/vars.hpp | 1 + 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index a99fda17e42d7b..c02560ae14afd5 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -28,7 +28,6 @@ public AssemblyBinder? Binder public bool IsInTPA { get; } - public Assembly(nint pPEImage, bool isInTPA) { // Get assembly name def from meta data import and store it for later refs access diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 2aaeaf89cde406..49934ce23f4519 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3934,7 +3934,8 @@ OBJECTHANDLE AppDomain::CreateDefaultBinder() GCPROTECT_BEGIN(managedBinder); MethodDescCallSite ctor(METHOD__BINDER_DEFAULTASSEMBLYBINDER__CTOR); - ctor.Call((ARG_SLOT*)NULL); + ARG_SLOT arg = ObjToArgSlot(managedBinder); + ctor.Call(&arg); m_pManagedDefaultBinder = CreateHandle(managedBinder); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 5fd58e10c30fce..6aa40129b6da1b 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1195,21 +1195,20 @@ DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) #endif // FOR_ILLINK // Managed binder types -DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalLoader, AssemblyBinder) +DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalBinder, AssemblyBinder) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetLoaderAllocator) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_IntPtr_RetVoid) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefBinderAssembly_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefBinderAssembly_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) -DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalLoader, DefaultAssemblyBinder) +DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalBinder, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) -DEFINE_CLASS(BINDER_ASSEMBLY, InternalLoader, Assembly) -DEFINE_METHOD(BINDER_ASSEMBLY, ISCORELIB, get_IsCoreLib, IM_RetBool) +DEFINE_CLASS(BINDER_ASSEMBLY, InternalBinder, Assembly) -DEFINE_CLASS(BINDER_ASSEMBLYBINDERCOMMON, InternalLoader, AssemblyBinderCommon) +DEFINE_CLASS(BINDER_ASSEMBLYBINDERCOMMON, InternalBinder, AssemblyBinderCommon) DEFINE_METHOD(BINDER_ASSEMBLYBINDERCOMMON, BINDTOSYSTEMSATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefObj_RetInt) DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) diff --git a/src/coreclr/vm/namespace.h b/src/coreclr/vm/namespace.h index 7e17cc6b2b5024..11a60b6ea0be30 100644 --- a/src/coreclr/vm/namespace.h +++ b/src/coreclr/vm/namespace.h @@ -70,4 +70,4 @@ #define g_ExceptionServicesNS g_RuntimeNS ".ExceptionServices" #define g_LoaderNS g_RuntimeNS ".Loader" -#define g_InternalLoaderNS "Internal.Runtime.Loader" +#define g_InternalBinderNS "Internal.Runtime.Binder" diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 37d9da98eb1f3f..01d22d2ca65738 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -145,6 +145,7 @@ class OBJECTREF { class ReflectClassBaseObject* m_asReflectClass; class ExecutionContextObject* m_asExecutionContext; class AssemblyLoadContextBaseObject* m_asAssemblyLoadContextBase; + class AssemblyBinderObject* m_asAssemblyBinder; }; public: From ef2786e72dfc8678286fd78d349cf7bb8270d117 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 21 Sep 2023 23:57:30 +0800 Subject: [PATCH 063/136] Revert ALC.Load* to be native --- .../Loader/AssemblyLoadContext.CoreCLR.cs | 158 +++--------------- src/coreclr/vm/assemblynative.cpp | 48 ++++-- src/coreclr/vm/assemblynative.hpp | 6 +- 3 files changed, 61 insertions(+), 151 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index d5f99872ce32d7..9c6f8d26657b76 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -58,62 +58,9 @@ private static void PrepareForAssemblyLoadContextRelease(Internal.Runtime.Binder ((Internal.Runtime.Binder.CustomAssemblyBinder)ptrNativeAssemblyBinder).PrepareForLoadContextRelease(ptrAssemblyLoadContextStrong); } - private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, byte* ptrAssemblyArray, int iAssemblyArrayLen, byte* ptrSymbols, int iSymbolArrayLen) - { - IntPtr pILImage = 0; - - try - { - pILImage = PEImage_CreateFromByteArray(ptrAssemblyArray, iAssemblyArrayLen); - - // Need to verify that this is a valid CLR assembly. - if (!PEImage_CheckILFormat(pILImage)) - throw new BadImageFormatException(SR.BadImageFormat_BadILFormat); - - LoaderAllocator? loaderAllocator = assemblyBinder.GetLoaderAllocator(); - if (loaderAllocator != null && loaderAllocator.IsCollectible() && !PEImage_IsILOnly(pILImage)) - { - // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed - throw new BadImageFormatException("Cannot load a mixed assembly into a collectible AssemblyLoadContext"); - } - - // Pass the stream based assembly as IL in an attempt to bind and load it - IntPtr loadedAssembly = LoadFromPEImage(ObjectHandleOnStack.Create(ref assemblyBinder), pILImage); - RuntimeAssembly? retAssembly = null; - Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); - Debug.Assert(retAssembly != null); - - // LOG((LF_CLASSLOADER, - // LL_INFO100, - // "\tLoaded assembly from a file\n")); - - // In order to assign the PDB image (if present), - // the resulting assembly's image needs to be exactly the one - // we created above. We need pointer comparison instead of pe image equivalence - // to avoid mixed binaries/PDB pairs of other images. - // This applies to both Desktop CLR and CoreCLR, with or without fusion. - bool isSameAssembly = Internal.Runtime.Binder.AssemblyBinder.Assembly_GetPEImage(loadedAssembly) == pILImage; - - // Setting the PDB info is only applicable for our original assembly. - // This applies to both Desktop CLR and CoreCLR, with or without fusion. - if (isSameAssembly) - { - // #ifdef DEBUGGING_SUPPORTED - if (ptrSymbols != null) - { - Internal.Runtime.Binder.AssemblyBinder.Assembly_SetSymbolBytes(loadedAssembly, ptrAssemblyArray, iSymbolArrayLen); - } - // #endif - } - - return retAssembly; - } - finally - { - if (pILImage != 0) - PEImage_Release(pILImage); - } - } + [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromStream")] + private static partial void LoadFromStream(ObjectHandleOnStack ptrNativeAssemblyBinder, IntPtr ptrAssemblyArray, int iAssemblyArrayLen, IntPtr ptrSymbols, int iSymbolArrayLen, ObjectHandleOnStack retAssembly); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MultiCoreJIT_InternalSetProfileRoot", StringMarshalling = StringMarshalling.Utf16)] internal static partial void InternalSetProfileRoot(string directoryPath); @@ -126,51 +73,8 @@ private static unsafe RuntimeAssembly LoadFromStream(Internal.Runtime.Binder.Ass internal static extern void InternalStartProfile(string? profile, Internal.Runtime.Binder.AssemblyBinder ptrNativeAssemblyBinder); [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] -#pragma warning disable IDE0060 // niPath is unused - private static RuntimeAssembly LoadFromPath(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, string? ilPath, string? niPath) -#pragma warning restore IDE0060 - { - // Form the PEImage for the ILAssembly. In case of an exception, the holder will ensure - // the release of the image. - IntPtr pILImage = 0; - - try - { - if (ilPath != null) - { - pILImage = PEImage_OpenImage(ilPath, 0, default); - - // Need to verify that this is a valid CLR assembly. - if (!PEImage_CheckILFormat(pILImage)) - throw new BadImageFormatException($"{SR.BadImageFormat_BadILFormat} The format of the file '{ilPath}' is invalid."); - - LoaderAllocator? loaderAllocator = assemblyBinder.GetLoaderAllocator(); - if (loaderAllocator != null && loaderAllocator.IsCollectible() && !PEImage_IsILOnly(pILImage)) - { - // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed - throw new BadImageFormatException($"Cannot load a mixed assembly into a collectible AssemblyLoadContext. The format of the file '{ilPath}' is invalid."); - } - - IntPtr loadedAssembly = LoadFromPEImage(ObjectHandleOnStack.Create(ref assemblyBinder), pILImage); - RuntimeAssembly? retAssembly = null; - Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); - Debug.Assert(retAssembly != null); - return retAssembly; - - // LOG((LF_CLASSLOADER, - // LL_INFO100, - // "\tLoaded assembly from a file\n")); - } - - // The behavior was inherited from native implementation. - return null!; - } - finally - { - if (pILImage != 0) - PEImage_Release(pILImage); - } - } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromPath", StringMarshalling = StringMarshalling.Utf16)] + private static partial void LoadFromPath(ObjectHandleOnStack ptrNativeAssemblyBinder, string? ilPath, string? niPath, ObjectHandleOnStack retAssembly); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern Assembly[] GetLoadedAssemblies(); @@ -197,49 +101,31 @@ private static RuntimeAssembly LoadFromPath(Internal.Runtime.Binder.AssemblyBind [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] private RuntimeAssembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) { - return LoadFromPath(_assemblyBinder, assemblyPath, nativeImagePath); + RuntimeAssembly? loadedAssembly = null; + Internal.Runtime.Binder.AssemblyBinder assemblyBinder = _assemblyBinder; + LoadFromPath(ObjectHandleOnStack.Create(ref assemblyBinder), assemblyPath, nativeImagePath, ObjectHandleOnStack.Create(ref loadedAssembly)); + return loadedAssembly!; } [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySpan arrSymbols) { + RuntimeAssembly? loadedAssembly = null; + Internal.Runtime.Binder.AssemblyBinder assemblyBinder = _assemblyBinder; + fixed (byte* ptrAssembly = arrAssembly, ptrSymbols = arrSymbols) { - return LoadFromStream(_assemblyBinder, ptrAssembly, arrAssembly.Length, - ptrSymbols, arrSymbols.Length); + LoadFromStream(ObjectHandleOnStack.Create(ref assemblyBinder), new IntPtr(ptrAssembly), arrAssembly.Length, + new IntPtr(ptrSymbols), arrSymbols.Length, ObjectHandleOnStack.Create(ref loadedAssembly)); } + + return loadedAssembly!; } #if TARGET_WINDOWS - private static RuntimeAssembly LoadFromInMemoryModuleInternal(Internal.Runtime.Binder.AssemblyBinder assemblyBinder, IntPtr hModule) - { - IntPtr pILImage = 0; + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromInMemoryModule")] + private static partial IntPtr LoadFromInMemoryModuleInternal(ObjectHandleOnStack ptrNativeAssemblyBinder, IntPtr hModule, ObjectHandleOnStack retAssembly); - try - { - pILImage = PEImage_CreateFromHMODULE(hModule); - - // Need to verify that this is a valid CLR assembly. - if (!PEImage_HasCorHeader(pILImage)) - throw new BadImageFormatException(SR.BadImageFormat_BadILFormat); - - // Pass the in memory module as IL in an attempt to bind and load it - IntPtr loadedAssembly = LoadFromPEImage(ObjectHandleOnStack.Create(ref assemblyBinder), pILImage); - RuntimeAssembly? retAssembly = null; - Internal.Runtime.Binder.AssemblyBinder.Assembly_GetExposedObject(loadedAssembly, ObjectHandleOnStack.Create(ref retAssembly)); - Debug.Assert(retAssembly != null); - return retAssembly; - - // LOG((LF_CLASSLOADER, - // LL_INFO100, - // "\tLoaded assembly from a file\n")); - } - finally - { - if (pILImage != 0) - PEImage_Release(pILImage); - } - } /// /// Load a module that has already been loaded into memory by the OS loader as a .NET assembly. @@ -252,7 +138,13 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) { VerifyIsAlive(); - return LoadFromInMemoryModuleInternal(_assemblyBinder, moduleHandle); + RuntimeAssembly? loadedAssembly = null; + Internal.Runtime.Binder.AssemblyBinder assemblyBinder = _assemblyBinder; + LoadFromInMemoryModuleInternal( + ObjectHandleOnStack.Create(ref assemblyBinder), + moduleHandle, + ObjectHandleOnStack.Create(ref loadedAssembly)); + return loadedAssembly!; } } #endif diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 849bd7216a1f35..af25f47e6e94a9 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -186,8 +186,25 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI RETURN pDomainAssembly->GetAssembly(); } -// unused -extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) +LoaderAllocator* AssemblyBinder_GetNativeLoaderAllocator(ASSEMBLYBINDERREF pBinder) +{ + GCX_COOP(); + + LoaderAllocator* pNativeLA = NULL; + + GCPROTECT_BEGIN(pBinder); + + MethodDescCallSite getLA(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); + ARG_SLOT arg = ObjToArgSlot(pBinder); + LOADERALLOCATORREF pManagedLA = (LOADERALLOCATORREF)getLA.Call_RetOBJECTREF(&arg); + pNativeLA = pManagedLA->GetNativeLoaderAllocator(); + + GCPROTECT_END(); + + return pNativeLA; +} + +extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; @@ -195,8 +212,10 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB PTR_AppDomain pCurDomain = GetAppDomain(); + GCX_COOP(); + // Get the binder context in which the assembly will be loaded. - AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); + ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ptrNativeAssemblyBinder.Get(); _ASSERTE(pBinder != NULL); // Form the PEImage for the ILAssembly. In case of an exception, the holder will ensure @@ -213,7 +232,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB if (!pILImage->CheckILFormat()) THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue()); - LoaderAllocator* pLoaderAllocator = pBinder->GetLoaderAllocator(); + LoaderAllocator* pLoaderAllocator = AssemblyBinder_GetNativeLoaderAllocator(pBinder); if (pLoaderAllocator && pLoaderAllocator->IsCollectible() && !pILImage->IsILOnly()) { // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed @@ -236,8 +255,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB } /*static */ -// unused -extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, +extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly) { @@ -246,7 +264,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl BEGIN_QCALL; // Ensure that the invariants are in place - _ASSERTE(ptrNativeAssemblyBinder != NULL); + _ASSERTE(ptrNativeAssemblyBinder.Get() != NULL); _ASSERTE((ptrAssemblyArray != NULL) && (cbAssemblyArrayLength > 0)); _ASSERTE((ptrSymbolArray == NULL) || (cbSymbolArrayLength > 0)); @@ -255,11 +273,13 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl // Need to verify that this is a valid CLR assembly. if (!pILImage->CheckILFormat()) ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); + + GCX_COOP(); // Get the binder context in which the assembly will be loaded - AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); + ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ptrNativeAssemblyBinder.Get(); - LoaderAllocator* pLoaderAllocator = pBinder->GetLoaderAllocator(); + LoaderAllocator* pLoaderAllocator = AssemblyBinder_GetNativeLoaderAllocator(pBinder); if (pLoaderAllocator && pLoaderAllocator->IsCollectible() && !pILImage->IsILOnly()) { // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed @@ -267,9 +287,8 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl } // Pass the stream based assembly as IL in an attempt to bind and load it - Assembly* pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; + Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); { - GCX_COOP(); retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); } @@ -303,15 +322,14 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssembl #ifdef TARGET_WINDOWS /*static */ -// unused -extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly) +extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; BEGIN_QCALL; // Ensure that the invariants are in place - _ASSERTE(ptrNativeAssemblyBinder != NULL); + _ASSERTE(ptrNativeAssemblyBinder.Get() != NULL); _ASSERTE(hModule != NULL); PEImageHolder pILImage(PEImage::CreateFromHMODULE((HMODULE)hModule)); @@ -321,7 +339,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativ ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); // Get the binder context in which the assembly will be loaded - AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); + ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ptrNativeAssemblyBinder.Get(); // Pass the in memory module as IL in an attempt to bind and load it Assembly* pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index b2607fe1794885..d4c0c26ccb0a04 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -121,12 +121,12 @@ extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(IN extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* pAssemblyName, QCall::ObjectHandleOnStack requestingAssembly, QCall::StackCrawlMarkHandle stackMark,BOOL fThrowOnFileNotFound, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly); -extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); +extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); -extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly); +extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly); #ifdef TARGET_WINDOWS -extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly); +extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly); #endif extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly); From 148df3526378d9d01272452f21e42edfc26d8cef Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Sep 2023 00:03:41 +0800 Subject: [PATCH 064/136] Revert QCalls for ALC.Load* --- .../Loader/AssemblyLoadContext.CoreCLR.cs | 26 ----- src/coreclr/vm/assemblynative.cpp | 110 ------------------ src/coreclr/vm/assemblynative.hpp | 16 --- src/coreclr/vm/qcallentrypoints.cpp | 9 -- 4 files changed, 161 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 9c6f8d26657b76..f17c14420973a6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -15,9 +15,6 @@ public partial class AssemblyLoadContext [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] internal static partial IntPtr GetDefaultAssemblyBinder(); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromPEImage")] - private static partial IntPtr LoadFromPEImage(ObjectHandleOnStack pBinder, IntPtr pPEImage, [MarshalAs(UnmanagedType.Bool)] bool excludeAppPaths = false); - private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadContext(GCHandle ptrAssemblyLoadContext, bool representsTPALoadContext, bool isCollectible) { // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and @@ -187,35 +184,12 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetLoadContextForAssembly")] private static partial IntPtr GetLoadContextForAssembly(QCallAssembly assembly); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_OpenImage", StringMarshalling = StringMarshalling.Utf16)] - private static partial IntPtr PEImage_OpenImage(string path, int mdInternalImportFlags, Internal.Runtime.Binder.BundleFileLocation bundleFileLocation = default); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_CreateFromByteArray")] - private static unsafe partial IntPtr PEImage_CreateFromByteArray(byte* ptrArray, int size); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_CheckILFormat")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool PEImage_CheckILFormat(IntPtr pPEImage); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_IsILOnly")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool PEImage_IsILOnly(IntPtr pPEImage); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_Release")] internal static partial void PEImage_Release(IntPtr pPEImage); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetMVID")] internal static partial void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); -#if TARGET_WINDOWS - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_CreateFromHMODULE")] - private static unsafe partial IntPtr PEImage_CreateFromHMODULE(IntPtr hMod); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_HasCorHeader")] - [return: MarshalAs(UnmanagedType.Bool)] - private static partial bool PEImage_HasCorHeader(IntPtr pPEImage); -#endif - // Returns the load context in which the specified assembly has been loaded public static AssemblyLoadContext? GetLoadContext(Assembly assembly) { diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index af25f47e6e94a9..fb2d6154a62d2a 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1556,24 +1556,6 @@ extern "C" void QCALLTYPE AssemblyNative_SetSymbolBytes(Assembly * pAssembly, BY END_QCALL; } -extern "C" Assembly * QCALLTYPE AssemblyNative_LoadFromPEImage(QCall::ObjectHandleOnStack pBinder, PEImage * pPEImage, BOOL excludeAppPaths) -{ - QCALL_CONTRACT; - - Assembly* result = NULL; - - BEGIN_QCALL; - - GCX_COOP(); - - ASSEMBLYBINDERREF binder = (ASSEMBLYBINDERREF)pBinder.Get(); - result = AssemblyNative::LoadFromPEImage(binder, pPEImage, excludeAppPaths); - - END_QCALL; - - return result; -} - extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags) { QCALL_CONTRACT; @@ -1634,66 +1616,6 @@ extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPat return hr; } -extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation) -{ - QCALL_CONTRACT; - - PEImage* result = NULL; - - BEGIN_QCALL; - - result = PEImage::OpenImage(pPath, flags, bundleFileLocation); - - END_QCALL; - - return result; -} - -extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size) -{ - QCALL_CONTRACT; - - PEImage * result = NULL; - - BEGIN_QCALL; - - result = PEImage::CreateFromByteArray(array, (COUNT_T)size); - - END_QCALL; - - return result; -} - -extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BOOL result = false; - - BEGIN_QCALL; - - result = pPEImage->CheckILFormat(); - - END_QCALL; - - return result; -} - -extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BOOL result = false; - - BEGIN_QCALL; - - result = pPEImage->IsILOnly(); - - END_QCALL; - - return result; -} - extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage) { QCALL_CONTRACT; @@ -1716,38 +1638,6 @@ extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID) END_QCALL; } -#ifdef TARGET_WINDOWS -extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod) -{ - QCALL_CONTRACT; - - PEImage * result = NULL; - - BEGIN_QCALL; - - result = PEImage::CreateFromHMODULE(hMod); - - END_QCALL; - - return result; -} - -extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage) -{ - QCALL_CONTRACT; - - BOOL result = false; - - BEGIN_QCALL; - - result = pPEImage->HasCorHeader(); - - END_QCALL; - - return result; -} -#endif // TARGET_WINDOWS - extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index d4c0c26ccb0a04..db1cf2dc6a2f52 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -159,30 +159,14 @@ extern "C" PEImage * QCALLTYPE AssemblyNative_GetPEImage(Assembly * pAssembly); extern "C" void QCALLTYPE AssemblyNative_SetSymbolBytes(Assembly * pAssembly, BYTE* ptrSymbolArray, int32_t cbSymbolArrayLength); -extern "C" Assembly * QCALLTYPE AssemblyNative_LoadFromPEImage(QCall::ObjectHandleOnStack pBinder, PEImage * pPEImage, BOOL excludeAppPaths); - extern "C" IMDInternalImport * QCALLTYPE PEImage_BinderAcquireImport(PEImage * pPEImage, DWORD * pdwPAFlags); extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPath, PEImage * *ppPEImage, BundleFileLocation bundleFileLocation); -extern "C" PEImage * QCALLTYPE PEImage_OpenImage(LPCWSTR pPath, MDInternalImportFlags flags, BundleFileLocation bundleFileLocation); - -extern "C" PEImage * QCALLTYPE PEImage_CreateFromByteArray(BYTE* array, DWORD size); - -extern "C" BOOL QCALLTYPE PEImage_CheckILFormat(PEImage * pPEImage); - -extern "C" BOOL QCALLTYPE PEImage_IsILOnly(PEImage * pPEImage); - extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage); extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID); -#ifdef TARGET_WINDOWS -extern "C" PEImage * QCALLTYPE PEImage_CreateFromHMODULE(HMODULE hMod); - -extern "C" BOOL QCALLTYPE PEImage_HasCorHeader(PEImage * pPEImage); -#endif // TARGET_WINDOWS - extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly); extern "C" LoaderAllocator * QCALLTYPE DomainAssembly_GetLoaderAllocator(DomainAssembly * pDomainAssembly); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 52e99d488f2ab1..704b2e1b74f8b7 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -182,7 +182,6 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetExposedObject) DllImportEntry(AssemblyNative_GetPEImage) DllImportEntry(AssemblyNative_SetSymbolBytes) - DllImportEntry(AssemblyNative_LoadFromPEImage) DllImportEntry(AssemblyNative_GetDefaultAssemblyBinder) DllImportEntry(AssemblyNative_InitializeAssemblyLoadContext) DllImportEntry(AssemblyNative_PrepareForAssemblyLoadContextRelease) @@ -201,16 +200,8 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetExecutingAssembly) DllImportEntry(PEImage_BinderAcquireImport) DllImportEntry(PEImage_BinderAcquirePEImage) - DllImportEntry(PEImage_OpenImage) - DllImportEntry(PEImage_CreateFromByteArray) - DllImportEntry(PEImage_CheckILFormat) - DllImportEntry(PEImage_IsILOnly) DllImportEntry(PEImage_Release) DllImportEntry(PEImage_GetMVID) -#ifdef TARGET_WINDOWS - DllImportEntry(PEImage_CreateFromHMODULE) - DllImportEntry(PEImage_HasCorHeader) -#endif DllImportEntry(DomainAssembly_GetPEAssembly) DllImportEntry(DomainAssembly_GetLoaderAllocator) DllImportEntry(PEAssembly_GetHostAssembly) From 791c478067cb24fe689e98d8362d0e0005889953 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Sep 2023 10:13:36 +0800 Subject: [PATCH 065/136] Create assembly object for corelib --- .../src/Internal/Runtime/Binder/Assembly.cs | 2 +- .../Internal/Runtime/Binder/AssemblyName.cs | 4 ++-- .../Runtime/Binder/DefaultAssemblyBinder.cs | 2 ++ src/coreclr/vm/appdomain.cpp | 21 ++++++++++++++++++- src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/domainassembly.h | 1 + src/coreclr/vm/metasig.h | 1 + src/coreclr/vm/object.h | 2 +- src/coreclr/vm/peassembly.h | 7 +++++++ 9 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index c02560ae14afd5..77c207b015bf7b 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -12,9 +12,9 @@ internal sealed class Assembly { // fields used by VM #pragma warning disable CA1823, 414, 169 + private AssemblyBinder? m_binder; public IntPtr PEImage; private IntPtr m_pDomainAssembly; - private AssemblyBinder? m_binder; private bool m_isCoreLib; #pragma warning restore CA1823, 414, 169 diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 99e030f8764031..0f8b2fc42fcb48 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -117,13 +117,13 @@ public AssemblyName(IntPtr pPEImage) } // See if the assembly[def] is retargetable (ie, for a generic assembly). - if ((dwRefOrDefFlags | CorAssemblyFlags.afRetargetable) != 0) + if ((dwRefOrDefFlags & CorAssemblyFlags.afRetargetable) != 0) { IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE; } // Set ContentType - if ((dwRefOrDefFlags | CorAssemblyFlags.afContentType_Mask) == CorAssemblyFlags.afContentType_Default) + if ((dwRefOrDefFlags & CorAssemblyFlags.afContentType_Mask) == CorAssemblyFlags.afContentType_Default) { ContentType = System.Reflection.AssemblyContentType.Default; } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs index 078fe4f30a067a..516dc3b4b6620f 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs @@ -15,6 +15,8 @@ internal sealed class DefaultAssemblyBinder : AssemblyBinder // Not supported by this binder public override System.Reflection.LoaderAllocator? GetLoaderAllocator() => null; + public Assembly CreateCoreLib(IntPtr pCoreLibPEImage) => new Assembly(pCoreLibPEImage, true) { Binder = this }; + // Helper functions private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly, bool excludeAppPaths) { diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 49934ce23f4519..981feb27fa59b5 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1162,7 +1162,26 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); - GetAppDomain()->CreateDefaultBinder(); + ASSEMBLYBINDERREF defaultBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(GetAppDomain()->CreateDefaultBinder()); + + { + // AdHoc setup for corelib PEAssembly + GCPROTECT_BEGIN(defaultBinder); + + // Set binder assembly for CoreLib + MethodDescCallSite createCoreLib(METHOD__BINDER_DEFAULTASSEMBLYBINDER__CREATECORELIB); + ARG_SLOT args[2] = + { + ObjToArgSlot(defaultBinder), + PtrToArgSlot(m_pSystemPEAssembly->GetPEImage()) + }; + OBJECTREF coreLibHostAssembly = createCoreLib.Call_RetOBJECTREF(args); + m_pSystemPEAssembly->SetHostAssemblyAdHoc(CreateHandle(coreLibHostAssembly)); + + m_pSystemAssembly->GetDomainAssembly()->RegisterWithHostAssembly(); + + GCPROTECT_END(); + } } #ifdef _DEBUG diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 6aa40129b6da1b..8bc92e0954ec85 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1205,6 +1205,7 @@ DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyO DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalBinder, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) +DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CREATECORELIB, CreateCoreLib, IM_IntPtr_RetBinderAssembly) DEFINE_CLASS(BINDER_ASSEMBLY, InternalBinder, Assembly) diff --git a/src/coreclr/vm/domainassembly.h b/src/coreclr/vm/domainassembly.h index e9b198f0681062..f9e4d610677670 100644 --- a/src/coreclr/vm/domainassembly.h +++ b/src/coreclr/vm/domainassembly.h @@ -321,6 +321,7 @@ class DomainAssembly final friend class Assembly; friend class Module; friend class FileLoadLock; + friend class SystemDomain; DomainAssembly(AppDomain* pDomain, PEAssembly* pPEAssembly, LoaderAllocator* pLoaderAllocator); diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 8da4b41961ae6d..a861a60e4cc624 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -622,6 +622,7 @@ DEFINE_METASIG_T(IM(PtrVoid_RefBinderAssembly_RetInt, P(v) r(C(BINDER_ASSEMBLY)) DEFINE_METASIG(SM(PtrChar_PtrChar_PtrChar_RefObj_RetInt, P(u) P(u) P(u) r(j), i)) DEFINE_METASIG_T(IM(PtrByte_RefGuid_Bool_PtrByte_RetVoid, P(b) r(g(GUID)) F P(b), v)) DEFINE_METASIG_T(IM(RetLoaderAllocator, ,C(LOADERALLOCATOR))) +DEFINE_METASIG_T(IM(IntPtr_RetBinderAssembly, I, C(BINDER_ASSEMBLY))) // Undefine macros in case we include the file again in the compilation unit diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index acfd5281d93db1..a92feb9952b0d7 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1460,9 +1460,9 @@ class PEImage; class BinderAssemblyObject : public Object { public: + OBJECTREF m_binder; PEImage* m_PEImage; DomainAssembly* m_pDomainAssembly; - OBJECTREF m_binder; CLR_BOOL m_isCoreLib; }; diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index 5703bedd174e81..4c1e5a34cafd7d 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -307,6 +307,13 @@ class PEAssembly final return m_pHostAssembly; } + // Set host assembly after PEAssembly was created. + // Adhoc for CoreLib + void SetHostAssemblyAdHoc(OBJECTHANDLE pHostAssembly) + { + m_pHostAssembly = pHostAssembly; + } + // Returns the AssemblyBinder* instance associated with the PEAssembly // which owns the context into which the current PEAssembly was loaded. // For Dynamic assemblies this is the fallback binder. From c323031ed89f48c67dde0a39451d338cda23ace3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 22 Sep 2023 10:23:38 +0800 Subject: [PATCH 066/136] Fix some compilation and assert during corelib loading --- src/coreclr/vm/assemblyspec.cpp | 4 ++-- src/coreclr/vm/corhost.cpp | 9 ++++++++- src/coreclr/vm/nativelibrary.cpp | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 1da47de72851fe..8da249f67f0ac9 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -410,7 +410,7 @@ ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) // // For (3), fetch the fallback load context binder reference. - pParentAssemblyBinder = ObjectFromHandle(GetFallbackBinderForRequestingAssembly()); + pParentAssemblyBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(GetFallbackBinderForRequestingAssembly()); } if (!pParentAssemblyBinder) @@ -420,7 +420,7 @@ ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) // // In such a case, the parent assembly (semantically) is CoreLibrary and thus, the default binding context should be // used as the parent assembly binder. - pParentAssemblyBinder = ObjectFromHandle(pDomain->GetDefaultBinder()); + pParentAssemblyBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pDomain->GetDefaultBinder()); } return pParentAssemblyBinder; diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index e758f826303bac..1942fc767eb9c0 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -618,18 +618,25 @@ HRESULT CorHost2::CreateAppDomainWithManager( pDomain->SetNativeDllSearchDirectories(pwzNativeDllSearchDirectories); { + GCX_COOP(); + ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pDomain->GetDefaultBinder()); _ASSERTE(pBinder != NULL); + GCPROTECT_BEGIN(pBinder); + MethodDescCallSite methSetupBindingPaths(METHOD__BINDER_DEFAULTASSEMBLYBINDER__SETUP_BINDING_PATHS); - ARG_SLOT args[3] = + ARG_SLOT args[4] = { + ObjToArgSlot(pBinder), PtrToArgSlot(pwzTrustedPlatformAssemblies), PtrToArgSlot(pwzPlatformResourceRoots), PtrToArgSlot(pwzAppPaths) }; methSetupBindingPaths.Call(args); + + GCPROTECT_END(); } #if defined(TARGET_UNIX) diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index 0ace5f7964837d..fdaa72be641c25 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -331,6 +331,8 @@ namespace } #endif // !TARGET_UNIX + GCX_COOP(); + NATIVE_LIBRARY_HANDLE hmod = NULL; PEAssembly *pManifestFile = pAssembly->GetPEAssembly(); ASSEMBLYBINDERREF pBinder = pManifestFile->GetAssemblyBinder(); @@ -348,8 +350,6 @@ namespace // Call System.Runtime.Loader.AssemblyLoadContext.ResolveUnmanagedDll to give // The custom assembly context a chance to load the unmanaged dll. - GCX_COOP(); - STRINGREF pUnmanagedDllName; pUnmanagedDllName = StringObject::NewString(wszLibName); From 8f6fde9426cc61ee18ff09625dc64dc42d34a874 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 24 Sep 2023 00:01:55 +0800 Subject: [PATCH 067/136] Fix more asserts during loading --- .../Runtime/Binder/ApplicationContext.cs | 12 +++++-- src/coreclr/vm/appdomain.cpp | 8 +++-- src/coreclr/vm/assemblyspec.cpp | 2 +- src/coreclr/vm/coreassemblyspec.cpp | 32 +++++++++++++------ src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/metasig.h | 2 +- src/coreclr/vm/peassembly.cpp | 4 +-- 7 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index bdb30574ffbb7f..240955bdd44194 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -67,13 +67,19 @@ private static bool GetNextPath(string paths, ref int startPos, out string outPa int iEnd = startPos; // Where current path ends int iNext; // Where next path starts + static int IndexOfInRange(ReadOnlySpan str, int start, char ch) + { + int index = str[start..].IndexOf(ch); + return index >= 0 ? index + start : index; + } + if (wrappedWithQuotes) { - iEnd = paths.AsSpan(iEnd).IndexOf('\"'); + iEnd = IndexOfInRange(paths, iEnd, '\"'); if (iEnd != -1) { // Find where the next path starts - there should be a path separator right after the closing quotation mark - iNext = paths.AsSpan(iEnd).IndexOf(PATH_SEPARATOR_CHAR); + iNext = IndexOfInRange(paths, iEnd, PATH_SEPARATOR_CHAR); if (iNext != -1) { iNext++; @@ -89,7 +95,7 @@ private static bool GetNextPath(string paths, ref int startPos, out string outPa throw new ArgumentException(nameof(paths)); } } - else if ((iEnd = paths.AsSpan(iEnd).IndexOf(PATH_SEPARATOR_CHAR)) != -1) + else if ((iEnd = IndexOfInRange(paths, iEnd, PATH_SEPARATOR_CHAR)) != -1) { iNext = iEnd + 1; } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 981feb27fa59b5..0daf7698e46bb4 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3565,7 +3565,7 @@ PEAssembly * AppDomain::BindAssemblySpec( PRECONDITION(pSpec->GetAppDomain() == this); PRECONDITION(this==::GetAppDomain()); - GCX_PREEMP(); + GCX_COOP(); BOOL fForceReThrow = FALSE; @@ -3582,7 +3582,9 @@ PEAssembly * AppDomain::BindAssemblySpec( { { - BINDERASSEMBLYREF boundAssembly; + BINDERASSEMBLYREF boundAssembly = NULL; + GCPROTECT_BEGIN(boundAssembly); + hrBindResult = pSpec->Bind(this, &boundAssembly); if (boundAssembly != NULL) @@ -3631,6 +3633,8 @@ PEAssembly * AppDomain::BindAssemblySpec( } } } + + GCPROTECT_END(); } } } diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 8da249f67f0ac9..dfb45a614d9eb1 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -373,7 +373,7 @@ ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) { NOTHROW; GC_NOTRIGGER; - MODE_ANY; + MODE_COOPERATIVE; PRECONDITION(pDomain != NULL); } CONTRACTL_END; diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index c14b5769ebf775..1df07a5c85469b 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -33,7 +33,9 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly CONTRACTL { INSTANCE_CHECK; - STANDARD_VM_CHECK; + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; PRECONDITION(CheckPointer(ppAssembly)); PRECONDITION(CheckPointer(pAppDomain)); PRECONDITION(IsCoreLib() == FALSE); // This should never be called for CoreLib (explicit loading) @@ -42,11 +44,21 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly HRESULT hr=S_OK; + GCX_COOP(); + + struct + { + ASSEMBLYBINDERREF pBinder; + BINDERASSEMBLYREF pPrivAsm; + } gc; + // Have a default binding context setup - ASSEMBLYBINDERREF pBinder = GetBinderFromParentAssembly(pAppDomain); + gc.pBinder = GetBinderFromParentAssembly(pAppDomain); + gc.pPrivAsm = NULL; - BINDERASSEMBLYREF pPrivAsm; - _ASSERTE(pBinder != NULL); + _ASSERTE(gc.pBinder != NULL); + + GCPROTECT_BEGIN(gc); if (IsCoreLibSatellite()) { @@ -64,7 +76,7 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly PtrToArgSlot(sSystemDirectory.GetUnicode()), PtrToArgSlot(sSimpleName.GetUnicode()), PtrToArgSlot(sCultureName.GetUnicode()), - PtrToArgSlot(&pPrivAsm) + PtrToArgSlot(&gc.pPrivAsm) }; hr = methSatellite.Call_RetHR(args); @@ -77,9 +89,9 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly MethodDescCallSite methBindAssemblyByName(METHOD__BINDER_ASSEMBLYBINDER__BINDASSEMBLYBYNAME); ARG_SLOT args[3] = { - ObjToArgSlot(pBinder), + ObjToArgSlot(gc.pBinder), PtrToArgSlot(&assemblyNameData), - PtrToArgSlot(&pPrivAsm) + PtrToArgSlot(&gc.pPrivAsm) }; hr = methBindAssemblyByName.Call_RetHR(args); @@ -87,10 +99,12 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly if (SUCCEEDED(hr)) { - _ASSERTE(pPrivAsm != NULL); - *ppAssembly = pPrivAsm; + _ASSERTE(gc.pPrivAsm != NULL); + *ppAssembly = gc.pPrivAsm; } + GCPROTECT_END(); + return hr; } diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 8bc92e0954ec85..8449aafa4ed16f 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1210,7 +1210,7 @@ DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CREATECORELIB, CreateCoreLib, IM_Int DEFINE_CLASS(BINDER_ASSEMBLY, InternalBinder, Assembly) DEFINE_CLASS(BINDER_ASSEMBLYBINDERCOMMON, InternalBinder, AssemblyBinderCommon) -DEFINE_METHOD(BINDER_ASSEMBLYBINDERCOMMON, BINDTOSYSTEMSATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefObj_RetInt) +DEFINE_METHOD(BINDER_ASSEMBLYBINDERCOMMON, BINDTOSYSTEMSATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefBinderAssembly_RetInt) DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index a861a60e4cc624..bed3a6d2fe164a 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -619,7 +619,7 @@ DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) DEFINE_METASIG_T(IM(IntPtr_Bool_RefBinderAssembly_RetInt, I F r(C(BINDER_ASSEMBLY)), i)) DEFINE_METASIG_T(IM(PtrVoid_RefBinderAssembly_RetInt, P(v) r(C(BINDER_ASSEMBLY)), i)) -DEFINE_METASIG(SM(PtrChar_PtrChar_PtrChar_RefObj_RetInt, P(u) P(u) P(u) r(j), i)) +DEFINE_METASIG_T(SM(PtrChar_PtrChar_PtrChar_RefBinderAssembly_RetInt, P(u) P(u) P(u) r(C(BINDER_ASSEMBLY)), i)) DEFINE_METASIG_T(IM(PtrByte_RefGuid_Bool_PtrByte_RetVoid, P(b) r(g(GUID)) F P(b), v)) DEFINE_METASIG_T(IM(RetLoaderAllocator, ,C(LOADERALLOCATOR))) DEFINE_METASIG_T(IM(IntPtr_RetBinderAssembly, I, C(BINDER_ASSEMBLY))) diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 937362450cea06..ead2a5a74c8aad 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -1103,10 +1103,10 @@ TADDR PEAssembly::GetMDInternalRWAddress() // Returns the AssemblyBinder* instance associated with the PEAssembly ASSEMBLYBINDERREF PEAssembly::GetAssemblyBinder() { - LIMITED_METHOD_CONTRACT; - CONTRACTL { + GC_NOTRIGGER; + NOTHROW; MODE_COOPERATIVE; } CONTRACTL_END From 754a81c52d058c933d43cbab1dc804cceb3ad5d4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 24 Sep 2023 17:47:03 +0800 Subject: [PATCH 068/136] Fix calls to BindUsingPEImage --- .../src/Internal/Runtime/Binder/AssemblyBinder.cs | 5 +++-- .../Internal/Runtime/Binder/AssemblyBinderCommon.cs | 2 +- .../Binder/Tracing/ResolutionAttemptedOperation.cs | 3 ++- src/coreclr/vm/assemblynative.cpp | 10 ++++++++-- src/coreclr/vm/assemblyspec.cpp | 5 ++++- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 82f1b7437e8cd7..57176daebf959c 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -84,12 +84,13 @@ public void AddLoadedAssembly(IntPtr loadedAssembly) public static string GetNameForDiagnosticsFromManagedALC(GCHandle managedALC) { - if (managedALC.Target == GCHandle.FromIntPtr(AssemblyLoadContext.GetDefaultAssemblyBinder()).Target) + AssemblyLoadContext? alc = managedALC.IsAllocated ? (AssemblyLoadContext?)managedALC.Target : null; + + if (alc == null || alc == GCHandle.FromIntPtr(AssemblyLoadContext.GetDefaultAssemblyBinder()).Target) { return "Default"; } - var alc = managedALC.Target as AssemblyLoadContext; Debug.Assert(alc != null); return alc.ToString(); } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 53e347bc76d44a..5a6f2246cbc0f6 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -691,7 +691,7 @@ or RO_E_METADATA_NAME_NOT_FOUND public static int Register(ApplicationContext applicationContext, ref BindResult bindResult) { - Debug.Assert(bindResult.IsContextBound); + Debug.Assert(!bindResult.IsContextBound); Debug.Assert(bindResult.Assembly != null); applicationContext.IncrementVersion(); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index 3db41b7f189f1e..cdf73610288309 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -85,8 +85,9 @@ public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? if (_assemblyNameObject != null) _assemblyName = _assemblyNameObject.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); - if (pManagedALC.Target is AssemblyLoadContext managedALC) + if (pManagedALC.IsAllocated) { + Debug.Assert(pManagedALC.Target is AssemblyLoadContext); // AssemblyBinder::GetNameForDiagnosticsFromManagedALC(managedALC, m_assemblyLoadContextName); _assemblyLoadContextName = AssemblyBinder.GetNameForDiagnosticsFromManagedALC(pManagedALC); } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index fb2d6154a62d2a..e3df5a9ab6ea63 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -126,7 +126,9 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI { CONTRACT(Assembly*) { - STANDARD_VM_CHECK; + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; PRECONDITION(pBinder != NULL); PRECONDITION(pImage != NULL); POSTCONDITION(CheckPointer(RETVAL)); @@ -149,7 +151,9 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI HRESULT hr = S_OK; PTR_AppDomain pCurDomain = GetAppDomain(); - MethodDescCallSite methBind(METHOD__BINDER_ASSEMBLYBINDER__BINDUSINGPEIMAGE); + GCPROTECT_BEGIN(pBinder); + + MethodDescCallSite methBind(METHOD__BINDER_ASSEMBLYBINDER__BINDUSINGPEIMAGE, &pBinder); ARG_SLOT args[4] = { ObjToArgSlot(pBinder), @@ -159,6 +163,8 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI }; hr = methBind.Call_RetHR(args); + GCPROTECT_END(); + if (hr != S_OK) { StackSString name; diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index dfb45a614d9eb1..0ea8d01945e34a 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -513,7 +513,10 @@ Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath) if (!pILImage->CheckILFormat()) THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue()); - RETURN AssemblyNative::LoadFromPEImage((ASSEMBLYBINDERREF)ObjectFromHandle(AppDomain::GetCurrentDomain()->GetDefaultBinder()), pILImage, true /* excludeAppPaths */); + { + GCX_COOP(); + RETURN AssemblyNative::LoadFromPEImage((ASSEMBLYBINDERREF)ObjectFromHandle(AppDomain::GetCurrentDomain()->GetDefaultBinder()), pILImage, true /* excludeAppPaths */); + } } HRESULT AssemblySpec::CheckFriendAssemblyName() From 6ee05b28dfd97459cabf0678db7efd8b9863bc3d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Sep 2023 02:04:59 +0800 Subject: [PATCH 069/136] Assembly object layout --- .../src/Internal/Runtime/Binder/Assembly.cs | 16 ++++++++++------ src/coreclr/vm/assemblynative.cpp | 2 +- src/coreclr/vm/corelib.h | 7 +++++++ src/coreclr/vm/object.h | 4 +++- src/coreclr/vm/peassembly.cpp | 2 +- src/coreclr/vm/vars.hpp | 1 + 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 77c207b015bf7b..854498efed8516 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -13,8 +13,10 @@ internal sealed class Assembly // fields used by VM #pragma warning disable CA1823, 414, 169 private AssemblyBinder? m_binder; - public IntPtr PEImage; + private AssemblyName m_assemblyName; + private IntPtr m_peImage; private IntPtr m_pDomainAssembly; + private bool m_isInTPA; private bool m_isCoreLib; #pragma warning restore CA1823, 414, 169 @@ -24,14 +26,16 @@ public AssemblyBinder? Binder set => m_binder = value; } - public AssemblyName AssemblyName { get; } + public AssemblyName AssemblyName => m_assemblyName; - public bool IsInTPA { get; } + public IntPtr PEImage => m_peImage; + + public bool IsInTPA => m_isInTPA; public Assembly(nint pPEImage, bool isInTPA) { // Get assembly name def from meta data import and store it for later refs access - AssemblyName = new AssemblyName(pPEImage) + m_assemblyName = new AssemblyName(pPEImage) { IsDefinition = true }; @@ -45,8 +49,8 @@ public Assembly(nint pPEImage, bool isInTPA) throw new BadImageFormatException(); } - IsInTPA = isInTPA; - PEImage = pPEImage; + m_isInTPA = isInTPA; + m_peImage = pPEImage; } } } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index e3df5a9ab6ea63..0f50c5bbc625cc 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -185,7 +185,7 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI } } - PEAssemblyHolder pPEAssembly(PEAssembly::Open(pAssembly->m_PEImage, pAssembly)); + PEAssemblyHolder pPEAssembly(PEAssembly::Open(pAssembly->m_peImage, pAssembly)); bindOperation.SetResult(pPEAssembly.GetValue()); DomainAssembly *pDomainAssembly = pCurDomain->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 8449aafa4ed16f..2f9b6772dcdeb4 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1208,6 +1208,13 @@ DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPat DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CREATECORELIB, CreateCoreLib, IM_IntPtr_RetBinderAssembly) DEFINE_CLASS(BINDER_ASSEMBLY, InternalBinder, Assembly) +DEFINE_CLASS_U(InternalBinder, Assembly, BinderAssemblyObject) +DEFINE_FIELD_U(m_binder, BinderAssemblyObject, m_binder) +DEFINE_FIELD_U(m_assemblyName, BinderAssemblyObject, m_assemblyName) +DEFINE_FIELD_U(m_peImage, BinderAssemblyObject, m_peImage) +DEFINE_FIELD_U(m_pDomainAssembly, BinderAssemblyObject, m_pDomainAssembly) +DEFINE_FIELD_U(m_isInTPA, BinderAssemblyObject, m_isInTPA) +DEFINE_FIELD_U(m_isCoreLib, BinderAssemblyObject, m_isCoreLib) DEFINE_CLASS(BINDER_ASSEMBLYBINDERCOMMON, InternalBinder, AssemblyBinderCommon) DEFINE_METHOD(BINDER_ASSEMBLYBINDERCOMMON, BINDTOSYSTEMSATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefBinderAssembly_RetInt) diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index a92feb9952b0d7..dc8cfe4f64dfa7 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1461,8 +1461,10 @@ class BinderAssemblyObject : public Object { public: OBJECTREF m_binder; - PEImage* m_PEImage; + OBJECTREF m_assemblyName; + PEImage* m_peImage; DomainAssembly* m_pDomainAssembly; + CLR_BOOL m_isInTPA; CLR_BOOL m_isCoreLib; }; diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index ead2a5a74c8aad..ecabb95398cfb7 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -683,7 +683,7 @@ PEAssembly::PEAssembly( m_pHostAssembly = nullptr; m_pFallbackBinder = nullptr; - pPEImage = (pBindResultInfo != NULL) ? pBindResultInfo->m_PEImage : pPEImage; + pPEImage = (pBindResultInfo != NULL) ? pBindResultInfo->m_peImage : pPEImage; if (pPEImage) { _ASSERTE(pPEImage->CheckUniqueInstance()); diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 01d22d2ca65738..9a623803d90fcb 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -146,6 +146,7 @@ class OBJECTREF { class ExecutionContextObject* m_asExecutionContext; class AssemblyLoadContextBaseObject* m_asAssemblyLoadContextBase; class AssemblyBinderObject* m_asAssemblyBinder; + class BinderAssemblyObject* m_asBinderAssembly; }; public: From 9884e7bb3ad5ef79cd12ac48c25277b323cdf4fb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 25 Sep 2023 02:12:42 +0800 Subject: [PATCH 070/136] Load application assembly --- src/coreclr/vm/appdomain.cpp | 4 +++- src/coreclr/vm/nativelibrary.cpp | 3 ++- src/coreclr/vm/peassembly.cpp | 20 ++++++++++++++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 0daf7698e46bb4..4292648da79207 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -2764,7 +2764,8 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if // marked as collectible - MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); + GCPROTECT_BEGIN(pAssemblyBinder); + MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR, &pAssemblyBinder); ARG_SLOT args[1] = { ObjToArgSlot(pAssemblyBinder) @@ -2775,6 +2776,7 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, { pLoaderAllocator = pManagedLA->GetNativeLoaderAllocator(); } + GCPROTECT_END(); } if (pLoaderAllocator == NULL) diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index fdaa72be641c25..73ff9252008279 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -341,7 +341,8 @@ namespace ASSEMBLYBINDERREF pCurrentBinder = pBinder; // For assemblies bound via default binder, we should use the standard mechanism to make the pinvoke call. - if (pCurrentBinder->m_isDefault) + // Binder can be null during CoreLib bootstrap. + if (pCurrentBinder == NULL || pCurrentBinder->m_isDefault) { return NULL; } diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index ecabb95398cfb7..86784323900635 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -666,7 +666,9 @@ PEAssembly::PEAssembly( CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(pEmit, NULL_OK)); // PRECONDITION(pBindResultInfo == NULL || pPEImage == NULL); // disabled for corelib - STANDARD_VM_CHECK; + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; } CONTRACTL_END; @@ -744,7 +746,13 @@ PEAssembly *PEAssembly::Open( PEImage * pPEImageIL, BINDERASSEMBLYREF pManagedHostAssembly) { - STANDARD_VM_CONTRACT; + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_COOPERATIVE; + } + CONTRACTL_END; PEAssembly * pPEAssembly = new PEAssembly( NULL, // BindResult @@ -843,8 +851,12 @@ PEAssembly *PEAssembly::DoOpenSystem() ReleaseHolder pBoundAssembly; IfFailThrow(((DefaultAssemblyBinder*)NULL)->BindToSystem(&pBoundAssembly)); - // TODO: Is HostAssembly ever used for CoreLib? - RETURN new PEAssembly(NULL, NULL, TRUE, pBoundAssembly->GetPEImage()); + { + GCX_COOP(); + + // HostAssembly is set afterwards for CoreLib + RETURN new PEAssembly(NULL, NULL, TRUE, pBoundAssembly->GetPEImage()); + } } PEAssembly* PEAssembly::Open(BINDERASSEMBLYREF pManagedBindResult) From 2ae3cd1e9ab81f3d208fdb3e521be2ad82f9e1c3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 2 Oct 2023 22:32:09 +0800 Subject: [PATCH 071/136] AssemblyBinder layout --- src/coreclr/vm/corelib.h | 4 ++++ src/coreclr/vm/object.h | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 2f9b6772dcdeb4..78594284d1e427 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1202,6 +1202,10 @@ DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntP DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefBinderAssembly_RetInt) DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) +DEFINE_CLASS_U(InternalBinder, AssemblyBinder, AssemblyBinderObject) +DEFINE_FIELD_U(m_managedALC, AssemblyBinderObject, m_managedALC) +DEFINE_FIELD_U(m_isDefault, AssemblyBinderObject, m_isDefault) + DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalBinder, DefaultAssemblyBinder) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index dc8cfe4f64dfa7..27f5f5e5630eb4 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1443,9 +1443,12 @@ NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembl // managed Internal.Runtime.Binder.AssemblyBinder class AssemblyBinderObject : public Object { + OBJECTREF m_appContext; + OBJECTREF m_assemblySimpleNameMvidCheckHash; + OBJECTREF m_loadedAssemblies; public: - INT_PTR m_managedALC; CLR_BOOL m_isDefault; + INT_PTR m_managedALC; }; #ifdef USE_CHECKED_OBJECTREFS From 44582808bc4fe5d4542a0d86812f645f4254f5df Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 3 Oct 2023 16:18:46 +0800 Subject: [PATCH 072/136] Fix BinderAcquirePEImage usage --- .../src/Internal/Runtime/Binder/AssemblyBinderCommon.cs | 6 ++++-- src/coreclr/vm/assemblynative.cpp | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 5a6f2246cbc0f6..ae0c6cce84ac07 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -35,7 +35,7 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquireImport")] public static unsafe partial IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf8)] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf16)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetPEAssembly")] @@ -675,6 +675,7 @@ or RO_E_METADATA_NAME_NOT_FOUND } assembly = new Assembly(pPEImage, isInTPA); + pPEImage = IntPtr.Zero; return HResults.S_OK; } catch (Exception e) @@ -685,7 +686,8 @@ or RO_E_METADATA_NAME_NOT_FOUND finally { // SAFE_RELEASE(pPEImage); - AssemblyLoadContext.PEImage_Release(pPEImage); + if (pPEImage != IntPtr.Zero) + AssemblyLoadContext.PEImage_Release(pPEImage); } } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 0f50c5bbc625cc..729debbf2ff2c9 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1604,6 +1604,8 @@ extern "C" HRESULT QCALLTYPE PEImage_BinderAcquirePEImage(LPCWSTR wszAssemblyPat BEGIN_QCALL; + *ppPEImage = NULL; + EX_TRY { PEImageHolder pImage = PEImage::OpenImage(wszAssemblyPath, MDInternalImport_Default, bundleFileLocation); From 9a2df4ff7b7aa43841c337589976bab1615825b6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 6 Oct 2023 16:51:49 +0800 Subject: [PATCH 073/136] Enable AssemblySpecBindingCache --- .../Internal/Runtime/Binder/AssemblyBinder.cs | 1 + src/coreclr/vm/appdomain.cpp | 29 +- src/coreclr/vm/assemblyspec.cpp | 447 +++++++++--------- src/coreclr/vm/baseassemblyspec.inl | 18 +- 4 files changed, 270 insertions(+), 225 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs index 57176daebf959c..b1ff9fb1000dba 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs @@ -39,6 +39,7 @@ internal abstract partial class AssemblyBinder protected AssemblyBinder() { m_isDefault = IsDefault; + _ = GetHashCode(); // Calculate hashcode for AssemblySpecBindingCache usage } public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 4292648da79207..2212e5cfbca57a 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1181,6 +1181,11 @@ void SystemDomain::Init() m_pSystemAssembly->GetDomainAssembly()->RegisterWithHostAssembly(); GCPROTECT_END(); + + // Add CoreLib to AssemblyBindingCache + AssemblySpec spec; + spec.InitializeSpec(m_pSystemPEAssembly); + GetAppDomain()->AddAssemblyToCache(&spec, m_pSystemAssembly->GetDomainAssembly()); } } @@ -2850,16 +2855,20 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, result->EnsureLoadLevel(targetLevel); // Cache result in all cases, since found pPEAssembly could be from a different AssemblyRef than pIdentity - //if (pIdentity == NULL) - //{ - // AssemblySpec spec; - // spec.InitializeSpec(result->GetPEAssembly()); - // GetAppDomain()->AddAssemblyToCache(&spec, result); - //} - //else - //{ - // GetAppDomain()->AddAssemblyToCache(pIdentity, result); - //} + if (!result->IsSystem()) + { + // CoreLib bootstrap: this method is called before managed binder available + if (pIdentity == NULL) + { + AssemblySpec spec; + spec.InitializeSpec(result->GetPEAssembly()); + GetAppDomain()->AddAssemblyToCache(&spec, result); + } + else + { + GetAppDomain()->AddAssemblyToCache(pIdentity, result); + } + } RETURN result; } // AppDomain::LoadDomainAssembly diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 0ea8d01945e34a..19a468252e5ed7 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -692,48 +692,50 @@ AssemblySpecBindingCache::AssemblyBinding* AssemblySpecBindingCache::LookupInter } CONTRACTL_END; - return (AssemblyBinding *) INVALIDENTRY; - - //UPTR key = (UPTR)pSpec->Hash(); - - //AssemblyBinder *pBinderForLookup = NULL; - //bool fGetBindingContextFromParent = true; - - //// Check if the AssemblySpec already has specified its binding context. This will be set for assemblies that are - //// attempted to be explicitly bound using AssemblyLoadContext LoadFrom* methods. - //pBinderForLookup = pSpec->GetBinder(); - - //if (pBinderForLookup != NULL) - //{ - // // We are working with the actual binding context in which the assembly was expected to be loaded. - // // Thus, we don't need to get it from the parent assembly. - // fGetBindingContextFromParent = false; - //} - - //if (fGetBindingContextFromParent) - //{ - // pBinderForLookup = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); - // pSpec->SetBinder(pBinderForLookup); - //} - - //if (pBinderForLookup) - //{ - // key = key ^ (UPTR)pBinderForLookup; - //} - - //AssemblyBinding* pEntry = (AssemblyBinding *)m_map.LookupValue(key, pSpec); - - //// Reset the binding context if one was originally never present in the AssemblySpec and we didnt find any entry - //// in the cache. - //if (fGetBindingContextFromParent) - //{ - // if (pEntry == (AssemblyBinding *) INVALIDENTRY) - // { - // pSpec->SetBinder(NULL); - // } - //} - - //return pEntry; + GCX_COOP(); + + UPTR key = (UPTR)pSpec->Hash(); + + ASSEMBLYBINDERREF pBinderForLookup = NULL; + bool fGetBindingContextFromParent = true; + + // Check if the AssemblySpec already has specified its binding context. This will be set for assemblies that are + // attempted to be explicitly bound using AssemblyLoadContext LoadFrom* methods. + OBJECTHANDLE pBinderHandle = pSpec->GetBinder(); + if (pBinderHandle != NULL) + pBinderForLookup = ObjectFromHandle(pSpec->GetBinder()); + + if (pBinderForLookup != NULL) + { + // We are working with the actual binding context in which the assembly was expected to be loaded. + // Thus, we don't need to get it from the parent assembly. + fGetBindingContextFromParent = false; + } + + if (fGetBindingContextFromParent) + { + pBinderForLookup = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); + pSpec->SetBinder(GetAppDomain()->CreateHandle(pBinderForLookup)); + } + + if (pBinderForLookup != NULL) + { + key = key ^ (UPTR)(pBinderForLookup->GetHeader()->GetBits() | MASK_HASHCODE); + } + + AssemblyBinding* pEntry = (AssemblyBinding *)m_map.LookupValue(key, pSpec); + + // Reset the binding context if one was originally never present in the AssemblySpec and we didnt find any entry + // in the cache. + if (fGetBindingContextFromParent) + { + if (pEntry == (AssemblyBinding *) INVALIDENTRY) + { + pSpec->SetBinder(NULL); + } + } + + return pEntry; } BOOL AssemblySpecBindingCache::Contains(AssemblySpec *pSpec) @@ -925,64 +927,68 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly } CONTRACT_END; - //UPTR key = (UPTR)pSpec->Hash(); - - //AssemblyBinder* pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); - //key = key ^ (UPTR)pBinderContextForLookup; - - //if (!pSpec->GetBinder()) - //{ - // pSpec->SetBinder(pBinderContextForLookup); - //} - - //AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); - - //if (entry == (AssemblyBinding *) INVALIDENTRY) - //{ - // AssemblyBindingHolder abHolder; - - // LoaderHeap* pHeap = m_pHeap; - // if (pAssembly->IsCollectible()) - // { - // pHeap = pAssembly->GetLoaderAllocator()->GetHighFrequencyHeap(); - // } - - // entry = abHolder.CreateAssemblyBinding(pHeap); - // entry->Init(pSpec,pAssembly->GetPEAssembly(),pAssembly,NULL,pHeap, abHolder.GetPamTracker()); - - // m_map.InsertValue(key, entry); - - // abHolder.SuppressRelease(); - - // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreAssembly): Add cached entry (%p) with PEAssembly %p",entry,pAssembly->GetPEAssembly()); - // RETURN TRUE; - //} - //else - //{ - // if (!entry->IsError()) - // { - // if (entry->GetAssembly() != NULL) - // { - // // OK if this is a duplicate - // if (entry->GetAssembly() == pAssembly) - // RETURN TRUE; - // } - // else - // { - // // OK if we have a matching PEAssembly - // if (entry->GetFile() != NULL - // && pAssembly->GetPEAssembly()->Equals(entry->GetFile())) - // { - // entry->SetAssembly(pAssembly); - // RETURN TRUE; - // } - // } - // } - - // // Invalid cache transition (see above note about state transitions) - // RETURN FALSE; - //} - RETURN TRUE; + UPTR key = (UPTR)pSpec->Hash(); + + { + GCX_COOP(); + + ASSEMBLYBINDERREF pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + + key = key ^ (UPTR)(pBinderContextForLookup->GetHeader()->GetBits() | MASK_HASHCODE); + + if (!pSpec->GetBinder()) + { + pSpec->SetBinder(GetAppDomain()->CreateHandle(pBinderContextForLookup)); + } + } + + AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); + + if (entry == (AssemblyBinding *) INVALIDENTRY) + { + AssemblyBindingHolder abHolder; + + LoaderHeap* pHeap = m_pHeap; + if (pAssembly->IsCollectible()) + { + pHeap = pAssembly->GetLoaderAllocator()->GetHighFrequencyHeap(); + } + + entry = abHolder.CreateAssemblyBinding(pHeap); + entry->Init(pSpec,pAssembly->GetPEAssembly(),pAssembly,NULL,pHeap, abHolder.GetPamTracker()); + + m_map.InsertValue(key, entry); + + abHolder.SuppressRelease(); + + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreAssembly): Add cached entry (%p) with PEAssembly %p",entry,pAssembly->GetPEAssembly()); + RETURN TRUE; + } + else + { + if (!entry->IsError()) + { + if (entry->GetAssembly() != NULL) + { + // OK if this is a duplicate + if (entry->GetAssembly() == pAssembly) + RETURN TRUE; + } + else + { + // OK if we have a matching PEAssembly + if (entry->GetFile() != NULL + && pAssembly->GetPEAssembly()->Equals(entry->GetFile())) + { + entry->SetAssembly(pAssembly); + RETURN TRUE; + } + } + } + + // Invalid cache transition (see above note about state transitions) + RETURN FALSE; + } } // Note that this routine may be called outside a lock, so may be racing with another thread. @@ -1002,68 +1008,79 @@ BOOL AssemblySpecBindingCache::StorePEAssembly(AssemblySpec *pSpec, PEAssembly * } CONTRACT_END; - //UPTR key = (UPTR)pSpec->Hash(); - - //AssemblyBinder* pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); - //key = key ^ (UPTR)pBinderContextForLookup; - - //if (!pSpec->GetBinder()) - //{ - // pSpec->SetBinder(pBinderContextForLookup); - //} - - //AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); - - //if (entry == (AssemblyBinding *) INVALIDENTRY) - //{ - // AssemblyBindingHolder abHolder; - - // LoaderHeap* pHeap = m_pHeap; - - // if (pBinderContextForLookup != NULL) - // { - // LoaderAllocator* pLoaderAllocator = pBinderContextForLookup->GetLoaderAllocator(); - - // // Assemblies loaded with AssemblyLoadContext need to use a different heap if - // // marked as collectible - // if (pLoaderAllocator) - // { - // pHeap = pLoaderAllocator->GetHighFrequencyHeap(); - // } - // } - - // entry = abHolder.CreateAssemblyBinding(pHeap); - - // entry->Init(pSpec, pPEAssembly,NULL,NULL,pHeap, abHolder.GetPamTracker()); - - // m_map.InsertValue(key, entry); - // abHolder.SuppressRelease(); - - // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly: Add cached entry (%p) with PEAssembly %p\n", entry, pPEAssembly); - - // RETURN TRUE; - //} - //else - //{ - // if (!entry->IsError()) - // { - // // OK if this is a duplicate - // if (entry->GetFile() != NULL - // && pPEAssembly->Equals(entry->GetFile())) - // RETURN TRUE; - // } - // else - // if (entry->IsPostBindError()) - // { - // // Another thread has reported what's going to happen later. - // entry->ThrowIfError(); - - // } - // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"Incompatible cached entry found (%p) when adding PEAssembly %p\n", entry, pPEAssembly); - // // Invalid cache transition (see above note about state transitions) - // RETURN FALSE; - //} - RETURN TRUE; + GCX_COOP(); + + UPTR key = (UPTR)pSpec->Hash(); + + ASSEMBLYBINDERREF pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); + + if (pBinderContextForLookup != NULL) + { + key = key ^ (UPTR)(pBinderContextForLookup->GetHeader()->GetBits() | MASK_HASHCODE); + } + + if (!pSpec->GetBinder()) + { + pSpec->SetBinder(GetAppDomain()->CreateHandle(pBinderContextForLookup)); + } + + AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); + + if (entry == (AssemblyBinding *) INVALIDENTRY) + { + AssemblyBindingHolder abHolder; + + LoaderHeap* pHeap = m_pHeap; + + if (pBinderContextForLookup != NULL) + { + GCPROTECT_BEGIN(pBinderContextForLookup); + + MethodDescCallSite getLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR, &pBinderContextForLookup); + ARG_SLOT arg = ObjToArgSlot(pBinderContextForLookup); + LOADERALLOCATORREF pLoaderAllocator = (LOADERALLOCATORREF)getLoaderAllocator.Call_RetOBJECTREF(&arg); + + // Assemblies loaded with AssemblyLoadContext need to use a different heap if + // marked as collectible + if (pLoaderAllocator != NULL) + { + pHeap = pLoaderAllocator->GetNativeLoaderAllocator()->GetHighFrequencyHeap(); + } + + GCPROTECT_END(); + } + + entry = abHolder.CreateAssemblyBinding(pHeap); + + entry->Init(pSpec, pPEAssembly,NULL,NULL,pHeap, abHolder.GetPamTracker()); + + m_map.InsertValue(key, entry); + abHolder.SuppressRelease(); + + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly: Add cached entry (%p) with PEAssembly %p\n", entry, pPEAssembly); + + RETURN TRUE; + } + else + { + if (!entry->IsError()) + { + // OK if this is a duplicate + if (entry->GetFile() != NULL + && pPEAssembly->Equals(entry->GetFile())) + RETURN TRUE; + } + else + if (entry->IsPostBindError()) + { + // Another thread has reported what's going to happen later. + entry->ThrowIfError(); + + } + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"Incompatible cached entry found (%p) when adding PEAssembly %p\n", entry, pPEAssembly); + // Invalid cache transition (see above note about state transitions) + RETURN FALSE; + } } BOOL AssemblySpecBindingCache::StoreException(AssemblySpec *pSpec, Exception* pEx) @@ -1079,58 +1096,60 @@ BOOL AssemblySpecBindingCache::StoreException(AssemblySpec *pSpec, Exception* pE } CONTRACT_END; - //UPTR key = (UPTR)pSpec->Hash(); - - //AssemblyBinding *entry = LookupInternal(pSpec, TRUE); - //if (entry == (AssemblyBinding *) INVALIDENTRY) - //{ - // // TODO: Merge this with the failure lookup in the binder - // // - // // Since no entry was found for this assembly in any binding context, save the failure - // // in the DefaultBinder context - // AssemblyBinder* pBinderToSaveException = NULL; - // pBinderToSaveException = pSpec->GetBinder(); - // if (pBinderToSaveException == NULL) - // { - // pBinderToSaveException = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); - // key = key ^ (UPTR)pBinderToSaveException; - // } - //} - - //if (entry == (AssemblyBinding *) INVALIDENTRY) { - // AssemblyBindingHolder abHolder; - // entry = abHolder.CreateAssemblyBinding(m_pHeap); - - // entry->Init(pSpec,NULL,NULL,pEx,m_pHeap, abHolder.GetPamTracker()); - - // m_map.InsertValue(key, entry); - // abHolder.SuppressRelease(); - - // STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreException): Add cached entry (%p) with exception %p",entry,pEx); - // RETURN TRUE; - //} - //else - //{ - // // OK if this is a duplicate - // if (entry->IsError()) - // { - // if (entry->GetHR() == pEx->GetHR()) - // RETURN TRUE; - // } - // else - // { - // // OK to transition to error if we don't have an Assembly yet - // if (entry->GetAssembly() == NULL) - // { - // entry->InitException(pEx); - // RETURN TRUE; - // } - // } - - // // Invalid cache transition (see above note about state transitions) - // RETURN FALSE; - //} - RETURN TRUE; + UPTR key = (UPTR)pSpec->Hash(); + + AssemblyBinding *entry = LookupInternal(pSpec, TRUE); + if (entry == (AssemblyBinding *) INVALIDENTRY) + { + // TODO: Merge this with the failure lookup in the binder + // + // Since no entry was found for this assembly in any binding context, save the failure + // in the DefaultBinder context + GCX_COOP(); + + ASSEMBLYBINDERREF pBinderToSaveException = NULL; + pBinderToSaveException = ObjectFromHandle(pSpec->GetBinder()); + if (pBinderToSaveException == NULL) + { + pBinderToSaveException = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); + + key = key ^ (UPTR)(pBinderToSaveException->GetHeader()->GetBits() | MASK_HASHCODE); + } + } + + if (entry == (AssemblyBinding *) INVALIDENTRY) { + AssemblyBindingHolder abHolder; + entry = abHolder.CreateAssemblyBinding(m_pHeap); + + entry->Init(pSpec,NULL,NULL,pEx,m_pHeap, abHolder.GetPamTracker()); + + m_map.InsertValue(key, entry); + abHolder.SuppressRelease(); + + STRESS_LOG2(LF_CLASSLOADER,LL_INFO10,"StorePEAssembly (StoreException): Add cached entry (%p) with exception %p",entry,pEx); + RETURN TRUE; + } + else + { + // OK if this is a duplicate + if (entry->IsError()) + { + if (entry->GetHR() == pEx->GetHR()) + RETURN TRUE; + } + else + { + // OK to transition to error if we don't have an Assembly yet + if (entry->GetAssembly() == NULL) + { + entry->InitException(pEx); + RETURN TRUE; + } + } + + // Invalid cache transition (see above note about state transitions) + RETURN FALSE; + } } BOOL AssemblySpecBindingCache::RemoveAssembly(DomainAssembly* pAssembly) diff --git a/src/coreclr/vm/baseassemblyspec.inl b/src/coreclr/vm/baseassemblyspec.inl index 125e31a592a9ea..07a505aa3c87b2 100644 --- a/src/coreclr/vm/baseassemblyspec.inl +++ b/src/coreclr/vm/baseassemblyspec.inl @@ -14,6 +14,11 @@ #ifndef __BASE_ASSEMBLY_SPEC_INL__ #define __BASE_ASSEMBLY_SPEC_INL__ +#include +#include +#include +#include + inline int BaseAssemblySpec::CompareStrings(LPCUTF8 string1, LPCUTF8 string2) { WRAPPER_NO_CONTRACT; @@ -279,7 +284,18 @@ inline BOOL BaseAssemblySpec::CompareEx(BaseAssemblySpec *pSpec, DWORD dwCompare // If the assemblySpec contains the binding context, then check if they match. if (pSpec->m_pBinder != m_pBinder) { - return FALSE; + if (pSpec->m_pBinder != NULL && m_pBinder != NULL) + { + GCX_COOP(); + if (ObjectFromHandle(pSpec->m_pBinder) != ObjectFromHandle(m_pBinder)) + { + return FALSE; + } + } + else + { + return FALSE; + } } return TRUE; From 20c1347f3717a9cd6f93a6fab5283a7c058ce1d2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Oct 2023 21:20:17 +0800 Subject: [PATCH 074/136] StartProfileOptimization --- .../System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index f17c14420973a6..2d6f0b495f1230 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -65,10 +65,6 @@ private static void PrepareForAssemblyLoadContextRelease(Internal.Runtime.Binder [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MultiCoreJIT_InternalStartProfile", StringMarshalling = StringMarshalling.Utf16)] internal static partial void InternalStartProfile(string? profile, IntPtr ptrNativeAssemblyBinder); - // Foo - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void InternalStartProfile(string? profile, Internal.Runtime.Binder.AssemblyBinder ptrNativeAssemblyBinder); - [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromPath", StringMarshalling = StringMarshalling.Utf16)] private static partial void LoadFromPath(ObjectHandleOnStack ptrNativeAssemblyBinder, string? ilPath, string? niPath, ObjectHandleOnStack retAssembly); @@ -227,7 +223,9 @@ public void SetProfileOptimizationRoot(string directoryPath) // Start profile optimization for the specified profile name. public void StartProfileOptimization(string? profile) { - InternalStartProfile(profile, _assemblyBinder); + // AssemblyBinder isn't supported in profiler implementation yet. + // See MulticoreJitProfilePlayer::LoadAssembly + InternalStartProfile(profile, IntPtr.Zero); } internal static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) From db8c08c9dcb7d592c11e712c2f246937e1bc250b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Oct 2023 22:09:28 +0800 Subject: [PATCH 075/136] AppBundle support --- .../Runtime/Binder/AssemblyBinderCommon.cs | 64 +++++++++++++++++-- src/coreclr/vm/assemblynative.cpp | 41 ++++++++++++ src/coreclr/vm/assemblynative.hpp | 6 ++ src/coreclr/vm/qcallentrypoints.cpp | 3 + 4 files changed, 109 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index ae0c6cce84ac07..34cd8b7aae4a0d 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -28,6 +28,8 @@ internal struct BundleFileLocation public long Size; public long Offset; public long UncompressedSize; + + public readonly bool IsValid => Offset != 0; } internal static partial class AssemblyBinderCommon @@ -47,6 +49,16 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetLoaderAllocator")] private static partial IntPtr DomainAssembly_GetLoaderAllocator(IntPtr pDomainAssembly); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_AppIsBundle")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool AppIsBundle(); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_ProbeAppBundle", StringMarshalling = StringMarshalling.Utf16)] + private static partial BundleFileLocation ProbeAppBundle(string path, [MarshalAs(UnmanagedType.Bool)] bool pathIsBundleRelative); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_GetAppBundleBasePath")] + private static partial void GetAppBundleBasePath(StringHandleOnStack path); + public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; @@ -257,11 +269,17 @@ private static unsafe int BindToSystemSatellite(char* systemDirectory, char* sim // Satellite assembly's path: // * Absolute path when looking for a file on disk // * Bundle-relative path when looking within the single-file bundle. + string sCoreLibSatellite = string.Empty; - // PathSource pathSource = PathSource.Bundle; - // BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /*pathIsBundleRelative */ true); - PathSource pathSource = PathSource.ApplicationAssemblies; - string sCoreLibSatellite = new string(systemDirectory) + relativePath; + PathSource pathSource = PathSource.Bundle; + BundleFileLocation bundleFileLocation = ProbeAppBundle(relativePath, pathIsBundleRelative: true); + if (!bundleFileLocation.IsValid) + { + sCoreLibSatellite = new string(systemDirectory); + pathSource = PathSource.ApplicationAssemblies; + } + + sCoreLibSatellite = Path.Combine(sCoreLibSatellite, relativePath); int hr = GetAssembly(sCoreLibSatellite, isInTPA: true, out assembly, default); if (hr < 0) @@ -542,8 +560,44 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN // The list of bundled assemblies is contained in the bundle manifest, and NOT in the TPA. // Therefore the bundle is first probed using the assembly's simple name. // If found, the assembly is loaded from the bundle. + if (AppIsBundle()) + { + // Search Assembly.ni.dll, then Assembly.dll + // The Assembly.ni.dll paths are rare, and intended for supporting managed C++ R2R assemblies. + ReadOnlySpan candidates = ["ni.dll", ".dll"]; + + // Loop through the binding paths looking for a matching assembly + foreach (string candidate in candidates) + { + string assemblyFileName = requestedAssemblyName.SimpleName + candidate; + string? assemblyFilePath = string.Empty; + GetAppBundleBasePath(new StringHandleOnStack(ref assemblyFilePath)); + assemblyFilePath += assemblyFileName; + + BundleFileLocation bundleFileLocation = ProbeAppBundle(assemblyFileName, pathIsBundleRelative: true); + if (bundleFileLocation.IsValid) + { + int hr = GetAssembly(assemblyFilePath, isInTPA: true, out tpaAssembly, bundleFileLocation); - // if (Bundle::AppIsBundle()) + NativeRuntimeEventSource.Log.KnownPathProbed(assemblyFilePath, (ushort)PathSource.Bundle, hr); + + if (hr != HResults.E_FILENOTFOUND) + { + // Any other error is fatal + if (hr < 0) return hr; + + Debug.Assert(tpaAssembly != null); + if (TestCandidateRefMatchesDef(requestedAssemblyName, tpaAssembly.AssemblyName, tpaListAssembly: true)) + { + // We have found the requested assembly match in the bundle with validation of the full-qualified name. + // Bind to it. + bindResult.SetResult(tpaAssembly); + return HResults.S_OK; + } + } + } + } + } // Is assembly on TPA list? Debug.Assert(applicationContext.TrustedPlatformAssemblyMap != null); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 729debbf2ff2c9..78221dd40a94f4 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1690,3 +1690,44 @@ extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly return result; } + +extern "C" BOOL QCALLTYPE Bundle_AppIsBundle() +{ + QCALL_CONTRACT; + + BOOL result = FALSE; + + BEGIN_QCALL; + + result = Bundle::AppIsBundle(); + + END_QCALL; + + return result; +} + +extern "C" BundleFileLocation QCALLTYPE Bundle_ProbeAppBundle(LPCWSTR path, BOOL pathIsBundleRelative) +{ + QCALL_CONTRACT; + + BundleFileLocation result = BundleFileLocation::Invalid(); + + BEGIN_QCALL; + + result = Bundle::ProbeAppBundle(SString(path), pathIsBundleRelative); + + END_QCALL; + + return result; +} + +extern "C" void QCALLTYPE Bundle_GetAppBundleBasePath(QCall::StringHandleOnStack path) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + path.Set(Bundle::AppBundle->BasePath().GetUnicode()); + + END_QCALL; +} diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index db1cf2dc6a2f52..426b39a36d715c 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -172,4 +172,10 @@ extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * extern "C" LoaderAllocator * QCALLTYPE DomainAssembly_GetLoaderAllocator(DomainAssembly * pDomainAssembly); extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly); + +extern "C" BOOL QCALLTYPE Bundle_AppIsBundle(); + +extern "C" BundleFileLocation QCALLTYPE Bundle_ProbeAppBundle(LPCWSTR path, BOOL pathIsBundleRelative); + +extern "C" void QCALLTYPE Bundle_GetAppBundleBasePath(QCall::StringHandleOnStack path); #endif diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index b9884548351949..17b3ba268aab88 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -205,6 +205,9 @@ static const Entry s_QCall[] = DllImportEntry(DomainAssembly_GetPEAssembly) DllImportEntry(DomainAssembly_GetLoaderAllocator) DllImportEntry(PEAssembly_GetHostAssembly) + DllImportEntry(Bundle_AppIsBundle) + DllImportEntry(Bundle_ProbeAppBundle) + DllImportEntry(Bundle_GetAppBundleBasePath) #if defined(FEATURE_MULTICOREJIT) DllImportEntry(MultiCoreJIT_InternalSetProfileRoot) DllImportEntry(MultiCoreJIT_InternalStartProfile) From ef3f57bcd9f8312d4d02623a9fa472a7f1346ed9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Oct 2023 22:34:14 +0800 Subject: [PATCH 076/136] Implement BindSatelliteResource --- .../Runtime/Binder/ApplicationContext.cs | 4 +- .../Runtime/Binder/AssemblyBinderCommon.cs | 120 +++++++++++++++++- 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs index 240955bdd44194..00276ee08052de 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs @@ -32,7 +32,7 @@ internal sealed class ApplicationContext public object ContextCriticalSection { get; } = new object(); - private readonly List _platformResourceRoots = new List(); + public List PlatformResourceRoots { get; } = new List(); public List AppPaths { get; } = new List(); @@ -255,7 +255,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string throw new ArgumentException(nameof(pathName)); } - _platformResourceRoots.Add(pathName); + PlatformResourceRoots.Add(pathName); } // diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index 34cd8b7aae4a0d..a8544a634d85a8 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -8,6 +8,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using System.Runtime.Loader; using Internal.Runtime.Binder.Tracing; @@ -468,7 +469,118 @@ private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyNam return boundAssemblyName.Equals(requestedAssemblyName, includeFlags); } - // TODO: BindSatelliteResource + private static int BindSatelliteResourceFromBundle(AssemblyName requestedAssemblyName, string relativePath, ref BindResult bindResult) + { + int hr = HResults.S_OK; + + BundleFileLocation bundleFileLocation = ProbeAppBundle(relativePath, pathIsBundleRelative: true); + if (!bundleFileLocation.IsValid) + { + return hr; + } + + hr = GetAssembly(relativePath, isInTPA: false, out Assembly? assembly, bundleFileLocation); + + NativeRuntimeEventSource.Log.KnownPathProbed(relativePath, (ushort)PathSource.Bundle, hr); + + // Missing files are okay and expected when probing + if (hr == HResults.E_FILENOTFOUND) + { + return HResults.S_OK; + } + + bindResult.SetAttemptResult(hr, assembly); + if (hr < 0) + return hr; + + Debug.Assert(assembly != null); + AssemblyName boundAssemblyName = assembly.AssemblyName; + if (TestCandidateRefMatchesDef(requestedAssemblyName, boundAssemblyName, tpaListAssembly: false)) + { + bindResult.SetResult(assembly); + hr = HResults.S_OK; + } + else + { + hr = HResults.FUSION_E_REF_DEF_MISMATCH; + } + + bindResult.SetAttemptResult(hr, assembly); + return hr; + } + + private static int BindSatelliteResourceByProbingPaths( + List resourceRoots, + AssemblyName requestedAssemblyName, + string relativePath, + ref BindResult bindResult, + PathSource pathSource) + { + foreach (string bindingPath in resourceRoots) + { + string fileName = Path.Combine(relativePath, bindingPath); + int hr = GetAssembly(fileName, isInTPA: false, out Assembly? assembly); + NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); + + // Missing files are okay and expected when probing + if (hr == HResults.E_FILENOTFOUND) + { + return HResults.S_OK; + } + + Debug.Assert(assembly != null); + AssemblyName boundAssemblyName = assembly.AssemblyName; + if (TestCandidateRefMatchesDef(requestedAssemblyName, boundAssemblyName, tpaListAssembly: false)) + { + bindResult.SetResult(assembly); + hr = HResults.S_OK; + } + else + { + hr = HResults.FUSION_E_REF_DEF_MISMATCH; + } + + bindResult.SetAttemptResult(hr, assembly); + return hr; + } + + // Up-stack expects S_OK when we don't find any candidate assemblies and no fatal error occurred (ie, no S_FALSE) + return HResults.S_OK; + } + + private static int BindSatelliteResource(ApplicationContext applicationContext, AssemblyName requestedAssemblyName, ref BindResult bindResult) + { + Debug.Assert(!requestedAssemblyName.IsNeutralCulture); + + string fileName = Path.Combine(requestedAssemblyName.CultureOrLanguage, requestedAssemblyName.SimpleName) + ".dll"; + + // Satellite resource probing strategy is to look: + // * First within the single-file bundle + // * Then under each of the Platform Resource Roots + // * Then under each of the App Paths. + // + // During each search, if we find a platform resource file with matching file name, but whose ref-def didn't match, + // fall back to application resource lookup to handle case where a user creates resources with the same + // names as platform ones. + + int hr = BindSatelliteResourceFromBundle(requestedAssemblyName, fileName, ref bindResult); + + if (bindResult.Assembly != null || hr < 0) + { + return hr; + } + + hr = BindSatelliteResourceByProbingPaths(applicationContext.PlatformResourceRoots, requestedAssemblyName, fileName, ref bindResult, PathSource.PlatformResourceRoots); + + if (bindResult.Assembly != null || hr < 0) + { + return hr; + } + + hr = BindSatelliteResourceByProbingPaths(applicationContext.AppPaths, requestedAssemblyName, fileName, ref bindResult, PathSource.AppPaths); + + return hr; + } private static int BindAssemblyByProbingPaths(List bindingPaths, AssemblyName requestedAssemblyName, out Assembly? result) { @@ -547,9 +659,11 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN { bool fPartialMatchOnTpa = false; - if (requestedAssemblyName.IsNeutralCulture) + if (!requestedAssemblyName.IsNeutralCulture) { - // IF_FAIL_GO(BindSatelliteResource(pApplicationContext, pRequestedAssemblyName, pBindResult)); + int hr = BindSatelliteResource(applicationContext, requestedAssemblyName, ref bindResult); + if (hr < 0) + return hr; } else { From d6972b5f5e6f29b9091a230c29945f6abda17c1a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Oct 2023 22:45:36 +0800 Subject: [PATCH 077/136] Delete unused QCalls --- src/coreclr/vm/assemblynative.cpp | 91 ----------------------------- src/coreclr/vm/assemblynative.hpp | 4 -- src/coreclr/vm/qcallentrypoints.cpp | 2 - 3 files changed, 97 deletions(-) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 78221dd40a94f4..89c701df72b72b 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1214,79 +1214,6 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH END_QCALL; } -/*static*/ -// unused -extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible) -{ - QCALL_CONTRACT; - - INT_PTR ptrNativeAssemblyBinder = NULL; - - BEGIN_QCALL; - - // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and - // only one thread is ever executing a ctor for a given instance. - // - - // Initialize the assembly binder instance in the VM - PTR_AppDomain pCurDomain = AppDomain::GetCurrentDomain(); - DefaultAssemblyBinder *pDefaultBinder = /*pCurDomain->GetDefaultBinder()*/ NULL; - if (!fRepresentsTPALoadContext) - { - // Initialize a custom assembly binder - CustomAssemblyBinder *pCustomBinder = NULL; - - AssemblyLoaderAllocator* loaderAllocator = NULL; - OBJECTHANDLE loaderAllocatorHandle = NULL; - - if (fIsCollectible) - { - // Create a new AssemblyLoaderAllocator for an AssemblyLoadContext - loaderAllocator = new AssemblyLoaderAllocator(); - - GCX_COOP(); - LOADERALLOCATORREF pManagedLoaderAllocator = NULL; - GCPROTECT_BEGIN(pManagedLoaderAllocator); - { - GCX_PREEMP(); - // Some of the initialization functions are not virtual. Call through the derived class - // to prevent calling the base class version. - loaderAllocator->Init(pCurDomain); - loaderAllocator->InitVirtualCallStubManager(pCurDomain); - - // Setup the managed proxy now, but do not actually transfer ownership to it. - // Once everything is setup and nothing can fail anymore, the ownership will be - // atomically transferred by call to LoaderAllocator::ActivateManagedTracking(). - loaderAllocator->SetupManagedTracking(&pManagedLoaderAllocator); - } - - // Create a strong handle to the LoaderAllocator - loaderAllocatorHandle = pCurDomain->CreateHandle(pManagedLoaderAllocator); - - GCPROTECT_END(); - - loaderAllocator->ActivateManagedTracking(); - } - - IfFailThrow(CustomAssemblyBinder::SetupContext(pDefaultBinder, loaderAllocator, loaderAllocatorHandle, ptrManagedAssemblyLoadContext, &pCustomBinder)); - ptrNativeAssemblyBinder = reinterpret_cast(pCustomBinder); - } - else - { - // We are initializing the managed instance of Assembly Load Context that would represent the TPA binder. - // First, confirm we do not have an existing managed ALC attached to the TPA binder. - _ASSERTE(pDefaultBinder->GetManagedAssemblyLoadContext() == NULL); - - // Attach the managed TPA binding context with the native one. - pDefaultBinder->SetManagedAssemblyLoadContext(ptrManagedAssemblyLoadContext); - ptrNativeAssemblyBinder = reinterpret_cast(pDefaultBinder); - } - - END_QCALL; - - return ptrNativeAssemblyBinder; -} - extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder() { QCALL_CONTRACT; @@ -1302,24 +1229,6 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder() return ptrDefaultAssemblyBinder; } -/*static*/ -extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext) -{ - QCALL_CONTRACT; - - BOOL fDestroyed = FALSE; - - BEGIN_QCALL; - - - { - GCX_COOP(); - reinterpret_cast(ptrNativeAssemblyBinder)->PrepareForLoadContextRelease(ptrManagedStrongAssemblyLoadContext); - } - - END_QCALL; -} - /*static*/ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly) { diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 426b39a36d715c..6e54762f47f000 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -115,10 +115,6 @@ extern "C" BOOL QCALLTYPE AssemblyNative_GetIsCollectible(QCall::AssemblyHandle extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder(); -extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible); - -extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext); - extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* pAssemblyName, QCall::ObjectHandleOnStack requestingAssembly, QCall::StackCrawlMarkHandle stackMark,BOOL fThrowOnFileNotFound, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly); extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 17b3ba268aab88..fabc77d3c6d19d 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -183,8 +183,6 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetPEImage) DllImportEntry(AssemblyNative_SetSymbolBytes) DllImportEntry(AssemblyNative_GetDefaultAssemblyBinder) - DllImportEntry(AssemblyNative_InitializeAssemblyLoadContext) - DllImportEntry(AssemblyNative_PrepareForAssemblyLoadContextRelease) DllImportEntry(AssemblyNative_LoadFromPath) DllImportEntry(AssemblyNative_LoadFromStream) #ifdef TARGET_WINDOWS From 244aedd29e450f806f5fa810489cafca11c9fba8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 7 Oct 2023 22:55:11 +0800 Subject: [PATCH 078/136] Make ProbeAppBundle compatible to extern "C" --- .../src/Internal/Runtime/Binder/AssemblyBinderCommon.cs | 8 ++++---- src/coreclr/vm/assemblynative.cpp | 8 ++------ src/coreclr/vm/assemblynative.hpp | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index a8544a634d85a8..e1a27535d40772 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -55,7 +55,7 @@ internal static partial class AssemblyBinderCommon private static partial bool AppIsBundle(); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_ProbeAppBundle", StringMarshalling = StringMarshalling.Utf16)] - private static partial BundleFileLocation ProbeAppBundle(string path, [MarshalAs(UnmanagedType.Bool)] bool pathIsBundleRelative); + private static partial void ProbeAppBundle(string path, [MarshalAs(UnmanagedType.Bool)] bool pathIsBundleRelative, out BundleFileLocation result); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_GetAppBundleBasePath")] private static partial void GetAppBundleBasePath(StringHandleOnStack path); @@ -273,7 +273,7 @@ private static unsafe int BindToSystemSatellite(char* systemDirectory, char* sim string sCoreLibSatellite = string.Empty; PathSource pathSource = PathSource.Bundle; - BundleFileLocation bundleFileLocation = ProbeAppBundle(relativePath, pathIsBundleRelative: true); + ProbeAppBundle(relativePath, pathIsBundleRelative: true, out BundleFileLocation bundleFileLocation); if (!bundleFileLocation.IsValid) { sCoreLibSatellite = new string(systemDirectory); @@ -473,7 +473,7 @@ private static int BindSatelliteResourceFromBundle(AssemblyName requestedAssembl { int hr = HResults.S_OK; - BundleFileLocation bundleFileLocation = ProbeAppBundle(relativePath, pathIsBundleRelative: true); + ProbeAppBundle(relativePath, pathIsBundleRelative: true, out BundleFileLocation bundleFileLocation); if (!bundleFileLocation.IsValid) { return hr; @@ -688,7 +688,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN GetAppBundleBasePath(new StringHandleOnStack(ref assemblyFilePath)); assemblyFilePath += assemblyFileName; - BundleFileLocation bundleFileLocation = ProbeAppBundle(assemblyFileName, pathIsBundleRelative: true); + ProbeAppBundle(assemblyFileName, pathIsBundleRelative: true, out BundleFileLocation bundleFileLocation); if (bundleFileLocation.IsValid) { int hr = GetAssembly(assemblyFilePath, isInTPA: true, out tpaAssembly, bundleFileLocation); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 89c701df72b72b..eda867b8ba3737 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1615,19 +1615,15 @@ extern "C" BOOL QCALLTYPE Bundle_AppIsBundle() return result; } -extern "C" BundleFileLocation QCALLTYPE Bundle_ProbeAppBundle(LPCWSTR path, BOOL pathIsBundleRelative) +extern "C" void QCALLTYPE Bundle_ProbeAppBundle(LPCWSTR path, BOOL pathIsBundleRelative, BundleFileLocation* result) { QCALL_CONTRACT; - BundleFileLocation result = BundleFileLocation::Invalid(); - BEGIN_QCALL; - result = Bundle::ProbeAppBundle(SString(path), pathIsBundleRelative); + *result = Bundle::ProbeAppBundle(SString(path), pathIsBundleRelative); END_QCALL; - - return result; } extern "C" void QCALLTYPE Bundle_GetAppBundleBasePath(QCall::StringHandleOnStack path) diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 6e54762f47f000..36f9b2ee3ea91d 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -171,7 +171,7 @@ extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly extern "C" BOOL QCALLTYPE Bundle_AppIsBundle(); -extern "C" BundleFileLocation QCALLTYPE Bundle_ProbeAppBundle(LPCWSTR path, BOOL pathIsBundleRelative); +extern "C" void QCALLTYPE Bundle_ProbeAppBundle(LPCWSTR path, BOOL pathIsBundleRelative, BundleFileLocation* result); extern "C" void QCALLTYPE Bundle_GetAppBundleBasePath(QCall::StringHandleOnStack path); #endif From f954fea8b79008993416e9f6e793687f88b32b55 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 15 Oct 2023 20:58:44 +0800 Subject: [PATCH 079/136] Register managed binder to native LoaderAllocator --- .../Runtime/Binder/CustomAssemblyBinder.cs | 7 ++++-- .../src/System/Reflection/LoaderAllocator.cs | 6 ++++- src/coreclr/vm/loaderallocator.cpp | 25 +++++++++++++------ src/coreclr/vm/loaderallocator.hpp | 8 ++---- src/coreclr/vm/object.h | 1 - 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs index 06e9cb69b3a4a3..ad3cf667508a6c 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs @@ -42,7 +42,8 @@ public CustomAssemblyBinder( // VERIFY(pLoaderAllocator->AddReferenceIfAlive()); // ((AssemblyLoaderAllocator*)pLoaderAllocator)->RegisterBinder(pBinder); - loaderAllocator.m_binderToRelease = this; + var thisHandle = GCHandle.Alloc(this); + loaderAllocator.RegisterBinder(thisHandle); } _loaderAllocator = loaderAllocator; @@ -76,8 +77,10 @@ public void PrepareForLoadContextRelease(GCHandle ptrManagedStrongAssemblyLoadCo _loaderAllocatorHandle = default; } - public void ReleaseLoadContext() + ~CustomAssemblyBinder() { + // CustomAssemblyBinder::ReleaseLoadContext + Debug.Assert(ManagedAssemblyLoadContext.IsAllocated); Debug.Assert(_ptrManagedStrongAssemblyLoadContext.IsAllocated); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index 67148b564342aa..b3c9df0366086e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -57,7 +57,6 @@ private LoaderAllocator() #pragma warning disable CA1823, 414, 169 private LoaderAllocatorScout m_scout; private object[] m_slots; - internal Internal.Runtime.Binder.AssemblyBinder? m_binderToRelease; internal CerHashtable m_methodInstantiations; private int m_slotsUsed; #pragma warning restore CA1823, 414, 169 @@ -72,5 +71,10 @@ private LoaderAllocator() internal static partial bool IsCollectible(IntPtr nativeLoaderAllocator); internal bool IsCollectible() => IsCollectible(m_scout.m_nativeLoaderAllocator); + + internal void RegisterBinder(GCHandle handle) => RegisterBinder(m_scout.m_nativeLoaderAllocator, handle); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_RegisterBinder")] + private static partial void RegisterBinder(IntPtr pNativeLA, GCHandle handle); } } diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index f1ff01b59652a7..9b5373cb537a43 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -279,6 +279,17 @@ extern "C" BOOL QCALLTYPE LoaderAllocator_IsCollectible(QCall::LoaderAllocatorHa return result; } +extern "C" void QCALLTYPE LoaderAllocator_RegisterBinder(AssemblyLoaderAllocator* pLA, OBJECTHANDLE handle) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + pLA->RegisterBinder(handle); + + END_QCALL; +} + BOOL LoaderAllocator::EnsureInstantiation(Module *pDefiningModule, Instantiation inst) { CONTRACTL @@ -1741,17 +1752,11 @@ void AssemblyLoaderAllocator::Init(AppDomain* pAppDomain) AssemblyLoaderAllocator::~AssemblyLoaderAllocator() { - if (m_binderToRelease != NULL) - { - delete m_binderToRelease; - m_binderToRelease = NULL; - } - delete m_pShuffleThunkCache; m_pShuffleThunkCache = NULL; } -void AssemblyLoaderAllocator::RegisterBinder(CustomAssemblyBinder* binderToRelease) +void AssemblyLoaderAllocator::RegisterBinder(OBJECTHANDLE binderToRelease) { // When the binder is registered it will be released by the destructor // of this instance @@ -2056,7 +2061,11 @@ void AssemblyLoaderAllocator::ReleaseManagedAssemblyLoadContext() if (m_binderToRelease != NULL) { // Release the managed ALC - m_binderToRelease->ReleaseLoadContext(); + // Depends on the destructor of managed binder + + // m_binderToRelease->ReleaseLoadContext(); + DestroyHandle(m_binderToRelease); + m_binderToRelease = NULL; } } diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 5216e0bb433b19..5fe13e668c3f02 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -900,12 +900,8 @@ class AssemblyLoaderAllocator : public LoaderAllocator virtual void RegisterHandleForCleanup(OBJECTHANDLE objHandle); virtual void UnregisterHandleFromCleanup(OBJECTHANDLE objHandle); virtual void CleanupHandles(); - CustomAssemblyBinder* GetBinder() - { - return m_binderToRelease; - } virtual ~AssemblyLoaderAllocator(); - void RegisterBinder(CustomAssemblyBinder* binderToRelease); + void RegisterBinder(OBJECTHANDLE binderToRelease); virtual void ReleaseManagedAssemblyLoadContext(); #endif // !defined(DACCESS_COMPILE) @@ -923,7 +919,7 @@ class AssemblyLoaderAllocator : public LoaderAllocator SList m_handleCleanupList; #if !defined(DACCESS_COMPILE) - CustomAssemblyBinder* m_binderToRelease; + OBJECTHANDLE m_binderToRelease; #endif private: diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 27f5f5e5630eb4..744c0352b91fd1 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -2294,7 +2294,6 @@ class LoaderAllocatorObject : public Object protected: LOADERALLOCATORSCOUTREF m_pLoaderAllocatorScout; OBJECTREF m_pSlots; - ASSEMBLYBINDERREF m_binderToRelease; INT32 m_slotsUsed; OBJECTREF m_methodInstantiationsTable; }; From e8efdeafe3494036b8794297aa1353072922e67d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 5 Nov 2023 22:55:12 +0800 Subject: [PATCH 080/136] Fix IsNeutralCulture --- .../src/Internal/Runtime/Binder/AssemblyName.cs | 2 +- .../src/Internal/Runtime/Binder/TextualIdentityParser.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index 0f8b2fc42fcb48..e2bcc25533409c 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -199,7 +199,7 @@ public unsafe AssemblyName(AssemblyNameData* data) // TODO: Is this simple comparison enough? public bool IsCoreLib => string.EqualsOrdinalIgnoreCase(SimpleName, CoreLib.Name); - public bool IsNeutralCulture => string.EqualsOrdinalIgnoreCase(CultureOrLanguage, NeutralCulture); + public bool IsNeutralCulture => string.IsNullOrEmpty(CultureOrLanguage) || string.EqualsOrdinalIgnoreCase(CultureOrLanguage, NeutralCulture); public override int GetHashCode() => GetHashCode(AssemblyNameIncludeFlags.INCLUDE_ALL); diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs index f482b98a9623e5..2c1be6a1f086ca 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs @@ -73,7 +73,7 @@ public static string ToString(AssemblyIdentity pAssemblyIdentity, AssemblyIdenti textualIdentity.Append(", Retargetable=Yes"); } - if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) + if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CONTENT_TYPE) != 0) { textualIdentity.Append($", ContentType={nameof(System.Reflection.AssemblyContentType.WindowsRuntime)}"); } From 62995fb0cece67344dff65a2ca98de21924fc9cd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 22:29:24 +0800 Subject: [PATCH 081/136] Restore AssemblyBinder usage in AppDomain --- src/coreclr/vm/appdomain.cpp | 85 +++++++++++------------------------- src/coreclr/vm/appdomain.hpp | 12 ++--- 2 files changed, 32 insertions(+), 65 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 2212e5cfbca57a..70d884e421ce42 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -571,8 +571,8 @@ BaseDomain::BaseDomain() FORBID_FAULT; } CONTRACTL_END; - - m_pManagedDefaultBinder = NULL; + + m_pDefaultBinder = NULL; // Make sure the container is set to NULL so that it gets loaded when it is used. m_pPinnedHeapHandleTable = NULL; @@ -682,11 +682,11 @@ void BaseDomain::ClearBinderContext() MODE_PREEMPTIVE; } CONTRACTL_END; - - if (m_pManagedDefaultBinder != NULL) + + if (m_pDefaultBinder) { - DestroyHandle(m_pManagedDefaultBinder); - m_pManagedDefaultBinder = NULL; + delete m_pDefaultBinder; + m_pDefaultBinder = NULL; } } @@ -1803,7 +1803,7 @@ void AppDomain::Create() pDomain->InitThreadStaticBlockTypeMap(); pDomain->SetStage(AppDomain::STAGE_OPEN); - // pDomain->CreateDefaultBinder(); // Should be delayed after CoreLib loaded + pDomain->CreateDefaultBinder(); pDomain.SuppressRelease(); @@ -2688,18 +2688,16 @@ DomainAssembly* AppDomain::LoadDomainAssembly(AssemblySpec* pSpec, Exception* pEx = GET_EXCEPTION(); if (!pEx->IsTransient()) { - GCX_COOP(); - // Setup the binder reference in AssemblySpec from the PEAssembly if one is not already set. - ASSEMBLYBINDERREF pCurrentBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pSpec->GetBinder()); - ASSEMBLYBINDERREF pBinderFromPEAssembly = pPEAssembly->GetAssemblyBinder(); + AssemblyBinder* pCurrentBinder = pSpec->GetBinder(); + AssemblyBinder* pBinderFromPEAssembly = pPEAssembly->GetAssemblyBinder(); if (pCurrentBinder == NULL) { // Set the binding context we got from the PEAssembly if AssemblySpec does not // have that information _ASSERTE(pBinderFromPEAssembly != NULL); - pSpec->SetBinder(CreateHandle(pBinderFromPEAssembly)); + pSpec->SetBinder(pBinderFromPEAssembly); } #if defined(_DEBUG) else @@ -2757,37 +2755,15 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (result == NULL) { - LoaderAllocator *pLoaderAllocator = NULL; + AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); + // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if + // marked as collectible + pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator(); + if (pLoaderAllocator == NULL) { - if (!pPEAssembly->IsSystem()) - { - GCX_COOP(); - ASSEMBLYBINDERREF pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); - - // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if - // marked as collectible - - GCPROTECT_BEGIN(pAssemblyBinder); - MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR, &pAssemblyBinder); - ARG_SLOT args[1] = - { - ObjToArgSlot(pAssemblyBinder) - }; - - LOADERALLOCATORREF pManagedLA = (LOADERALLOCATORREF)methGetLoaderAllocator.Call_RetOBJECTREF(args); - if (pManagedLA != NULL) - { - pLoaderAllocator = pManagedLA->GetNativeLoaderAllocator(); - } - GCPROTECT_END(); - } - - if (pLoaderAllocator == NULL) - { - pLoaderAllocator = this->GetLoaderAllocator(); - } + pLoaderAllocator = this->GetLoaderAllocator(); } // Allocate the DomainAssembly a bit early to avoid GC mode problems. We could potentially avoid @@ -3611,11 +3587,11 @@ PEAssembly * AppDomain::BindAssemblySpec( // IsSystem on the PEAssembly should be false, even for CoreLib satellites result = PEAssembly::Open(boundAssembly); } - + // Setup the reference to the binder, which performed the bind, into the AssemblySpec - ASSEMBLYBINDERREF pBinder = result->GetAssemblyBinder(); + AssemblyBinder* pBinder = result->GetAssemblyBinder(); _ASSERTE(pBinder != NULL); - pSpec->SetBinder(CreateHandle(pBinder)); + pSpec->SetBinder(pBinder); // Failure to add simply means someone else beat us to it. In that case // the FindCachedFile call below (after catch block) will update result @@ -3945,9 +3921,9 @@ AppDomain::RaiseUnhandledExceptionEvent(OBJECTREF *pThrowable, BOOL isTerminatin } -OBJECTHANDLE AppDomain::CreateDefaultBinder() +DefaultAssemblyBinder *AppDomain::CreateDefaultBinder() { - CONTRACT(OBJECTHANDLE) + CONTRACT(DefaultAssemblyBinder *) { GC_TRIGGERS; THROWS; @@ -3957,26 +3933,17 @@ OBJECTHANDLE AppDomain::CreateDefaultBinder() } CONTRACT_END; - if (!m_pManagedDefaultBinder) + if (!m_pDefaultBinder) { ETWOnStartup (FusionAppCtx_V1, FusionAppCtxEnd_V1); - GCX_COOP(); - - OBJECTREF managedBinder = AllocateObject(CoreLibBinder::GetClass(CLASS__BINDER_DEFAULTASSEMBLYBINDER)); - - GCPROTECT_BEGIN(managedBinder); - - MethodDescCallSite ctor(METHOD__BINDER_DEFAULTASSEMBLYBINDER__CTOR); - ARG_SLOT arg = ObjToArgSlot(managedBinder); - ctor.Call(&arg); - - m_pManagedDefaultBinder = CreateHandle(managedBinder); + GCX_PREEMP(); - GCPROTECT_END(); + // Initialize the assembly binder for the default context loads for CoreCLR. + IfFailThrow(BINDER_SPACE::AssemblyBinderCommon::CreateDefaultBinder(&m_pDefaultBinder)); } - RETURN m_pManagedDefaultBinder; + RETURN m_pDefaultBinder; } diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index a0fcf7f3dfa3b8..892e23edb81cb7 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1073,8 +1073,8 @@ class BaseDomain } #endif // DACCESS_COMPILE - - OBJECTHANDLE GetDefaultBinder() { LIMITED_METHOD_CONTRACT; return m_pManagedDefaultBinder; } + + DefaultAssemblyBinder *GetDefaultBinder() {LIMITED_METHOD_CONTRACT; return m_pDefaultBinder; } CrstExplicitInit * GetLoaderAllocatorReferencesLock() { @@ -1122,8 +1122,8 @@ class BaseDomain JitListLock m_JITLock; ListLock m_ILStubGenLock; ListLock m_NativeTypeLoadLock; - - OBJECTHANDLE m_pManagedDefaultBinder; + + DefaultAssemblyBinder *m_pDefaultBinder; // Reference to the binding context that holds TPA list details IGCHandleStore* m_handleStore; @@ -1966,8 +1966,8 @@ class AppDomain : public BaseDomain public: RCWRefCache *GetRCWRefCache(); #endif // FEATURE_COMWRAPPERS - - OBJECTHANDLE CreateDefaultBinder(); + + DefaultAssemblyBinder *CreateDefaultBinder(); void SetIgnoreUnhandledExceptions() { From 26c8224a7f1966f8b43698913102d422018ae12c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 20:56:23 +0800 Subject: [PATCH 082/136] Restore native binder lifetime --- .../Loader/AssemblyLoadContext.CoreCLR.cs | 47 ++-------- src/coreclr/vm/assemblynative.cpp | 90 +++++++++++++++++++ src/coreclr/vm/assemblynative.hpp | 4 + src/coreclr/vm/qcallentrypoints.cpp | 2 + .../Runtime/Loader/AssemblyLoadContext.cs | 14 --- 5 files changed, 102 insertions(+), 55 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 2d6f0b495f1230..d6505c81e6d908 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Reflection; @@ -12,48 +11,14 @@ namespace System.Runtime.Loader { public partial class AssemblyLoadContext { - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] - internal static partial IntPtr GetDefaultAssemblyBinder(); - - private static Internal.Runtime.Binder.AssemblyBinder InitializeAssemblyLoadContext(GCHandle ptrAssemblyLoadContext, bool representsTPALoadContext, bool isCollectible) - { - // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and - // only one thread is ever executing a ctor for a given instance. - - // Initialize the assembly binder instance in the VM - GCHandle pDefaultBinder = GCHandle.FromIntPtr(GetDefaultAssemblyBinder()); - var defaultBinder = pDefaultBinder.Target as Internal.Runtime.Binder.DefaultAssemblyBinder; - Debug.Assert(defaultBinder != null); - if (!representsTPALoadContext) - { - // Initialize a custom assembly binder - - LoaderAllocator? loaderAllocator = null; - GCHandle loaderAllocatorHandle = default; - - if (isCollectible) - { - // Create a new AssemblyLoaderAllocator for an AssemblyLoadContext - } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_InitializeAssemblyLoadContext")] + private static partial IntPtr InitializeAssemblyLoadContext(IntPtr ptrAssemblyLoadContext, [MarshalAs(UnmanagedType.Bool)] bool fRepresentsTPALoadContext, [MarshalAs(UnmanagedType.Bool)] bool isCollectible); - return new Internal.Runtime.Binder.CustomAssemblyBinder(defaultBinder, loaderAllocator, loaderAllocatorHandle, ptrAssemblyLoadContext); - } - else - { - // We are initializing the managed instance of Assembly Load Context that would represent the TPA binder. - // First, confirm we do not have an existing managed ALC attached to the TPA binder. - Debug.Assert(!defaultBinder.ManagedAssemblyLoadContext.IsAllocated); - - // Attach the managed TPA binding context with the native one. - defaultBinder.ManagedAssemblyLoadContext = ptrAssemblyLoadContext; - return defaultBinder; - } - } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_PrepareForAssemblyLoadContextRelease")] + private static partial void PrepareForAssemblyLoadContextRelease(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyLoadContextStrong); - private static void PrepareForAssemblyLoadContextRelease(Internal.Runtime.Binder.AssemblyBinder ptrNativeAssemblyBinder, GCHandle ptrAssemblyLoadContextStrong) - { - ((Internal.Runtime.Binder.CustomAssemblyBinder)ptrNativeAssemblyBinder).PrepareForLoadContextRelease(ptrAssemblyLoadContextStrong); - } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] + internal static partial IntPtr GetDefaultAssemblyBinder(); [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromStream")] diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index eda867b8ba3737..91b4e4147559ca 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1213,6 +1213,96 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH END_QCALL; } +/*static*/ + +extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible) +{ + QCALL_CONTRACT; + + INT_PTR ptrNativeAssemblyBinder = NULL; + + BEGIN_QCALL; + + // We do not need to take a lock since this method is invoked from the ctor of AssemblyLoadContext managed type and + // only one thread is ever executing a ctor for a given instance. + // + + // Initialize the assembly binder instance in the VM + PTR_AppDomain pCurDomain = AppDomain::GetCurrentDomain(); + DefaultAssemblyBinder *pDefaultBinder = pCurDomain->GetDefaultBinder(); + if (!fRepresentsTPALoadContext) + { + // Initialize a custom assembly binder + CustomAssemblyBinder *pCustomBinder = NULL; + + AssemblyLoaderAllocator* loaderAllocator = NULL; + OBJECTHANDLE loaderAllocatorHandle = NULL; + + if (fIsCollectible) + { + // Create a new AssemblyLoaderAllocator for an AssemblyLoadContext + loaderAllocator = new AssemblyLoaderAllocator(); + + GCX_COOP(); + LOADERALLOCATORREF pManagedLoaderAllocator = NULL; + GCPROTECT_BEGIN(pManagedLoaderAllocator); + { + GCX_PREEMP(); + // Some of the initialization functions are not virtual. Call through the derived class + // to prevent calling the base class version. + loaderAllocator->Init(pCurDomain); + loaderAllocator->InitVirtualCallStubManager(pCurDomain); + + // Setup the managed proxy now, but do not actually transfer ownership to it. + // Once everything is setup and nothing can fail anymore, the ownership will be + // atomically transferred by call to LoaderAllocator::ActivateManagedTracking(). + loaderAllocator->SetupManagedTracking(&pManagedLoaderAllocator); + } + + // Create a strong handle to the LoaderAllocator + loaderAllocatorHandle = pCurDomain->CreateHandle(pManagedLoaderAllocator); + + GCPROTECT_END(); + + loaderAllocator->ActivateManagedTracking(); + } + + IfFailThrow(CustomAssemblyBinder::SetupContext(pDefaultBinder, loaderAllocator, loaderAllocatorHandle, ptrManagedAssemblyLoadContext, &pCustomBinder)); + ptrNativeAssemblyBinder = reinterpret_cast(pCustomBinder); + } + else + { + // We are initializing the managed instance of Assembly Load Context that would represent the TPA binder. + // First, confirm we do not have an existing managed ALC attached to the TPA binder. + _ASSERTE(pDefaultBinder->GetManagedAssemblyLoadContext() == NULL); + + // Attach the managed TPA binding context with the native one. + pDefaultBinder->SetManagedAssemblyLoadContext(ptrManagedAssemblyLoadContext); + ptrNativeAssemblyBinder = reinterpret_cast(pDefaultBinder); + } + + END_QCALL; + + return ptrNativeAssemblyBinder; +} + +/*static*/ +extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext) +{ + QCALL_CONTRACT; + + BOOL fDestroyed = FALSE; + + BEGIN_QCALL; + + + { + GCX_COOP(); + reinterpret_cast(ptrNativeAssemblyBinder)->PrepareForLoadContextRelease(ptrManagedStrongAssemblyLoadContext); + } + + END_QCALL; +} extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder() { diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 36f9b2ee3ea91d..a327c741d6996c 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -113,6 +113,10 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH extern "C" BOOL QCALLTYPE AssemblyNative_GetIsCollectible(QCall::AssemblyHandle pAssembly); +extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible); + +extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext); + extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder(); extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* pAssemblyName, QCall::ObjectHandleOnStack requestingAssembly, QCall::StackCrawlMarkHandle stackMark,BOOL fThrowOnFileNotFound, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index fabc77d3c6d19d..0af4b107d21fc7 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -177,6 +177,8 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_InternalTryGetRawMetadata) DllImportEntry(AssemblyNative_ApplyUpdate) DllImportEntry(AssemblyNative_IsApplyUpdateSupported) + DllImportEntry(AssemblyNative_InitializeAssemblyLoadContext) + DllImportEntry(AssemblyNative_PrepareForAssemblyLoadContextRelease) DllImportEntry(AssemblyNative_GetMDImport) DllImportEntry(AssemblyNative_GetSimpleNameNative) DllImportEntry(AssemblyNative_GetExposedObject) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 4fc00005956019..9c36b5933f52eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -40,16 +40,12 @@ private enum InternalState s_allContexts; #region private data members -#if CORECLR - private readonly Internal.Runtime.Binder.AssemblyBinder _assemblyBinder; -#else // If you modify this field, you must also update the // AssemblyLoadContextBaseObject structure in object.h // and MonoManagedAssemblyLoadContext in object-internals.h // Contains the reference to VM's representation of the AssemblyLoadContext private readonly IntPtr _nativeAssemblyLoadContext; -#endif #endregion // synchronization primitive to protect against usage of this instance while unloading @@ -104,13 +100,7 @@ private protected AssemblyLoadContext(bool representsTPALoadContext, bool isColl // If this is a collectible ALC, we are creating a weak handle tracking resurrection otherwise we use a strong handle var thisHandle = GCHandle.Alloc(this, IsCollectible ? GCHandleType.WeakTrackResurrection : GCHandleType.Normal); var thisHandlePtr = GCHandle.ToIntPtr(thisHandle); - -#if CORECLR - // AssemblyNative_InitializeAssemblyLoadContext - _assemblyBinder = InitializeAssemblyLoadContext(thisHandle, representsTPALoadContext, isCollectible); -#else _nativeAssemblyLoadContext = InitializeAssemblyLoadContext(thisHandlePtr, representsTPALoadContext, isCollectible); -#endif // Add this instance to the list of alive ALC Dictionary> allContexts = AllContexts; @@ -158,11 +148,7 @@ private void InitiateUnload() var thisStrongHandlePtr = GCHandle.ToIntPtr(thisStrongHandle); // The underlying code will transform the original weak handle // created by InitializeLoadContext to a strong handle -#if CORECLR - PrepareForAssemblyLoadContextRelease(_assemblyBinder, thisStrongHandle); -#else PrepareForAssemblyLoadContextRelease(_nativeAssemblyLoadContext, thisStrongHandlePtr); -#endif _state = InternalState.Unloading; } From 5e412b8a977afaa97d1bd18081e67819c81acd4d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 22:35:57 +0800 Subject: [PATCH 083/136] Restore AssemblyBinder usage in AssemblySpec --- src/coreclr/vm/assemblyspec.cpp | 89 ++++++++++------------------- src/coreclr/vm/assemblyspec.hpp | 10 ++-- src/coreclr/vm/baseassemblyspec.h | 6 +- src/coreclr/vm/baseassemblyspec.inl | 18 +----- 4 files changed, 39 insertions(+), 84 deletions(-) diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 19a468252e5ed7..416f0491365d74 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -205,15 +205,13 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) InitializeSpec(a, pImport, NULL); // Set the binding context for the AssemblySpec - OBJECTHANDLE pCurrentBinder = GetBinder(); + AssemblyBinder* pCurrentBinder = GetBinder(); if (pCurrentBinder == NULL) { - // unblock CoreLib bootstrap - - //ASSEMBLYBINDERREF pExpectedBinder = pFile->GetAssemblyBinder(); - //// We should always have the binding context in the PEAssembly. - //_ASSERTE(pExpectedBinder != NULL); - //SetBinder(GetAppDomain()->CreateHandle(pExpectedBinder)); + AssemblyBinder* pExpectedBinder = pFile->GetAssemblyBinder(); + // We should always have the binding context in the PEAssembly. + _ASSERTE(pExpectedBinder != NULL); + SetBinder(pExpectedBinder); } } @@ -367,18 +365,18 @@ Assembly *AssemblySpec::LoadAssembly(FileLoadLevel targetLevel, BOOL fThrowOnFil return pDomainAssembly->GetAssembly(); } -ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) +AssemblyBinder* AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) { CONTRACTL { NOTHROW; GC_NOTRIGGER; - MODE_COOPERATIVE; + MODE_ANY; PRECONDITION(pDomain != NULL); } CONTRACTL_END; - ASSEMBLYBINDERREF pParentAssemblyBinder = NULL; + AssemblyBinder *pParentAssemblyBinder = NULL; DomainAssembly *pParentDomainAssembly = GetParentAssembly(); if(pParentDomainAssembly != NULL) @@ -410,7 +408,7 @@ ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) // // For (3), fetch the fallback load context binder reference. - pParentAssemblyBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(GetFallbackBinderForRequestingAssembly()); + pParentAssemblyBinder = GetFallbackBinderForRequestingAssembly(); } if (!pParentAssemblyBinder) @@ -420,7 +418,7 @@ ASSEMBLYBINDERREF AssemblySpec::GetBinderFromParentAssembly(AppDomain *pDomain) // // In such a case, the parent assembly (semantically) is CoreLibrary and thus, the default binding context should be // used as the parent assembly binder. - pParentAssemblyBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pDomain->GetDefaultBinder()); + pParentAssemblyBinder = static_cast(pDomain->GetDefaultBinder()); } return pParentAssemblyBinder; @@ -513,10 +511,7 @@ Assembly *AssemblySpec::LoadAssembly(LPCWSTR pFilePath) if (!pILImage->CheckILFormat()) THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue()); - { - GCX_COOP(); - RETURN AssemblyNative::LoadFromPEImage((ASSEMBLYBINDERREF)ObjectFromHandle(AppDomain::GetCurrentDomain()->GetDefaultBinder()), pILImage, true /* excludeAppPaths */); - } + RETURN AssemblyNative::LoadFromPEImage(AppDomain::GetCurrentDomain()->GetDefaultBinder(), pILImage, true /* excludeAppPaths */); } HRESULT AssemblySpec::CheckFriendAssemblyName() @@ -692,18 +687,14 @@ AssemblySpecBindingCache::AssemblyBinding* AssemblySpecBindingCache::LookupInter } CONTRACTL_END; - GCX_COOP(); - UPTR key = (UPTR)pSpec->Hash(); - ASSEMBLYBINDERREF pBinderForLookup = NULL; + AssemblyBinder *pBinderForLookup = NULL; bool fGetBindingContextFromParent = true; // Check if the AssemblySpec already has specified its binding context. This will be set for assemblies that are // attempted to be explicitly bound using AssemblyLoadContext LoadFrom* methods. - OBJECTHANDLE pBinderHandle = pSpec->GetBinder(); - if (pBinderHandle != NULL) - pBinderForLookup = ObjectFromHandle(pSpec->GetBinder()); + pBinderForLookup = pSpec->GetBinder(); if (pBinderForLookup != NULL) { @@ -715,12 +706,12 @@ AssemblySpecBindingCache::AssemblyBinding* AssemblySpecBindingCache::LookupInter if (fGetBindingContextFromParent) { pBinderForLookup = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); - pSpec->SetBinder(GetAppDomain()->CreateHandle(pBinderForLookup)); + pSpec->SetBinder(pBinderForLookup); } - if (pBinderForLookup != NULL) + if (pBinderForLookup) { - key = key ^ (UPTR)(pBinderForLookup->GetHeader()->GetBits() | MASK_HASHCODE); + key = key ^ (UPTR)pBinderForLookup; } AssemblyBinding* pEntry = (AssemblyBinding *)m_map.LookupValue(key, pSpec); @@ -929,17 +920,12 @@ BOOL AssemblySpecBindingCache::StoreAssembly(AssemblySpec *pSpec, DomainAssembly UPTR key = (UPTR)pSpec->Hash(); - { - GCX_COOP(); - - ASSEMBLYBINDERREF pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + AssemblyBinder* pBinderContextForLookup = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + key = key ^ (UPTR)pBinderContextForLookup; - key = key ^ (UPTR)(pBinderContextForLookup->GetHeader()->GetBits() | MASK_HASHCODE); - - if (!pSpec->GetBinder()) - { - pSpec->SetBinder(GetAppDomain()->CreateHandle(pBinderContextForLookup)); - } + if (!pSpec->GetBinder()) + { + pSpec->SetBinder(pBinderContextForLookup); } AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); @@ -1008,20 +994,14 @@ BOOL AssemblySpecBindingCache::StorePEAssembly(AssemblySpec *pSpec, PEAssembly * } CONTRACT_END; - GCX_COOP(); - UPTR key = (UPTR)pSpec->Hash(); - ASSEMBLYBINDERREF pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); - - if (pBinderContextForLookup != NULL) - { - key = key ^ (UPTR)(pBinderContextForLookup->GetHeader()->GetBits() | MASK_HASHCODE); - } + AssemblyBinder* pBinderContextForLookup = pPEAssembly->GetAssemblyBinder(); + key = key ^ (UPTR)pBinderContextForLookup; if (!pSpec->GetBinder()) { - pSpec->SetBinder(GetAppDomain()->CreateHandle(pBinderContextForLookup)); + pSpec->SetBinder(pBinderContextForLookup); } AssemblyBinding *entry = (AssemblyBinding *) m_map.LookupValue(key, pSpec); @@ -1034,20 +1014,14 @@ BOOL AssemblySpecBindingCache::StorePEAssembly(AssemblySpec *pSpec, PEAssembly * if (pBinderContextForLookup != NULL) { - GCPROTECT_BEGIN(pBinderContextForLookup); + LoaderAllocator* pLoaderAllocator = pBinderContextForLookup->GetLoaderAllocator(); - MethodDescCallSite getLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR, &pBinderContextForLookup); - ARG_SLOT arg = ObjToArgSlot(pBinderContextForLookup); - LOADERALLOCATORREF pLoaderAllocator = (LOADERALLOCATORREF)getLoaderAllocator.Call_RetOBJECTREF(&arg); - // Assemblies loaded with AssemblyLoadContext need to use a different heap if // marked as collectible - if (pLoaderAllocator != NULL) + if (pLoaderAllocator) { - pHeap = pLoaderAllocator->GetNativeLoaderAllocator()->GetHighFrequencyHeap(); + pHeap = pLoaderAllocator->GetHighFrequencyHeap(); } - - GCPROTECT_END(); } entry = abHolder.CreateAssemblyBinding(pHeap); @@ -1105,15 +1079,12 @@ BOOL AssemblySpecBindingCache::StoreException(AssemblySpec *pSpec, Exception* pE // // Since no entry was found for this assembly in any binding context, save the failure // in the DefaultBinder context - GCX_COOP(); - - ASSEMBLYBINDERREF pBinderToSaveException = NULL; - pBinderToSaveException = ObjectFromHandle(pSpec->GetBinder()); + AssemblyBinder* pBinderToSaveException = NULL; + pBinderToSaveException = pSpec->GetBinder(); if (pBinderToSaveException == NULL) { pBinderToSaveException = pSpec->GetBinderFromParentAssembly(pSpec->GetAppDomain()); - - key = key ^ (UPTR)(pBinderToSaveException->GetHeader()->GetBits() | MASK_HASHCODE); + key = key ^ (UPTR)pBinderToSaveException; } } diff --git a/src/coreclr/vm/assemblyspec.hpp b/src/coreclr/vm/assemblyspec.hpp index 6079b403eee080..3ff13181731258 100644 --- a/src/coreclr/vm/assemblyspec.hpp +++ b/src/coreclr/vm/assemblyspec.hpp @@ -31,7 +31,7 @@ class AssemblySpec : public BaseAssemblySpec DomainAssembly *m_pParentAssembly; // Contains the reference to the fallback load context associated with RefEmitted assembly requesting the load of another assembly (static or dynamic) - OBJECTHANDLE m_pFallbackBinder; + AssemblyBinder *m_pFallbackBinder; // Flag to indicate if we should prefer the fallback load context binder for binding or not. bool m_fPreferFallbackBinder; @@ -46,7 +46,7 @@ class AssemblySpec : public BaseAssemblySpec mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride, BOOL fDoNotUtilizeExtraChecks, - OBJECTHANDLE pBinderForLoadedAssembly); + AssemblyBinder *pBinderForLoadedAssembly); public: @@ -75,7 +75,7 @@ class AssemblySpec : public BaseAssemblySpec DomainAssembly* GetParentAssembly(); - ASSEMBLYBINDERREF GetBinderFromParentAssembly(AppDomain *pDomain); + AssemblyBinder* GetBinderFromParentAssembly(AppDomain *pDomain); bool HasParentAssembly() { WRAPPER_NO_CONTRACT; return GetParentAssembly() != NULL; } @@ -116,14 +116,14 @@ class AssemblySpec : public BaseAssemblySpec m_pParentAssembly = pAssembly; } - void SetFallbackBinderForRequestingAssembly(OBJECTHANDLE pFallbackBinder) + void SetFallbackBinderForRequestingAssembly(AssemblyBinder *pFallbackBinder) { LIMITED_METHOD_CONTRACT; m_pFallbackBinder = pFallbackBinder; } - OBJECTHANDLE GetFallbackBinderForRequestingAssembly() + AssemblyBinder* GetFallbackBinderForRequestingAssembly() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/baseassemblyspec.h b/src/coreclr/vm/baseassemblyspec.h index d216d97eeeb493..77180a3db980e8 100644 --- a/src/coreclr/vm/baseassemblyspec.h +++ b/src/coreclr/vm/baseassemblyspec.h @@ -26,7 +26,7 @@ class BaseAssemblySpec DWORD m_cbPublicKeyOrToken; DWORD m_dwFlags; // CorAssemblyFlags int m_ownedFlags; - OBJECTHANDLE m_pBinder; + AssemblyBinder *m_pBinder; public: enum @@ -60,14 +60,14 @@ class BaseAssemblySpec VOID CloneFields(); VOID CloneFieldsToLoaderHeap(LoaderHeap *pHeap, AllocMemTracker *pamTracker); - inline void SetBinder(OBJECTHANDLE pBinder) + inline void SetBinder(AssemblyBinder *pBinder) { LIMITED_METHOD_CONTRACT; m_pBinder = pBinder; } - inline OBJECTHANDLE GetBinder() + inline AssemblyBinder* GetBinder() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/baseassemblyspec.inl b/src/coreclr/vm/baseassemblyspec.inl index 07a505aa3c87b2..125e31a592a9ea 100644 --- a/src/coreclr/vm/baseassemblyspec.inl +++ b/src/coreclr/vm/baseassemblyspec.inl @@ -14,11 +14,6 @@ #ifndef __BASE_ASSEMBLY_SPEC_INL__ #define __BASE_ASSEMBLY_SPEC_INL__ -#include -#include -#include -#include - inline int BaseAssemblySpec::CompareStrings(LPCUTF8 string1, LPCUTF8 string2) { WRAPPER_NO_CONTRACT; @@ -284,18 +279,7 @@ inline BOOL BaseAssemblySpec::CompareEx(BaseAssemblySpec *pSpec, DWORD dwCompare // If the assemblySpec contains the binding context, then check if they match. if (pSpec->m_pBinder != m_pBinder) { - if (pSpec->m_pBinder != NULL && m_pBinder != NULL) - { - GCX_COOP(); - if (ObjectFromHandle(pSpec->m_pBinder) != ObjectFromHandle(m_pBinder)) - { - return FALSE; - } - } - else - { - return FALSE; - } + return FALSE; } return TRUE; From 1bdcf2f7f4c02bf6991bf2da6ff5605421c3a89a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 22:55:57 +0800 Subject: [PATCH 084/136] Restore AssemblyBinder usage in PEAssembly --- src/coreclr/vm/peassembly.cpp | 23 ++++++----------------- src/coreclr/vm/peassembly.h | 8 ++++---- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 86784323900635..b067f3b114197b 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -804,12 +804,6 @@ PEAssembly::~PEAssembly() DestroyHandle(m_pHostAssembly); m_pHostAssembly = NULL; } - - if (m_pFallbackBinder != NULL) - { - DestroyHandle(m_pFallbackBinder); - m_pFallbackBinder = NULL; - } } /* static */ @@ -1113,22 +1107,17 @@ TADDR PEAssembly::GetMDInternalRWAddress() #endif // Returns the AssemblyBinder* instance associated with the PEAssembly -ASSEMBLYBINDERREF PEAssembly::GetAssemblyBinder() +PTR_AssemblyBinder PEAssembly::GetAssemblyBinder() { - CONTRACTL - { - GC_NOTRIGGER; - NOTHROW; - MODE_COOPERATIVE; - } - CONTRACTL_END + LIMITED_METHOD_CONTRACT; - ASSEMBLYBINDERREF pBinder = NULL; + PTR_AssemblyBinder pBinder = NULL; OBJECTHANDLE pHostAssembly = GetHostAssembly(); if (pHostAssembly) { - pBinder = (ASSEMBLYBINDERREF)((BINDERASSEMBLYREF)ObjectFromHandle(pHostAssembly))->m_binder; + GCX_COOP(); + pBinder = ((BINDERASSEMBLYREF)ObjectFromHandle(pHostAssembly))->GetBinder(); } else { @@ -1137,7 +1126,7 @@ ASSEMBLYBINDERREF PEAssembly::GetAssemblyBinder() // binder reference. if (IsDynamic()) { - pBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(GetFallbackBinder()); + pBinder = GetFallbackBinder(); } } diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index 4c1e5a34cafd7d..aa0b208821d840 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -317,10 +317,10 @@ class PEAssembly final // Returns the AssemblyBinder* instance associated with the PEAssembly // which owns the context into which the current PEAssembly was loaded. // For Dynamic assemblies this is the fallback binder. - ASSEMBLYBINDERREF GetAssemblyBinder(); + PTR_AssemblyBinder GetAssemblyBinder(); #ifndef DACCESS_COMPILE - void SetFallbackBinder(OBJECTHANDLE pFallbackBinder) + void SetFallbackBinder(PTR_AssemblyBinder pFallbackBinder) { LIMITED_METHOD_CONTRACT; m_pFallbackBinder = pFallbackBinder; @@ -330,7 +330,7 @@ class PEAssembly final ULONG HashIdentity(); - OBJECTHANDLE GetFallbackBinder() + PTR_AssemblyBinder GetFallbackBinder() { LIMITED_METHOD_CONTRACT; @@ -443,7 +443,7 @@ class PEAssembly final // To enable this, we maintain a concept of "FallbackBinder", which will be set to the Binder of the // assembly that created the dynamic assembly. If the creator assembly is dynamic itself, then its fallback // load context would be propagated to the assembly being dynamically generated. - OBJECTHANDLE m_pFallbackBinder; + PTR_AssemblyBinder m_pFallbackBinder; }; // class PEAssembly From 7c233c6a161a7f8c1e498b6d8453e767686b471e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 23:03:03 +0800 Subject: [PATCH 085/136] Restore some more binder usage --- src/coreclr/debug/daccess/request.cpp | 4 ++-- src/coreclr/vm/nativeimage.cpp | 8 +++----- src/coreclr/vm/nativeimage.h | 8 ++++---- src/coreclr/vm/nativelibrary.cpp | 19 ++++++++----------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index fe126a4427ab93..d9e0b1807c6bf7 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -4926,9 +4926,9 @@ HRESULT ClrDataAccess::GetAssemblyLoadContext(CLRDATA_ADDRESS methodTable, CLRDA PTR_Module pModule = pMT->GetModule(); PTR_PEAssembly pPEAssembly = pModule->GetPEAssembly(); - ASSEMBLYBINDERREF pBinder = pPEAssembly->GetAssemblyBinder(); + PTR_AssemblyBinder pBinder = pPEAssembly->GetAssemblyBinder(); - INT_PTR managedAssemblyLoadContextHandle = pBinder->m_managedALC; + INT_PTR managedAssemblyLoadContextHandle = pBinder->GetManagedAssemblyLoadContext(); TADDR managedAssemblyLoadContextAddr = 0; if (managedAssemblyLoadContextHandle != 0) diff --git a/src/coreclr/vm/nativeimage.cpp b/src/coreclr/vm/nativeimage.cpp index 009dea6670c2af..49f797f8962544 100644 --- a/src/coreclr/vm/nativeimage.cpp +++ b/src/coreclr/vm/nativeimage.cpp @@ -41,7 +41,7 @@ NativeImageIndexTraits::count_t NativeImageIndexTraits::Hash(LPCUTF8 a) return SString(SString::Utf8Literal, a).HashCaseInsensitive(); } -NativeImage::NativeImage(OBJECTHANDLE pAssemblyBinder, PEImageLayout *pImageLayout, LPCUTF8 imageFileName) +NativeImage::NativeImage(AssemblyBinder *pAssemblyBinder, PEImageLayout *pImageLayout, LPCUTF8 imageFileName) : m_eagerFixupsLock(CrstNativeImageEagerFixups) { CONTRACTL @@ -111,7 +111,7 @@ NativeImage::~NativeImage() NativeImage *NativeImage::Open( Module *componentModule, LPCUTF8 nativeImageFileName, - OBJECTHANDLE pAssemblyBinder, + AssemblyBinder *pAssemblyBinder, LoaderAllocator *pLoaderAllocator, /* out */ bool *isNewNativeImage) { @@ -120,10 +120,8 @@ NativeImage *NativeImage::Open( NativeImage *pExistingImage = AppDomain::GetCurrentDomain()->GetNativeImage(nativeImageFileName); if (pExistingImage != nullptr) { - GCX_COOP(); - *isNewNativeImage = false; - if (ObjectFromHandle(pExistingImage->GetAssemblyBinder()) == ObjectFromHandle(pAssemblyBinder)) + if (pExistingImage->GetAssemblyBinder() == pAssemblyBinder) { return pExistingImage; } diff --git a/src/coreclr/vm/nativeimage.h b/src/coreclr/vm/nativeimage.h index dd4411c6d59c08..afbc1e32cd0acb 100644 --- a/src/coreclr/vm/nativeimage.h +++ b/src/coreclr/vm/nativeimage.h @@ -80,7 +80,7 @@ class NativeImage // Points to the OwnerCompositeExecutable section content within the component MSIL module LPCUTF8 m_fileName; - OBJECTHANDLE m_pAssemblyBinder; + AssemblyBinder *m_pAssemblyBinder; ReadyToRunInfo *m_pReadyToRunInfo; IMDInternalImport *m_pManifestMetadata; PEImageLayout *m_pImageLayout; @@ -97,7 +97,7 @@ class NativeImage bool m_readyToRunCodeDisabled; private: - NativeImage(OBJECTHANDLE pAssemblyBinder, PEImageLayout *peImageLayout, LPCUTF8 imageFileName); + NativeImage(AssemblyBinder *pAssemblyBinder, PEImageLayout *peImageLayout, LPCUTF8 imageFileName); protected: void Initialize(READYTORUN_HEADER *header, LoaderAllocator *loaderAllocator, AllocMemTracker *pamTracker); @@ -108,7 +108,7 @@ class NativeImage static NativeImage *Open( Module *componentModule, LPCUTF8 nativeImageFileName, - OBJECTHANDLE pAssemblyBinder, + AssemblyBinder *pAssemblyBinder, LoaderAllocator *pLoaderAllocator, /* out */ bool *isNewNativeImage); @@ -122,7 +122,7 @@ class NativeImage IMDInternalImport *GetManifestMetadata() const { return m_pManifestMetadata; } uint32_t GetManifestAssemblyCount() const { return m_manifestAssemblyCount; } PTR_Assembly *GetManifestMetadataAssemblyRefMap() { return m_pNativeMetadataAssemblyRefMap; } - OBJECTHANDLE GetAssemblyBinder() const { return m_pAssemblyBinder; } + AssemblyBinder *GetAssemblyBinder() const { return m_pAssemblyBinder; } Assembly *LoadManifestAssembly(uint32_t rowid, DomainAssembly *pParentAssembly); diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp index 73ff9252008279..c4460d91a5c01d 100644 --- a/src/coreclr/vm/nativelibrary.cpp +++ b/src/coreclr/vm/nativelibrary.cpp @@ -331,18 +331,15 @@ namespace } #endif // !TARGET_UNIX - GCX_COOP(); - NATIVE_LIBRARY_HANDLE hmod = NULL; PEAssembly *pManifestFile = pAssembly->GetPEAssembly(); - ASSEMBLYBINDERREF pBinder = pManifestFile->GetAssemblyBinder(); + PTR_AssemblyBinder pBinder = pManifestFile->GetAssemblyBinder(); //Step 0: Check if the assembly was bound using TPA. - ASSEMBLYBINDERREF pCurrentBinder = pBinder; + AssemblyBinder *pCurrentBinder = pBinder; // For assemblies bound via default binder, we should use the standard mechanism to make the pinvoke call. - // Binder can be null during CoreLib bootstrap. - if (pCurrentBinder == NULL || pCurrentBinder->m_isDefault) + if (pCurrentBinder->IsDefault()) { return NULL; } @@ -351,13 +348,15 @@ namespace // Call System.Runtime.Loader.AssemblyLoadContext.ResolveUnmanagedDll to give // The custom assembly context a chance to load the unmanaged dll. + GCX_COOP(); + STRINGREF pUnmanagedDllName; pUnmanagedDllName = StringObject::NewString(wszLibName); GCPROTECT_BEGIN(pUnmanagedDllName); // Get the pointer to the managed assembly load context - INT_PTR ptrManagedAssemblyLoadContext = pCurrentBinder->m_managedALC; + INT_PTR ptrManagedAssemblyLoadContext = pCurrentBinder->GetManagedAssemblyLoadContext(); // Prepare to invoke System.Runtime.Loader.AssemblyLoadContext.ResolveUnmanagedDll method. PREPARE_NONVIRTUAL_CALLSITE(METHOD__ASSEMBLYLOADCONTEXT__RESOLVEUNMANAGEDDLL); @@ -378,10 +377,8 @@ namespace { STANDARD_VM_CONTRACT; - GCX_COOP(); - - ASSEMBLYBINDERREF pBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); - return pBinder->m_managedALC; + PTR_AssemblyBinder pBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + return pBinder->GetManagedAssemblyLoadContext(); } NATIVE_LIBRARY_HANDLE LoadNativeLibraryViaAssemblyLoadContextEvent(Assembly * pAssembly, PCWSTR wszLibName) From e5dbd2e37ccbe63e8eff11e9c8d101427e912209 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 17:56:41 +0800 Subject: [PATCH 086/136] Delete unused HashIdentity --- src/coreclr/vm/assembly.hpp | 5 ----- src/coreclr/vm/domainassembly.h | 6 ------ src/coreclr/vm/peassembly.h | 2 -- src/coreclr/vm/peassembly.inl | 19 ------------------- 4 files changed, 32 deletions(-) diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index d104b552e67b35..99cde07902ae47 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -250,11 +250,6 @@ class Assembly m_debuggerFlags = flags; } - ULONG HashIdentity() - { - return GetPEAssembly()->HashIdentity(); - } - // On failure: // if loadFlag == Loader::Load => throw // if loadFlag != Loader::Load => return NULL diff --git a/src/coreclr/vm/domainassembly.h b/src/coreclr/vm/domainassembly.h index f9e4d610677670..e041cc42563452 100644 --- a/src/coreclr/vm/domainassembly.h +++ b/src/coreclr/vm/domainassembly.h @@ -161,12 +161,6 @@ class DomainAssembly final return m_fCollectible; } - ULONG HashIdentity() - { - WRAPPER_NO_CONTRACT; - return GetPEAssembly()->HashIdentity(); - } - // ------------------------------------------------------------ // Loading state checks // ------------------------------------------------------------ diff --git a/src/coreclr/vm/peassembly.h b/src/coreclr/vm/peassembly.h index aa0b208821d840..3a40ecf2f52ee3 100644 --- a/src/coreclr/vm/peassembly.h +++ b/src/coreclr/vm/peassembly.h @@ -328,8 +328,6 @@ class PEAssembly final #endif //!DACCESS_COMPILE - ULONG HashIdentity(); - PTR_AssemblyBinder GetFallbackBinder() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/peassembly.inl b/src/coreclr/vm/peassembly.inl index ce03546b3e17b1..3a805bea6300e3 100644 --- a/src/coreclr/vm/peassembly.inl +++ b/src/coreclr/vm/peassembly.inl @@ -78,25 +78,6 @@ inline ULONG PEAssembly::Release() RETURN result; } -// ------------------------------------------------------------ -// Identity -// ------------------------------------------------------------ - -inline ULONG PEAssembly::HashIdentity() -{ - CONTRACTL - { - PRECONDITION(CheckPointer(m_PEImage)); - MODE_ANY; - THROWS; - GC_TRIGGERS; - } - CONTRACTL_END; - //return m_pHostAssembly->GetAssemblyName()->Hash(BINDER_SPACE::AssemblyName::INCLUDE_VERSION); - // TODO: call managed implementation in some way - return 83079; -} - inline void PEAssembly::ValidateForExecution() { CONTRACTL From 2d7acada4368850023896a5dd03c47e9c30416c3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 8 Nov 2023 22:40:21 +0800 Subject: [PATCH 087/136] Typo --- .../src/Internal/Runtime/Binder/AssemblyBinderCommon.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs index e1a27535d40772..cc65fa0bb39c0d 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs @@ -901,7 +901,7 @@ public static int RegisterAndGetHostChosen(ApplicationContext applicationContext // Only perform costly validation if other binds succeeded before us if (kContextVersion != applicationContext.Version) { - hr = OtherBindInterferred(applicationContext, bindResult); + hr = OtherBindInterfered(applicationContext, bindResult); if (hr < 0) return hr; if (hr == HResults.S_FALSE) @@ -925,7 +925,7 @@ public static int RegisterAndGetHostChosen(ApplicationContext applicationContext return hr; } - private static int OtherBindInterferred(ApplicationContext applicationContext, BindResult bindResult) + private static int OtherBindInterfered(ApplicationContext applicationContext, BindResult bindResult) { Debug.Assert(bindResult.Assembly != null); Debug.Assert(bindResult.Assembly.AssemblyName != null); From f5376c1a42a72c60effc2431ea173cc657578867 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 00:54:20 +0800 Subject: [PATCH 088/136] Update CoreLib bootstrap to use PEImage --- src/coreclr/binder/assemblybindercommon.cpp | 22 +++++++------------ .../binder/inc/assemblybindercommon.hpp | 2 +- src/coreclr/vm/peassembly.cpp | 8 ++++--- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 55f9a0ae533614..83ed302f6b3104 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -251,13 +251,13 @@ namespace BINDER_SPACE /* static */ HRESULT AssemblyBinderCommon::BindToSystem(SString &systemDirectory, - Assembly **ppSystemAssembly) + PEImage **ppPEImage) { HRESULT hr = S_OK; - _ASSERTE(ppSystemAssembly != NULL); + _ASSERTE(ppPEImage != NULL); - ReleaseHolder pSystemAssembly; + ReleaseHolder pSystemAssembly; // System.Private.CoreLib.dll is expected to be found at one of the following locations: // * Non-single-file app: In systemDirectory, beside coreclr.dll @@ -279,14 +279,11 @@ namespace BINDER_SPACE sCoreLib.Set(systemDirectory); CombinePath(sCoreLib, sCoreLibName, sCoreLib); - hr = AssemblyBinderCommon::GetAssembly(sCoreLib, - TRUE /* fIsInTPA */, - &pSystemAssembly, - bundleFileLocation); + hr = BinderAcquirePEImage(sCoreLib.GetUnicode(), &pSystemAssembly, bundleFileLocation); BinderTracing::PathProbed(sCoreLib, pathSource, hr); - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + if ((FAILED(hr)) && IsFileNotFound(hr)) { // Try to find corelib in the TPA StackSString sCoreLibSimpleName(CoreLibName_W); @@ -318,18 +315,15 @@ namespace BINDER_SPACE { GO_WITH_HRESULT(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); } - - hr = AssemblyBinderCommon::GetAssembly(sCoreLib, - TRUE /* fIsInTPA */, - &pSystemAssembly, - bundleFileLocation); + + hr = BinderAcquirePEImage(sCoreLib.GetUnicode(), &pSystemAssembly, bundleFileLocation); BinderTracing::PathProbed(sCoreLib, BinderTracing::PathSource::ApplicationAssemblies, hr); } IF_FAIL_GO(hr); - *ppSystemAssembly = pSystemAssembly.Extract(); + *ppPEImage = pSystemAssembly.Extract(); Exit: return hr; diff --git a/src/coreclr/binder/inc/assemblybindercommon.hpp b/src/coreclr/binder/inc/assemblybindercommon.hpp index cdc091b9802441..70fea4fdb4789d 100644 --- a/src/coreclr/binder/inc/assemblybindercommon.hpp +++ b/src/coreclr/binder/inc/assemblybindercommon.hpp @@ -34,7 +34,7 @@ namespace BINDER_SPACE /* out */ Assembly **ppAssembly); static HRESULT BindToSystem(/* in */ SString &systemDirectory, - /* out */ Assembly **ppSystemAssembly); + /* out */ PEImage **ppPEImage); static HRESULT BindToSystemSatellite(/* in */ SString &systemDirectory, /* in */ SString &simpleName, diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index b067f3b114197b..d60f5a7c96b2f2 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -842,14 +842,16 @@ PEAssembly *PEAssembly::DoOpenSystem() CONTRACT_END; ETWOnStartup (FusionBinding_V1, FusionBindingEnd_V1); - ReleaseHolder pBoundAssembly; - IfFailThrow(((DefaultAssemblyBinder*)NULL)->BindToSystem(&pBoundAssembly)); + ReleaseHolder pBoundAssembly; + + StackSString systemPath(SystemDomain::System()->SystemDirectory()); + IfFailThrow(BINDER_SPACE::AssemblyBinderCommon::BindToSystem(systemPath, &pBoundAssembly)); { GCX_COOP(); // HostAssembly is set afterwards for CoreLib - RETURN new PEAssembly(NULL, NULL, TRUE, pBoundAssembly->GetPEImage()); + RETURN new PEAssembly(NULL, NULL, TRUE, pBoundAssembly); } } From f0ebbcf9a376760ca95664d1368bebafea500963 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 23:19:49 +0800 Subject: [PATCH 089/136] Restore native binder in native ALC object --- src/coreclr/vm/object.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 744c0352b91fd1..f47a8ef2902b69 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1469,6 +1469,11 @@ class BinderAssemblyObject : public Object DomainAssembly* m_pDomainAssembly; CLR_BOOL m_isInTPA; CLR_BOOL m_isCoreLib; + + PTR_AssemblyBinder GetBinder() + { + return (PTR_AssemblyBinder)((ASSEMBLYLOADCONTEXTREF)m_binder)->GetNativeAssemblyBinder(); + } }; // AssemblyLoadContextBaseObject @@ -1486,23 +1491,23 @@ class AssemblyLoadContextBaseObject : public Object // Modifying the order or fields of this object may require other changes to the // classlib class definition of this object. #ifdef TARGET_64BIT - OBJECTREF _assemblyBinder; OBJECTREF _unloadLock; OBJECTREF _resolvingUnmanagedDll; OBJECTREF _resolving; OBJECTREF _unloading; OBJECTREF _name; + INT_PTR _nativeAssemblyLoadContext; int64_t _id; // On 64-bit platforms this is a value type so it is placed after references and pointers DWORD _state; CLR_BOOL _isCollectible; #else // TARGET_64BIT int64_t _id; // On 32-bit platforms this 64-bit value type is larger than a pointer so JIT places it first - OBJECTREF _assemblyBinder; OBJECTREF _unloadLock; OBJECTREF _resolvingUnmanagedDll; OBJECTREF _resolving; OBJECTREF _unloading; OBJECTREF _name; + INT_PTR _nativeAssemblyLoadContext; DWORD _state; CLR_BOOL _isCollectible; #endif // TARGET_64BIT @@ -1512,7 +1517,7 @@ class AssemblyLoadContextBaseObject : public Object ~AssemblyLoadContextBaseObject() { LIMITED_METHOD_CONTRACT; } public: - OBJECTREF GetNativeAssemblyBinder() { LIMITED_METHOD_CONTRACT; return _assemblyBinder; } + INT_PTR GetNativeAssemblyBinder() { LIMITED_METHOD_CONTRACT; return _nativeAssemblyLoadContext; } }; #if defined(TARGET_X86) && !defined(TARGET_UNIX) #include "poppack.h" From 68a69187e3a0b8224084e27bdb7af8182996f6fb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 23:33:22 +0800 Subject: [PATCH 090/136] Get managed ALC object from native binder --- src/coreclr/vm/appdomain.cpp | 4 ++-- src/coreclr/vm/assemblybinder.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 70d884e421ce42..708824e2bb4f14 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1162,7 +1162,7 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); - ASSEMBLYBINDERREF defaultBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(GetAppDomain()->CreateDefaultBinder()); + ASSEMBLYLOADCONTEXTREF defaultBinder = (ASSEMBLYLOADCONTEXTREF)GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContextObject(); { // AdHoc setup for corelib PEAssembly @@ -2821,7 +2821,7 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, MethodDescCallSite methAddLoadedAssem(METHOD__BINDER_ASSEMBLYBINDER__ADDLOADEDASSEMBLY); ARG_SLOT args[2] = { - ObjToArgSlot(pPEAssembly->GetAssemblyBinder()), + ObjToArgSlot(pPEAssembly->GetAssemblyBinder()->GetManagedAssemblyLoadContextObject()), PtrToArgSlot(pDomainAssembly->GetAssembly()) }; methAddLoadedAssem.Call(args); diff --git a/src/coreclr/vm/assemblybinder.h b/src/coreclr/vm/assemblybinder.h index 8fa57302cfa401..d273b6bc4e63f2 100644 --- a/src/coreclr/vm/assemblybinder.h +++ b/src/coreclr/vm/assemblybinder.h @@ -47,6 +47,21 @@ class AssemblyBinder m_ptrManagedAssemblyLoadContext = ptrManagedDefaultBinderInstance; } +#ifndef DACCESS_COMPILE + ASSEMBLYLOADCONTEXTREF GetManagedAssemblyLoadContextObject() + { + CONTRACTL + { + MODE_COOPERATIVE; + } + CONTRACTL_END; + + _ASSERTE(m_ptrManagedAssemblyLoadContext != NULL); + OBJECTHANDLE alcHandle = reinterpret_cast(m_ptrManagedAssemblyLoadContext); + return (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle(alcHandle); + } +#endif + NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); void AddLoadedAssembly(Assembly* loadedAssembly); From 2c981b9a04e5bff8fe19038db80505cc936eb7d2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 23:47:48 +0800 Subject: [PATCH 091/136] Restore usages in AssemblyNative --- .../Loader/AssemblyLoadContext.CoreCLR.cs | 19 ++---- src/coreclr/vm/assemblynative.cpp | 65 +++++++++---------- src/coreclr/vm/assemblynative.hpp | 10 +-- src/coreclr/vm/multicorejitplayer.cpp | 3 +- 4 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index d6505c81e6d908..08ecf366a97811 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -22,7 +22,7 @@ public partial class AssemblyLoadContext [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromStream")] - private static partial void LoadFromStream(ObjectHandleOnStack ptrNativeAssemblyBinder, IntPtr ptrAssemblyArray, int iAssemblyArrayLen, IntPtr ptrSymbols, int iSymbolArrayLen, ObjectHandleOnStack retAssembly); + private static partial void LoadFromStream(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyArray, int iAssemblyArrayLen, IntPtr ptrSymbols, int iSymbolArrayLen, ObjectHandleOnStack retAssembly); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MultiCoreJIT_InternalSetProfileRoot", StringMarshalling = StringMarshalling.Utf16)] internal static partial void InternalSetProfileRoot(string directoryPath); @@ -32,7 +32,7 @@ public partial class AssemblyLoadContext [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromPath", StringMarshalling = StringMarshalling.Utf16)] - private static partial void LoadFromPath(ObjectHandleOnStack ptrNativeAssemblyBinder, string? ilPath, string? niPath, ObjectHandleOnStack retAssembly); + private static partial void LoadFromPath(IntPtr ptrNativeAssemblyBinder, string? ilPath, string? niPath, ObjectHandleOnStack retAssembly); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern Assembly[] GetLoadedAssemblies(); @@ -60,8 +60,7 @@ public partial class AssemblyLoadContext private RuntimeAssembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) { RuntimeAssembly? loadedAssembly = null; - Internal.Runtime.Binder.AssemblyBinder assemblyBinder = _assemblyBinder; - LoadFromPath(ObjectHandleOnStack.Create(ref assemblyBinder), assemblyPath, nativeImagePath, ObjectHandleOnStack.Create(ref loadedAssembly)); + LoadFromPath(_nativeAssemblyLoadContext, assemblyPath, nativeImagePath, ObjectHandleOnStack.Create(ref loadedAssembly)); return loadedAssembly!; } @@ -69,11 +68,10 @@ private RuntimeAssembly InternalLoadFromPath(string? assemblyPath, string? nativ internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySpan arrSymbols) { RuntimeAssembly? loadedAssembly = null; - Internal.Runtime.Binder.AssemblyBinder assemblyBinder = _assemblyBinder; fixed (byte* ptrAssembly = arrAssembly, ptrSymbols = arrSymbols) { - LoadFromStream(ObjectHandleOnStack.Create(ref assemblyBinder), new IntPtr(ptrAssembly), arrAssembly.Length, + LoadFromStream(_nativeAssemblyLoadContext, new IntPtr(ptrAssembly), arrAssembly.Length, new IntPtr(ptrSymbols), arrSymbols.Length, ObjectHandleOnStack.Create(ref loadedAssembly)); } @@ -82,7 +80,7 @@ internal unsafe Assembly InternalLoad(ReadOnlySpan arrAssembly, ReadOnlySp #if TARGET_WINDOWS [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromInMemoryModule")] - private static partial IntPtr LoadFromInMemoryModuleInternal(ObjectHandleOnStack ptrNativeAssemblyBinder, IntPtr hModule, ObjectHandleOnStack retAssembly); + private static partial IntPtr LoadFromInMemoryModuleInternal(IntPtr ptrNativeAssemblyBinder, IntPtr hModule, ObjectHandleOnStack retAssembly); /// @@ -97,9 +95,8 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) VerifyIsAlive(); RuntimeAssembly? loadedAssembly = null; - Internal.Runtime.Binder.AssemblyBinder assemblyBinder = _assemblyBinder; LoadFromInMemoryModuleInternal( - ObjectHandleOnStack.Create(ref assemblyBinder), + _nativeAssemblyLoadContext, moduleHandle, ObjectHandleOnStack.Create(ref loadedAssembly)); return loadedAssembly!; @@ -188,9 +185,7 @@ public void SetProfileOptimizationRoot(string directoryPath) // Start profile optimization for the specified profile name. public void StartProfileOptimization(string? profile) { - // AssemblyBinder isn't supported in profiler implementation yet. - // See MulticoreJitProfilePlayer::LoadAssembly - InternalStartProfile(profile, IntPtr.Zero); + InternalStartProfile(profile, _nativeAssemblyLoadContext); } internal static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 91b4e4147559ca..51b29d0cb908b9 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -122,21 +122,18 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p } /* static */ -Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pImage, bool excludeAppPaths) +Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths) { CONTRACT(Assembly*) { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(pBinder != NULL); + STANDARD_VM_CHECK; + PRECONDITION(CheckPointer(pBinder)); PRECONDITION(pImage != NULL); POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; Assembly *pLoadedAssembly = NULL; - BINDERASSEMBLYREF pAssembly; // Set the caller's assembly to be CoreLib DomainAssembly *pCallersAssembly = SystemDomain::System()->SystemAssembly()->GetDomainAssembly(); @@ -144,22 +141,29 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI // Initialize the AssemblySpec AssemblySpec spec; spec.InitializeSpec(TokenFromRid(1, mdtAssembly), pImage->GetMDImport(), pCallersAssembly); - spec.SetBinder(GetAppDomain()->CreateHandle(pBinder)); + spec.SetBinder(pBinder); BinderTracing::AssemblyBindOperation bindOperation(&spec, pImage->GetPath()); HRESULT hr = S_OK; PTR_AppDomain pCurDomain = GetAppDomain(); - GCPROTECT_BEGIN(pBinder); + GCX_COOP(); - MethodDescCallSite methBind(METHOD__BINDER_ASSEMBLYBINDER__BINDUSINGPEIMAGE, &pBinder); + struct { + ASSEMBLYLOADCONTEXTREF pBinder; + BINDERASSEMBLYREF pAssembly; + } gc; + + GCPROTECT_BEGIN(gc); + + MethodDescCallSite methBind(METHOD__BINDER_ASSEMBLYBINDER__BINDUSINGPEIMAGE, &gc.pBinder); ARG_SLOT args[4] = { - ObjToArgSlot(pBinder), + ObjToArgSlot(gc.pBinder), PtrToArgSlot(pImage), BoolToArgSlot(excludeAppPaths), - PtrToArgSlot(&pAssembly) + PtrToArgSlot(&gc.pAssembly) }; hr = methBind.Call_RetHR(args); @@ -185,7 +189,7 @@ Assembly* AssemblyNative::LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pI } } - PEAssemblyHolder pPEAssembly(PEAssembly::Open(pAssembly->m_peImage, pAssembly)); + PEAssemblyHolder pPEAssembly(PEAssembly::Open(gc.pAssembly->m_peImage, gc.pAssembly)); bindOperation.SetResult(pPEAssembly.GetValue()); DomainAssembly *pDomainAssembly = pCurDomain->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); @@ -210,7 +214,7 @@ LoaderAllocator* AssemblyBinder_GetNativeLoaderAllocator(ASSEMBLYBINDERREF pBind return pNativeLA; } -extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) +extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; @@ -218,10 +222,8 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack PTR_AppDomain pCurDomain = GetAppDomain(); - GCX_COOP(); - // Get the binder context in which the assembly will be loaded. - ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ptrNativeAssemblyBinder.Get(); + AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); _ASSERTE(pBinder != NULL); // Form the PEImage for the ILAssembly. In case of an exception, the holder will ensure @@ -238,7 +240,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack if (!pILImage->CheckILFormat()) THROW_BAD_FORMAT(BFA_BAD_IL, pILImage.GetValue()); - LoaderAllocator* pLoaderAllocator = AssemblyBinder_GetNativeLoaderAllocator(pBinder); + LoaderAllocator* pLoaderAllocator = pBinder->GetLoaderAllocator(); if (pLoaderAllocator && pLoaderAllocator->IsCollectible() && !pILImage->IsILOnly()) { // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed @@ -246,7 +248,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack } } - Assembly *pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; + Assembly *pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); { GCX_COOP(); @@ -261,7 +263,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack } /*static */ -extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, +extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly) { @@ -270,7 +272,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnSta BEGIN_QCALL; // Ensure that the invariants are in place - _ASSERTE(ptrNativeAssemblyBinder.Get() != NULL); + _ASSERTE(ptrNativeAssemblyBinder != NULL); _ASSERTE((ptrAssemblyArray != NULL) && (cbAssemblyArrayLength > 0)); _ASSERTE((ptrSymbolArray == NULL) || (cbSymbolArrayLength > 0)); @@ -279,13 +281,11 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnSta // Need to verify that this is a valid CLR assembly. if (!pILImage->CheckILFormat()) ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); - - GCX_COOP(); // Get the binder context in which the assembly will be loaded - ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ptrNativeAssemblyBinder.Get(); + AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); - LoaderAllocator* pLoaderAllocator = AssemblyBinder_GetNativeLoaderAllocator(pBinder); + LoaderAllocator* pLoaderAllocator = pBinder->GetLoaderAllocator(); if (pLoaderAllocator && pLoaderAllocator->IsCollectible() && !pILImage->IsILOnly()) { // Loading IJW assemblies into a collectible AssemblyLoadContext is not allowed @@ -295,6 +295,7 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnSta // Pass the stream based assembly as IL in an attempt to bind and load it Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); { + GCX_COOP(); retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); } @@ -328,14 +329,14 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnSta #ifdef TARGET_WINDOWS /*static */ -extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly) +extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; BEGIN_QCALL; // Ensure that the invariants are in place - _ASSERTE(ptrNativeAssemblyBinder.Get() != NULL); + _ASSERTE(ptrNativeAssemblyBinder != NULL); _ASSERTE(hModule != NULL); PEImageHolder pILImage(PEImage::CreateFromHMODULE((HMODULE)hModule)); @@ -345,10 +346,10 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(QCall::ObjectHan ThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); // Get the binder context in which the assembly will be loaded - ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ptrNativeAssemblyBinder.Get(); + AssemblyBinder *pBinder = reinterpret_cast(ptrNativeAssemblyBinder); // Pass the in memory module as IL in an attempt to bind and load it - Assembly* pLoadedAssembly = /*AssemblyNative::LoadFromPEImage(pBinder, pILImage)*/ NULL; + Assembly* pLoadedAssembly = AssemblyNative::LoadFromPEImage(pBinder, pILImage); { GCX_COOP(); retLoadedAssembly.Set(pLoadedAssembly->GetExposedObject()); @@ -1330,14 +1331,12 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::Ass _ASSERTE(pAssembly != NULL); - GCX_COOP(); - - ASSEMBLYBINDERREF pAssemblyBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); + AssemblyBinder* pAssemblyBinder = pAssembly->GetPEAssembly()->GetAssemblyBinder(); - if (!pAssemblyBinder->m_isDefault) + if (!pAssemblyBinder->IsDefault()) { // Fetch the managed binder reference from the native binder instance - ptrManagedAssemblyLoadContext = pAssemblyBinder->m_managedALC; + ptrManagedAssemblyLoadContext = pAssemblyBinder->GetManagedAssemblyLoadContext(); _ASSERTE(ptrManagedAssemblyLoadContext != NULL); } diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index a327c741d6996c..c7b3ab2fd0acc6 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -24,8 +24,8 @@ class AssemblyNative friend class DomainAssembly; public: - - static Assembly* LoadFromPEImage(ASSEMBLYBINDERREF pBinder, PEImage *pImage, bool excludeAppPaths = false); + + static Assembly* LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths = false); // static FCALLs static FCDECL0(FC_BOOL_RET, IsTracingEnabled); @@ -121,12 +121,12 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder(); extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* pAssemblyName, QCall::ObjectHandleOnStack requestingAssembly, QCall::StackCrawlMarkHandle stackMark,BOOL fThrowOnFileNotFound, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly); -extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); +extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); -extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly); +extern "C" void QCALLTYPE AssemblyNative_LoadFromStream(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrAssemblyArray, INT32 cbAssemblyArrayLength, INT_PTR ptrSymbolArray, INT32 cbSymbolArrayLength, QCall::ObjectHandleOnStack retLoadedAssembly); #ifdef TARGET_WINDOWS -extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(QCall::ObjectHandleOnStack ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly); +extern "C" void QCALLTYPE AssemblyNative_LoadFromInMemoryModule(INT_PTR ptrNativeAssemblyBinder, INT_PTR hModule, QCall::ObjectHandleOnStack retLoadedAssembly); #endif extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly); diff --git a/src/coreclr/vm/multicorejitplayer.cpp b/src/coreclr/vm/multicorejitplayer.cpp index 17552197a9b990..2b8a0a1ba80992 100644 --- a/src/coreclr/vm/multicorejitplayer.cpp +++ b/src/coreclr/vm/multicorejitplayer.cpp @@ -835,8 +835,7 @@ DomainAssembly * MulticoreJitProfilePlayer::LoadAssembly(SString & assemblyName) // Set the binding context to the assembly load context. if (m_pBinder != NULL) { - // TODO: support - // spec.SetBinder(m_pBinder); + spec.SetBinder(m_pBinder); } // Bind and load the assembly. From 219e9e6ed986bd94999c358a6a0bea6c2a44e0ca Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 23:57:52 +0800 Subject: [PATCH 092/136] Restore lifetime management with LoaderAllocator --- .../Runtime/Binder/CustomAssemblyBinder.cs | 81 ------------------- .../src/System/Reflection/LoaderAllocator.cs | 11 --- src/coreclr/vm/loaderallocator.cpp | 40 ++------- src/coreclr/vm/loaderallocator.hpp | 9 ++- src/coreclr/vm/qcallentrypoints.cpp | 1 - 5 files changed, 14 insertions(+), 128 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs index ad3cf667508a6c..74a505f1504887 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs @@ -3,98 +3,17 @@ using System; using System.Diagnostics; -using System.Runtime.InteropServices; namespace Internal.Runtime.Binder { internal sealed class CustomAssemblyBinder : AssemblyBinder { - private readonly DefaultAssemblyBinder _defaultBinder; private System.Reflection.LoaderAllocator? _loaderAllocator; - private GCHandle _loaderAllocatorHandle; - - // A strong GC handle to the managed AssemblyLoadContext. This handle is set when the unload of the AssemblyLoadContext is initiated - // to keep the managed AssemblyLoadContext alive until the unload is finished. - // We still keep the weak handle pointing to the same managed AssemblyLoadContext so that native code can use the handle above - // to refer to it during the whole lifetime of the AssemblyLoadContext. - private GCHandle _ptrManagedStrongAssemblyLoadContext; public override bool IsDefault => false; public override System.Reflection.LoaderAllocator? GetLoaderAllocator() => _loaderAllocator; - public CustomAssemblyBinder( - DefaultAssemblyBinder defaultBinder, - System.Reflection.LoaderAllocator? loaderAllocator, - GCHandle loaderAllocatorHandle, - GCHandle ptrAssemblyLoadContext) - { - // Save reference to the DefaultBinder that is required to be present. - _defaultBinder = defaultBinder; - - // Save the reference to the IntPtr for GCHandle for the managed - // AssemblyLoadContext instance - ManagedAssemblyLoadContext = ptrAssemblyLoadContext; - - if (loaderAllocator != null) - { - // Link to LoaderAllocator, keep a reference to it - // VERIFY(pLoaderAllocator->AddReferenceIfAlive()); - - // ((AssemblyLoaderAllocator*)pLoaderAllocator)->RegisterBinder(pBinder); - var thisHandle = GCHandle.Alloc(this); - loaderAllocator.RegisterBinder(thisHandle); - } - - _loaderAllocator = loaderAllocator; - _loaderAllocatorHandle = loaderAllocatorHandle; - } - - public void PrepareForLoadContextRelease(GCHandle ptrManagedStrongAssemblyLoadContext) - { - // Add a strong handle so that the managed assembly load context stays alive until the - // CustomAssemblyBinder::ReleaseLoadContext is called. - // We keep the weak handle as well since this method can be running on one thread (e.g. the finalizer one) - // and other thread can be using the weak handle. - _ptrManagedStrongAssemblyLoadContext = ptrManagedStrongAssemblyLoadContext; - - Debug.Assert(_loaderAllocator != null); - Debug.Assert(_loaderAllocatorHandle.IsAllocated); - - // We cannot delete the binder here as it is used indirectly when comparing assemblies with the same binder - // It will be deleted when the LoaderAllocator will be deleted - // We need to keep the LoaderAllocator pointer set as it still may be needed for creating references between the - // native LoaderAllocators of two collectible contexts in case the AssemblyLoadContext.Unload was called on the current - // context before returning from its AssemblyLoadContext.Load override or the context's Resolving event. - // But we need to release the LoaderAllocator so that it doesn't prevent completion of the final phase of unloading in - // some cases. It is safe to do as the AssemblyLoaderAllocator is guaranteed to be alive at least until the - // CustomAssemblyBinder::ReleaseLoadContext is called, where we NULL this pointer. - - _loaderAllocator = null!; - - // Destroy the strong handle to the LoaderAllocator in order to let it reach its finalizer - _loaderAllocatorHandle.Free(); - _loaderAllocatorHandle = default; - } - - ~CustomAssemblyBinder() - { - // CustomAssemblyBinder::ReleaseLoadContext - - Debug.Assert(ManagedAssemblyLoadContext.IsAllocated); - Debug.Assert(_ptrManagedStrongAssemblyLoadContext.IsAllocated); - - // This method is called to release the weak and strong handles on the managed AssemblyLoadContext - // once the Unloading event has been fired - ManagedAssemblyLoadContext.Free(); - _ptrManagedStrongAssemblyLoadContext.Free(); - ManagedAssemblyLoadContext = default; - - // The AssemblyLoaderAllocator is in a process of shutdown and should not be used - // after this point. - _ptrManagedStrongAssemblyLoadContext.Free(); - } - private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly) { // CoreLib should be bound using BindToSystem diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index b3c9df0366086e..181d9914892617 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -65,16 +65,5 @@ private LoaderAllocator() internal static partial void EnsureReference(IntPtr nativeLoaderAllocator, IntPtr otherNativeLoaderAllocator); internal void EnsureReference(IntPtr otherNativeLA) => EnsureReference(m_scout.m_nativeLoaderAllocator, otherNativeLA); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_IsCollectible")] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool IsCollectible(IntPtr nativeLoaderAllocator); - - internal bool IsCollectible() => IsCollectible(m_scout.m_nativeLoaderAllocator); - - internal void RegisterBinder(GCHandle handle) => RegisterBinder(m_scout.m_nativeLoaderAllocator, handle); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_RegisterBinder")] - private static partial void RegisterBinder(IntPtr pNativeLA, GCHandle handle); } } diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 9b5373cb537a43..29a343d0accc96 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -264,32 +264,6 @@ extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocator END_QCALL; } -extern "C" BOOL QCALLTYPE LoaderAllocator_IsCollectible(QCall::LoaderAllocatorHandle pLA) -{ - QCALL_CONTRACT; - - BOOL result = FALSE; - - BEGIN_QCALL; - - result = pLA->IsCollectible(); - - END_QCALL; - - return result; -} - -extern "C" void QCALLTYPE LoaderAllocator_RegisterBinder(AssemblyLoaderAllocator* pLA, OBJECTHANDLE handle) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - pLA->RegisterBinder(handle); - - END_QCALL; -} - BOOL LoaderAllocator::EnsureInstantiation(Module *pDefiningModule, Instantiation inst) { CONTRACTL @@ -1752,11 +1726,17 @@ void AssemblyLoaderAllocator::Init(AppDomain* pAppDomain) AssemblyLoaderAllocator::~AssemblyLoaderAllocator() { + if (m_binderToRelease != NULL) + { + delete m_binderToRelease; + m_binderToRelease = NULL; + } + delete m_pShuffleThunkCache; m_pShuffleThunkCache = NULL; } -void AssemblyLoaderAllocator::RegisterBinder(OBJECTHANDLE binderToRelease) +void AssemblyLoaderAllocator::RegisterBinder(CustomAssemblyBinder* binderToRelease) { // When the binder is registered it will be released by the destructor // of this instance @@ -2061,11 +2041,7 @@ void AssemblyLoaderAllocator::ReleaseManagedAssemblyLoadContext() if (m_binderToRelease != NULL) { // Release the managed ALC - // Depends on the destructor of managed binder - - // m_binderToRelease->ReleaseLoadContext(); - DestroyHandle(m_binderToRelease); - m_binderToRelease = NULL; + m_binderToRelease->ReleaseLoadContext(); } } diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 5fe13e668c3f02..3b6a4efcca01d0 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -838,7 +838,6 @@ typedef VPTR(LoaderAllocator) PTR_LoaderAllocator; extern "C" BOOL QCALLTYPE LoaderAllocator_Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator); extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocatorHandle pLA, QCall::LoaderAllocatorHandle pOtherLA); -extern "C" BOOL QCALLTYPE LoaderAllocator_IsCollectible(QCall::LoaderAllocatorHandle pLA); class GlobalLoaderAllocator : public LoaderAllocator { @@ -900,8 +899,12 @@ class AssemblyLoaderAllocator : public LoaderAllocator virtual void RegisterHandleForCleanup(OBJECTHANDLE objHandle); virtual void UnregisterHandleFromCleanup(OBJECTHANDLE objHandle); virtual void CleanupHandles(); + CustomAssemblyBinder* GetBinder() + { + return m_binderToRelease; + } virtual ~AssemblyLoaderAllocator(); - void RegisterBinder(OBJECTHANDLE binderToRelease); + void RegisterBinder(CustomAssemblyBinder* binderToRelease); virtual void ReleaseManagedAssemblyLoadContext(); #endif // !defined(DACCESS_COMPILE) @@ -919,7 +922,7 @@ class AssemblyLoaderAllocator : public LoaderAllocator SList m_handleCleanupList; #if !defined(DACCESS_COMPILE) - OBJECTHANDLE m_binderToRelease; + CustomAssemblyBinder* m_binderToRelease; #endif private: diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 0af4b107d21fc7..b74f8a31896ca1 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -214,7 +214,6 @@ static const Entry s_QCall[] = #endif DllImportEntry(LoaderAllocator_Destroy) DllImportEntry(LoaderAllocator_EnsureReference) - DllImportEntry(LoaderAllocator_IsCollectible) DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) DllImportEntry(ThreadNative_InformThreadNameChange) From 37702daebc26eaae93f40befe7b9eeb8534d8dbc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 00:09:58 +0800 Subject: [PATCH 093/136] Fix some compilation --- src/coreclr/vm/assemblybinder.cpp | 13 +++++++++ src/coreclr/vm/assemblybinder.h | 13 +-------- src/coreclr/vm/object.h | 44 +++++++++++++------------------ src/coreclr/vm/peassembly.cpp | 1 + 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index 3fa911bdec8fe3..30d5c1c07c07dd 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -8,6 +8,19 @@ #ifndef DACCESS_COMPILE +ASSEMBLYLOADCONTEXTREF AssemblyBinder::GetManagedAssemblyLoadContextObject() +{ + CONTRACTL + { + MODE_COOPERATIVE; + } + CONTRACTL_END; + + _ASSERTE(m_ptrManagedAssemblyLoadContext != NULL); + OBJECTHANDLE alcHandle = reinterpret_cast(m_ptrManagedAssemblyLoadContext); + return (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle(alcHandle); +} + HRESULT AssemblyBinder::BindAssemblyByName(AssemblyNameData* pAssemblyNameData, BINDER_SPACE::Assembly** ppAssembly) { diff --git a/src/coreclr/vm/assemblybinder.h b/src/coreclr/vm/assemblybinder.h index d273b6bc4e63f2..44c3b9a7c71b53 100644 --- a/src/coreclr/vm/assemblybinder.h +++ b/src/coreclr/vm/assemblybinder.h @@ -48,18 +48,7 @@ class AssemblyBinder } #ifndef DACCESS_COMPILE - ASSEMBLYLOADCONTEXTREF GetManagedAssemblyLoadContextObject() - { - CONTRACTL - { - MODE_COOPERATIVE; - } - CONTRACTL_END; - - _ASSERTE(m_ptrManagedAssemblyLoadContext != NULL); - OBJECTHANDLE alcHandle = reinterpret_cast(m_ptrManagedAssemblyLoadContext); - return (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle(alcHandle); - } + ASSEMBLYLOADCONTEXTREF GetManagedAssemblyLoadContextObject(); #endif NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index f47a8ef2902b69..0ba22f929cb411 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1451,31 +1451,6 @@ class AssemblyBinderObject : public Object INT_PTR m_managedALC; }; -#ifdef USE_CHECKED_OBJECTREFS - -#else - -#endif - -class PEImage; - -// managed Internal.Runtime.Binder.Assembly -class BinderAssemblyObject : public Object -{ -public: - OBJECTREF m_binder; - OBJECTREF m_assemblyName; - PEImage* m_peImage; - DomainAssembly* m_pDomainAssembly; - CLR_BOOL m_isInTPA; - CLR_BOOL m_isCoreLib; - - PTR_AssemblyBinder GetBinder() - { - return (PTR_AssemblyBinder)((ASSEMBLYLOADCONTEXTREF)m_binder)->GetNativeAssemblyBinder(); - } -}; - // AssemblyLoadContextBaseObject // This class is the base class for AssemblyLoadContext // @@ -1622,6 +1597,25 @@ typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; #endif //USE_CHECKED_OBJECTREFS +class PEImage; + +// managed Internal.Runtime.Binder.Assembly +class BinderAssemblyObject : public Object +{ +public: + ASSEMBLYLOADCONTEXTREF m_binder; + OBJECTREF m_assemblyName; + PEImage* m_peImage; + DomainAssembly* m_pDomainAssembly; + CLR_BOOL m_isInTPA; + CLR_BOOL m_isCoreLib; + + PTR_AssemblyBinder GetBinder() + { + return (PTR_AssemblyBinder)m_binder->GetNativeAssemblyBinder(); + } +}; + #define PtrToArgSlot(ptr) ((ARG_SLOT)(SIZE_T)(ptr)) #define ArgSlotToPtr(s) ((LPVOID)(SIZE_T)(s)) diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index d60f5a7c96b2f2..da1c3359d0f1bb 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -16,6 +16,7 @@ #include "peimagelayout.inl" #include "invokeutil.h" #include "strongnameinternal.h" +#include "object.h" #include "../binder/inc/applicationcontext.hpp" #include "../binder/inc/assemblybindercommon.hpp" From 4f20259f9a0355476b48c3f885666d14b926405c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 00:28:21 +0800 Subject: [PATCH 094/136] Fix more usage --- src/coreclr/binder/defaultassemblybinder.cpp | 40 ++++++++++---------- src/coreclr/vm/appdomainnative.cpp | 5 ++- src/coreclr/vm/assembly.cpp | 16 ++------ src/coreclr/vm/assembly.hpp | 4 +- src/coreclr/vm/assemblynative.cpp | 11 +++--- src/coreclr/vm/ceeload.cpp | 10 ++--- src/coreclr/vm/ceeload.h | 4 +- src/coreclr/vm/coreassemblyspec.cpp | 4 +- src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/corhost.cpp | 2 +- 10 files changed, 46 insertions(+), 52 deletions(-) diff --git a/src/coreclr/binder/defaultassemblybinder.cpp b/src/coreclr/binder/defaultassemblybinder.cpp index d4ad4f3265ce8b..3b98997bf46461 100644 --- a/src/coreclr/binder/defaultassemblybinder.cpp +++ b/src/coreclr/binder/defaultassemblybinder.cpp @@ -189,24 +189,26 @@ HRESULT DefaultAssemblyBinder::SetupBindingPaths(SString &sTrustedPlatformAssem HRESULT DefaultAssemblyBinder::BindToSystem(BINDER_SPACE::Assembly** ppSystemAssembly) { - HRESULT hr = S_OK; - _ASSERTE(ppSystemAssembly != NULL); - - EX_TRY - { - ReleaseHolder pAsm; - StackSString systemPath(SystemDomain::System()->SystemDirectory()); - hr = AssemblyBinderCommon::BindToSystem(systemPath, &pAsm); - if (SUCCEEDED(hr)) - { - _ASSERTE(pAsm != NULL); - *ppSystemAssembly = pAsm.Extract(); - (*ppSystemAssembly)->SetBinder(this); - } - - } - EX_CATCH_HRESULT(hr); - - return hr; + //HRESULT hr = S_OK; + //_ASSERTE(ppSystemAssembly != NULL); + + //EX_TRY + //{ + // ReleaseHolder pAsm; + // StackSString systemPath(SystemDomain::System()->SystemDirectory()); + // hr = AssemblyBinderCommon::BindToSystem(systemPath, &pAsm); + // if (SUCCEEDED(hr)) + // { + // _ASSERTE(pAsm != NULL); + // *ppSystemAssembly = pAsm.Extract(); + // (*ppSystemAssembly)->SetBinder(this); + // } + + //} + //EX_CATCH_HRESULT(hr); + + //return hr; + + return E_FAIL; // unused } diff --git a/src/coreclr/vm/appdomainnative.cpp b/src/coreclr/vm/appdomainnative.cpp index 88f9ae04d4d55d..79012785e8ecbc 100644 --- a/src/coreclr/vm/appdomainnative.cpp +++ b/src/coreclr/vm/appdomainnative.cpp @@ -26,9 +26,10 @@ extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnS _ASSERTE(assemblyLoadContext.Get() != NULL); - OBJECTREF pBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); + INT_PTR nativeAssemblyBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); + AssemblyBinder* pBinder = reinterpret_cast(nativeAssemblyBinder); - Assembly* pAssembly = Assembly::CreateDynamic(GetAppDomain()->CreateHandle(pBinder), pAssemblyNameParts, hashAlgorithm, access, &keepAlive); + Assembly* pAssembly = Assembly::CreateDynamic(pBinder, pAssemblyNameParts, hashAlgorithm, access, &keepAlive); retAssembly.Set(pAssembly->GetExposedObject()); diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 6cc26178f6a4fc..8833aa45742b30 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -368,7 +368,7 @@ Assembly * Assembly::Create( return pAssembly; } // Assembly::Create -Assembly *Assembly::CreateDynamic(OBJECTHANDLE pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive) +Assembly *Assembly::CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive) { // WARNING: not backout clean CONTRACT(Assembly *) @@ -446,22 +446,14 @@ Assembly *Assembly::CreateDynamic(OBJECTHANDLE pBinder, NativeAssemblyNameParts* BOOL createdNewAssemblyLoaderAllocator = FALSE; { + GCX_PREEMP(); + AssemblyLoaderAllocator* pBinderLoaderAllocator = nullptr; if (pBinder != nullptr) { - ASSEMBLYBINDERREF binderObj = (ASSEMBLYBINDERREF)ObjectFromHandle(pBinder); - MethodDescCallSite methGetLoaderAllocator(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); - ARG_SLOT args[1] = - { - ObjToArgSlot(binderObj) - }; - LOADERALLOCATORREF managedLA = (LOADERALLOCATORREF)methGetLoaderAllocator.Call_RetOBJECTREF(args); - - pBinderLoaderAllocator = (AssemblyLoaderAllocator*)managedLA->GetNativeLoaderAllocator(); + pBinderLoaderAllocator = pBinder->GetLoaderAllocator(); } - GCX_PREEMP(); - // Create a new LoaderAllocator if appropriate if ((access & ASSEMBLY_ACCESS_COLLECT) != 0) { diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index 99cde07902ae47..98d20bb3bbf182 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -65,8 +65,8 @@ class Assembly static void Initialize(); BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->IsSystem(); } - - static Assembly* CreateDynamic(OBJECTHANDLE pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive); + + static Assembly* CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive); MethodDesc *GetEntryPoint(); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 51b29d0cb908b9..18fa2f0ac765bb 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -43,14 +43,15 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p DomainAssembly * pParentAssembly = NULL; Assembly * pRefAssembly = NULL; - ASSEMBLYBINDERREF pBinder = NULL; - - GCX_COOP(); + AssemblyBinder *pBinder = NULL; { + GCX_COOP(); + if (assemblyLoadContext.Get() != NULL) { - pBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); + INT_PTR nativeAssemblyBinder = ((ASSEMBLYLOADCONTEXTREF)assemblyLoadContext.Get())->GetNativeAssemblyBinder(); + pBinder = reinterpret_cast(nativeAssemblyBinder); } // Compute parent assembly @@ -99,7 +100,7 @@ extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* p // If so, then use it to set the fallback load context binder. if (pBinder != NULL) { - spec.SetFallbackBinderForRequestingAssembly(GetAppDomain()->CreateHandle(pBinder)); + spec.SetFallbackBinderForRequestingAssembly(pBinder); spec.SetPreferFallbackBinder(); } else if (pRefAssembly != NULL) diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 573937745c0a39..d19781c9a1db9d 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -2848,7 +2848,7 @@ Module::GetAssemblyIfLoaded( mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride, // = NULL BOOL fDoNotUtilizeExtraChecks, // = FALSE - OBJECTHANDLE pBinderForLoadedAssembly // = NULL + AssemblyBinder *pBinderForLoadedAssembly // = NULL ) { CONTRACT(Assembly *) @@ -3033,22 +3033,20 @@ DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) // Set the binding context in the AssemblySpec if one is available. This can happen if the LoadAssembly ended up // invoking the custom AssemblyLoadContext implementation that returned a reference to an assembly bound to a different // AssemblyLoadContext implementation. - GCX_COOP(); - ASSEMBLYBINDERREF pBinder = pPEAssembly->GetAssemblyBinder(); + AssemblyBinder *pBinder = pPEAssembly->GetAssemblyBinder(); if (pBinder != NULL) { - spec.SetBinder(GetDomain()->CreateHandle(pBinder)); + spec.SetBinder(pBinder); } pDomainAssembly = GetAppDomain()->LoadDomainAssembly(&spec, pPEAssembly, FILE_LOADED); } if (pDomainAssembly != NULL) { - GCX_COOP(); _ASSERTE( pDomainAssembly->IsSystem() || // GetAssemblyIfLoaded will not find CoreLib (see AppDomain::FindCachedFile) !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies - GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, GetDomain()->CreateHandle(((BINDERASSEMBLYREF)ObjectFromHandle(pDomainAssembly->GetPEAssembly()->GetHostAssembly()))->m_binder)) != NULL); // GetAssemblyIfLoaded should find all remaining cases + GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, (AssemblyBinder*)((BINDERASSEMBLYREF)ObjectFromHandle(pDomainAssembly->GetPEAssembly()->GetHostAssembly()))->m_binder->GetNativeAssemblyBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases if (pDomainAssembly->GetAssembly() != NULL) { diff --git a/src/coreclr/vm/ceeload.h b/src/coreclr/vm/ceeload.h index cc6092dc5ac3f6..540d386fa6e45a 100644 --- a/src/coreclr/vm/ceeload.h +++ b/src/coreclr/vm/ceeload.h @@ -543,7 +543,7 @@ class ModuleBase mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride = NULL, BOOL fDoNotUtilizeExtraChecks = FALSE, - OBJECTHANDLE pBinderForLoadedAssembly = NULL + AssemblyBinder *pBinderForLoadedAssembly = NULL ) { LIMITED_METHOD_DAC_CONTRACT; @@ -1169,7 +1169,7 @@ class Module : public ModuleBase mdAssemblyRef kAssemblyRef, IMDInternalImport * pMDImportOverride = NULL, BOOL fDoNotUtilizeExtraChecks = FALSE, - OBJECTHANDLE pBinderForLoadedAssembly = NULL + AssemblyBinder *pBinderForLoadedAssembly = NULL ) final; protected: diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 1df07a5c85469b..489708d9bfc797 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -48,12 +48,12 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly struct { - ASSEMBLYBINDERREF pBinder; + ASSEMBLYLOADCONTEXTREF pBinder; BINDERASSEMBLYREF pPrivAsm; } gc; // Have a default binding context setup - gc.pBinder = GetBinderFromParentAssembly(pAppDomain); + gc.pBinder = GetBinderFromParentAssembly(pAppDomain)->GetManagedAssemblyLoadContextObject(); gc.pPrivAsm = NULL; _ASSERTE(gc.pBinder != NULL); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 78594284d1e427..df729e0af7dfd5 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -884,7 +884,7 @@ DEFINE_FIELD_U(_resolvingUnmanagedDll, AssemblyLoadContextBaseObject, _reso DEFINE_FIELD_U(_resolving, AssemblyLoadContextBaseObject, _resolving) DEFINE_FIELD_U(_unloading, AssemblyLoadContextBaseObject, _unloading) DEFINE_FIELD_U(_name, AssemblyLoadContextBaseObject, _name) -DEFINE_FIELD_U(_assemblyBinder, AssemblyLoadContextBaseObject, _assemblyBinder) +DEFINE_FIELD_U(_nativeAssemblyLoadContext, AssemblyLoadContextBaseObject, _nativeAssemblyLoadContext) DEFINE_FIELD_U(_id, AssemblyLoadContextBaseObject, _id) DEFINE_FIELD_U(_state, AssemblyLoadContextBaseObject, _state) DEFINE_FIELD_U(_isCollectible, AssemblyLoadContextBaseObject, _isCollectible) diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 1942fc767eb9c0..4d09ac0295e819 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -620,7 +620,7 @@ HRESULT CorHost2::CreateAppDomainWithManager( { GCX_COOP(); - ASSEMBLYBINDERREF pBinder = (ASSEMBLYBINDERREF)ObjectFromHandle(pDomain->GetDefaultBinder()); + ASSEMBLYLOADCONTEXTREF pBinder = pDomain->GetDefaultBinder()->GetManagedAssemblyLoadContextObject(); _ASSERTE(pBinder != NULL); GCPROTECT_BEGIN(pBinder); From b832f396c1d9dcda82c254290aaa1e0c85d5e1f6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 01:00:08 +0800 Subject: [PATCH 095/136] Give up exposing ALC ref in AssemblyBinder --- src/coreclr/vm/appdomain.cpp | 4 ++-- src/coreclr/vm/assemblybinder.cpp | 13 ------------- src/coreclr/vm/assemblybinder.h | 4 ---- src/coreclr/vm/coreassemblyspec.cpp | 2 +- src/coreclr/vm/corhost.cpp | 2 +- 5 files changed, 4 insertions(+), 21 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 708824e2bb4f14..748c9d52223347 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1162,7 +1162,7 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); - ASSEMBLYLOADCONTEXTREF defaultBinder = (ASSEMBLYLOADCONTEXTREF)GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContextObject(); + ASSEMBLYLOADCONTEXTREF defaultBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()); { // AdHoc setup for corelib PEAssembly @@ -2821,7 +2821,7 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, MethodDescCallSite methAddLoadedAssem(METHOD__BINDER_ASSEMBLYBINDER__ADDLOADEDASSEMBLY); ARG_SLOT args[2] = { - ObjToArgSlot(pPEAssembly->GetAssemblyBinder()->GetManagedAssemblyLoadContextObject()), + ObjToArgSlot((ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)(pPEAssembly->GetAssemblyBinder()))), PtrToArgSlot(pDomainAssembly->GetAssembly()) }; methAddLoadedAssem.Call(args); diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index 30d5c1c07c07dd..3fa911bdec8fe3 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -8,19 +8,6 @@ #ifndef DACCESS_COMPILE -ASSEMBLYLOADCONTEXTREF AssemblyBinder::GetManagedAssemblyLoadContextObject() -{ - CONTRACTL - { - MODE_COOPERATIVE; - } - CONTRACTL_END; - - _ASSERTE(m_ptrManagedAssemblyLoadContext != NULL); - OBJECTHANDLE alcHandle = reinterpret_cast(m_ptrManagedAssemblyLoadContext); - return (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle(alcHandle); -} - HRESULT AssemblyBinder::BindAssemblyByName(AssemblyNameData* pAssemblyNameData, BINDER_SPACE::Assembly** ppAssembly) { diff --git a/src/coreclr/vm/assemblybinder.h b/src/coreclr/vm/assemblybinder.h index 44c3b9a7c71b53..8fa57302cfa401 100644 --- a/src/coreclr/vm/assemblybinder.h +++ b/src/coreclr/vm/assemblybinder.h @@ -47,10 +47,6 @@ class AssemblyBinder m_ptrManagedAssemblyLoadContext = ptrManagedDefaultBinderInstance; } -#ifndef DACCESS_COMPILE - ASSEMBLYLOADCONTEXTREF GetManagedAssemblyLoadContextObject(); -#endif - NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); void AddLoadedAssembly(Assembly* loadedAssembly); diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 489708d9bfc797..2c8298226126b6 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -53,7 +53,7 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly } gc; // Have a default binding context setup - gc.pBinder = GetBinderFromParentAssembly(pAppDomain)->GetManagedAssemblyLoadContextObject(); + gc.pBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)GetBinderFromParentAssembly(pAppDomain)->GetManagedAssemblyLoadContext()); gc.pPrivAsm = NULL; _ASSERTE(gc.pBinder != NULL); diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 4d09ac0295e819..3dbaef9876cac0 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -620,7 +620,7 @@ HRESULT CorHost2::CreateAppDomainWithManager( { GCX_COOP(); - ASSEMBLYLOADCONTEXTREF pBinder = pDomain->GetDefaultBinder()->GetManagedAssemblyLoadContextObject(); + ASSEMBLYLOADCONTEXTREF pBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)pDomain->GetDefaultBinder()->GetManagedAssemblyLoadContext()); _ASSERTE(pBinder != NULL); GCPROTECT_BEGIN(pBinder); From 51decaaf6ed0105662e6ad2fa4a954de678babbb Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 10:51:02 +0800 Subject: [PATCH 096/136] Fold managed AssemblyBinder into ALC --- .../System.Private.CoreLib.csproj | 8 ++--- .../src/Internal/Runtime/Binder/Assembly.cs | 5 +-- .../Loader/AssemblyLoadContext.Binder.cs} | 32 ++++++------------- .../AssemblyLoadContext.BinderCommon.cs} | 15 ++++----- .../AssemblyLoadContext.CustomBinder.cs} | 18 +++++------ .../AssemblyLoadContext.DefaultBinder.cs} | 31 +++++++----------- .../Runtime/Loader/AssemblyLoadContext.cs | 2 +- 7 files changed, 44 insertions(+), 67 deletions(-) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder/AssemblyBinder.cs => System/Runtime/Loader/AssemblyLoadContext.Binder.cs} (88%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder/AssemblyBinderCommon.cs => System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs} (99%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder/CustomAssemblyBinder.cs => System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs} (88%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder/DefaultAssemblyBinder.cs => System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs} (83%) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 93c9dd5adc7c51..2336df2c752e91 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -121,14 +121,10 @@ - - - - @@ -239,7 +235,11 @@ + + + + diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs index 854498efed8516..042be36ce0fc59 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Runtime.Loader; namespace Internal.Runtime.Binder { @@ -12,7 +13,7 @@ internal sealed class Assembly { // fields used by VM #pragma warning disable CA1823, 414, 169 - private AssemblyBinder? m_binder; + private AssemblyLoadContext? m_binder; private AssemblyName m_assemblyName; private IntPtr m_peImage; private IntPtr m_pDomainAssembly; @@ -20,7 +21,7 @@ internal sealed class Assembly private bool m_isCoreLib; #pragma warning restore CA1823, 414, 169 - public AssemblyBinder? Binder + public AssemblyLoadContext? Binder { get => m_binder; set => m_binder = value; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs similarity index 88% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index b1ff9fb1000dba..88ca72c1a3a743 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -1,14 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.Loader; +using Internal.Runtime.Binder; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { // System.Reflection.TypeLoading.AssemblyNameData internal readonly unsafe struct AssemblyNameData @@ -30,7 +29,7 @@ internal readonly unsafe struct AssemblyNameData public readonly AssemblyIdentityFlags IdentityFlags; } - internal abstract partial class AssemblyBinder + public partial class AssemblyLoadContext { // fields used by VM private GCHandle m_managedALC; @@ -42,23 +41,12 @@ protected AssemblyBinder() _ = GetHashCode(); // Calculate hashcode for AssemblySpecBindingCache usage } - public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) + private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) { return BindUsingAssemblyName(new AssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); } - public abstract int BindUsingPEImage(IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly); - - public abstract int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly); - - /// - /// Get LoaderAllocator for binders that contain it. For other binders, return NULL. - /// - public abstract System.Reflection.LoaderAllocator? GetLoaderAllocator(); - - public abstract bool IsDefault { get; } - - public ApplicationContext AppContext { get; } = new ApplicationContext(); + internal ApplicationContext AppContext { get; } = new ApplicationContext(); // A GC handle to the managed AssemblyLoadContext. // It is a long weak handle for collectible AssemblyLoadContexts and strong handle for non-collectible ones. @@ -67,7 +55,7 @@ public unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? asse // NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); // called by vm - public void AddLoadedAssembly(IntPtr loadedAssembly) + private void AddLoadedAssembly(IntPtr loadedAssembly) { // BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); // TODO: is the lock shared outside this type? @@ -81,9 +69,9 @@ public void AddLoadedAssembly(IntPtr loadedAssembly) } } - public string GetNameForDiagnostics() => IsDefault ? "Default" : GetNameForDiagnosticsFromManagedALC(ManagedAssemblyLoadContext); + private string GetNameForDiagnostics() => IsDefault ? "Default" : GetNameForDiagnosticsFromManagedALC(ManagedAssemblyLoadContext); - public static string GetNameForDiagnosticsFromManagedALC(GCHandle managedALC) + private static string GetNameForDiagnosticsFromManagedALC(GCHandle managedALC) { AssemblyLoadContext? alc = managedALC.IsAllocated ? (AssemblyLoadContext?)managedALC.Target : null; @@ -117,11 +105,11 @@ private static void MvidMismatchFatalError(Guid mvidActual, Guid mvidExpected, s } // used by vm - internal unsafe void DeclareDependencyOnMvid(byte* simpleName, in Guid mvid, bool compositeComponent, byte* imageName) + private unsafe void DeclareDependencyOnMvid(byte* simpleName, in Guid mvid, bool compositeComponent, byte* imageName) => DeclareDependencyOnMvid(new MdUtf8String(simpleName).ToString(), mvid, compositeComponent, new MdUtf8String(imageName).ToString()); // Must be called under the LoadLock - public void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool compositeComponent, string imageName) + private void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool compositeComponent, string imageName) { // If the table is empty, then we didn't fill it with all the loaded assemblies as they were loaded. Record this detail, and fix after adding the dependency bool addAllLoadedModules = false; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs similarity index 99% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index cc65fa0bb39c0d..ba85a8336471a2 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyBinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -1,19 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Tracing; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Runtime.Loader; +using Internal.Runtime.Binder; using Internal.Runtime.Binder.Tracing; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { + internal enum CorPEKind { peNot = 0x00000000, // not a PE file @@ -207,7 +206,7 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) public const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); public const int CLR_E_BIND_ARCHITECTURE_MISMATCH = unchecked((int)0x80132006); - public static int BindAssembly(AssemblyBinder binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) + public static int BindAssembly(AssemblyLoadContext binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) { int kContextVersion = 0; BindResult bindResult = default; @@ -948,8 +947,8 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi public static int BindUsingHostAssemblyResolver( GCHandle pManagedAssemblyLoadContextToBindWithin, AssemblyName assemblyName, - DefaultAssemblyBinder? defaultBinder, - AssemblyBinder binder, + AssemblyLoadContext? defaultBinder, + AssemblyLoadContext binder, out Assembly? loadedAssembly) { int hr = HResults.E_FAIL; @@ -1157,7 +1156,7 @@ public static int BindUsingHostAssemblyResolver( return hr; } - public static int BindUsingPEImage(AssemblyBinder binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) + public static int BindUsingPEImage(AssemblyLoadContext binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) { int hr = HResults.S_OK; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs similarity index 88% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index 74a505f1504887..7a6b8228a2e0d0 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/CustomAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -1,18 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Diagnostics; +using Internal.Runtime.Binder; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { - internal sealed class CustomAssemblyBinder : AssemblyBinder + public partial class AssemblyLoadContext { - private System.Reflection.LoaderAllocator? _loaderAllocator; + private Reflection.LoaderAllocator _loaderAllocator; - public override bool IsDefault => false; - - public override System.Reflection.LoaderAllocator? GetLoaderAllocator() => _loaderAllocator; + internal virtual Reflection.LoaderAllocator? GetLoaderAllocator() => _loaderAllocator; private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly) { @@ -30,7 +28,7 @@ private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? co return hr; } - public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) + internal virtual int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) { int hr; Assembly? coreCLRFoundAssembly; @@ -62,7 +60,7 @@ public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembl // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly // that has been loaded. - hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(ManagedAssemblyLoadContext, assemblyName, _defaultBinder, this, out coreCLRFoundAssembly); + hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(ManagedAssemblyLoadContext, assemblyName, Default, this, out coreCLRFoundAssembly); if (hr >= 0) { @@ -79,7 +77,7 @@ public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembl return hr; } - public override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) + internal virtual int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) { assembly = null; int hr; diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs similarity index 83% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index 516dc3b4b6620f..8c3fa46574bc95 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/DefaultAssemblyBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -1,21 +1,19 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Diagnostics; using System.Runtime.InteropServices; -using System.Runtime.Loader; +using Internal.Runtime.Binder; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { - internal sealed class DefaultAssemblyBinder : AssemblyBinder + internal partial class DefaultAssemblyLoadContext { - public override bool IsDefault => true; - // Not supported by this binder - public override System.Reflection.LoaderAllocator? GetLoaderAllocator() => null; + internal override Reflection.LoaderAllocator? GetLoaderAllocator() => null; - public Assembly CreateCoreLib(IntPtr pCoreLibPEImage) => new Assembly(pCoreLibPEImage, true) { Binder = this }; + // called by vm + private Assembly CreateCoreLib(IntPtr pCoreLibPEImage) => new Assembly(pCoreLibPEImage, true) { Binder = this }; // Helper functions private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly, bool excludeAppPaths) @@ -34,7 +32,7 @@ private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? co return hr; } - public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) + internal override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) { assembly = null; @@ -60,7 +58,7 @@ public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembl if (!assemblyName.IsNeutralCulture) { // Make sure the managed default ALC is initialized. - AssemblyLoadContext.InitializeDefaultContext(); + InitializeDefaultContext(); } pManagedAssemblyLoadContext = ManagedAssemblyLoadContext; @@ -88,7 +86,7 @@ public override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembl return hr; } - public override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) + internal override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) { assembly = null; int hr; @@ -144,17 +142,10 @@ public override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out As return hr; } - public void SetupBindingPaths(string trustedPlatformAssemblies, string platformResourceRoots, string appPaths) - { - AppContext.SetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPaths, acquireLock: true); - } - // called by VM - public unsafe void SetupBindingPaths(char* trustedPlatformAssemblies, char* platformResourceRoots, char* appPaths) + private unsafe void SetupBindingPaths(char* trustedPlatformAssemblies, char* platformResourceRoots, char* appPaths) { - SetupBindingPaths(new string(trustedPlatformAssemblies), new string(platformResourceRoots), new string(appPaths)); + AppContext.SetupBindingPaths(new string(trustedPlatformAssemblies), new string(platformResourceRoots), new string(appPaths), acquireLock: true); } - - // BindToSystem } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 9c36b5933f52eb..02fcdf62420ea6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -836,7 +836,7 @@ internal IntPtr GetResolvedUnmanagedDll(Assembly assembly, string unmanagedDllNa } } - internal sealed class DefaultAssemblyLoadContext : AssemblyLoadContext + internal sealed partial class DefaultAssemblyLoadContext : AssemblyLoadContext { internal static readonly AssemblyLoadContext s_loadContext = new DefaultAssemblyLoadContext(); From 82ec2ac6970236872e18194d230db809f1267395 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 11:12:45 +0800 Subject: [PATCH 097/136] Resolve the gap between managed and native ALC --- .../Internal/Runtime/Binder/AssemblyName.cs | 1 + .../Tracing/ResolutionAttemptedOperation.cs | 17 +------- .../Loader/AssemblyLoadContext.Binder.cs | 30 -------------- .../AssemblyLoadContext.BinderCommon.cs | 15 +++---- .../Loader/AssemblyLoadContext.CoreCLR.cs | 16 ++++---- .../AssemblyLoadContext.CustomBinder.cs | 2 +- .../AssemblyLoadContext.DefaultBinder.cs | 40 +++++++------------ src/coreclr/vm/corelib.h | 3 -- 8 files changed, 31 insertions(+), 93 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs index e2bcc25533409c..5bb3fd57202293 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.Numerics; +using System.Runtime.Loader; namespace Internal.Runtime.Binder { diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs index cdf73610288309..580b892c2e54f7 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using System.Runtime.Loader; namespace Internal.Runtime.Binder.Tracing @@ -68,15 +67,13 @@ internal static bool IsEnabled() } // One of native bindContext or binder is expected to be non-zero. If the managed ALC is set, binder is ignored. - public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? binder, GCHandle pManagedALC, ref int hResult) + public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyLoadContext binder, ref int hResult) { _hr = ref hResult; _stage = Stage.NotYetStarted; _tracingEnabled = IsEnabled(); _assemblyNameObject = assemblyName; - Debug.Assert(binder != null || pManagedALC.IsAllocated); - if (!_tracingEnabled) return; @@ -85,17 +82,7 @@ public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyBinder? if (_assemblyNameObject != null) _assemblyName = _assemblyNameObject.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); - if (pManagedALC.IsAllocated) - { - Debug.Assert(pManagedALC.Target is AssemblyLoadContext); - // AssemblyBinder::GetNameForDiagnosticsFromManagedALC(managedALC, m_assemblyLoadContextName); - _assemblyLoadContextName = AssemblyBinder.GetNameForDiagnosticsFromManagedALC(pManagedALC); - } - else - { - Debug.Assert(binder != null); - _assemblyLoadContextName = binder.GetNameForDiagnostics(); - } + _assemblyLoadContextName = binder.ToString(); } public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index 88ca72c1a3a743..cc90267d01f60b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; -using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Internal.Runtime.Binder; @@ -31,16 +30,6 @@ internal readonly unsafe struct AssemblyNameData public partial class AssemblyLoadContext { - // fields used by VM - private GCHandle m_managedALC; - private bool m_isDefault; - - protected AssemblyBinder() - { - m_isDefault = IsDefault; - _ = GetHashCode(); // Calculate hashcode for AssemblySpecBindingCache usage - } - private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) { return BindUsingAssemblyName(new AssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); @@ -48,10 +37,6 @@ private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out Ass internal ApplicationContext AppContext { get; } = new ApplicationContext(); - // A GC handle to the managed AssemblyLoadContext. - // It is a long weak handle for collectible AssemblyLoadContexts and strong handle for non-collectible ones. - public GCHandle ManagedAssemblyLoadContext { get => m_managedALC; set => m_managedALC = value; } - // NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); // called by vm @@ -69,21 +54,6 @@ private void AddLoadedAssembly(IntPtr loadedAssembly) } } - private string GetNameForDiagnostics() => IsDefault ? "Default" : GetNameForDiagnosticsFromManagedALC(ManagedAssemblyLoadContext); - - private static string GetNameForDiagnosticsFromManagedALC(GCHandle managedALC) - { - AssemblyLoadContext? alc = managedALC.IsAllocated ? (AssemblyLoadContext?)managedALC.Target : null; - - if (alc == null || alc == GCHandle.FromIntPtr(AssemblyLoadContext.GetDefaultAssemblyBinder()).Target) - { - return "Default"; - } - - Debug.Assert(alc != null); - return alc.ToString(); - } - // static void GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ SString& alcName); //# ifdef FEATURE_READYTORUN diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index ba85a8336471a2..59f43e5356c055 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -215,7 +215,7 @@ public static int BindAssembly(AssemblyLoadContext binder, AssemblyName assembly ApplicationContext applicationContext = binder.AppContext; // Tracing happens outside the binder lock to avoid calling into managed code within the lock - using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, pManagedALC: default, ref hr); + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); Retry: lock (applicationContext.ContextCriticalSection) @@ -945,7 +945,6 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi } public static int BindUsingHostAssemblyResolver( - GCHandle pManagedAssemblyLoadContextToBindWithin, AssemblyName assemblyName, AssemblyLoadContext? defaultBinder, AssemblyLoadContext binder, @@ -955,12 +954,10 @@ public static int BindUsingHostAssemblyResolver( loadedAssembly = null; Assembly? resolvedAssembly = null; - Debug.Assert(pManagedAssemblyLoadContextToBindWithin.IsAllocated); - // body of RuntimeInvokeHostAssemblyResolver bool fResolvedAssembly = false; System.Reflection.Assembly? refLoadedAssembly = null; - using var tracer = new ResolutionAttemptedOperation(assemblyName, null, pManagedAssemblyLoadContextToBindWithin, ref hr); + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); // Allocate an AssemblyName managed object System.Reflection.AssemblyName refAssemblyName; @@ -1016,7 +1013,7 @@ public static int BindUsingHostAssemblyResolver( // This is not invoked for TPA Binder since it always returns NULL. tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextLoad); - refLoadedAssembly = AssemblyLoadContext.Resolve((IntPtr)pManagedAssemblyLoadContextToBindWithin, refAssemblyName); + refLoadedAssembly = AssemblyLoadContext.Resolve(binder, refAssemblyName); if (refLoadedAssembly != null) { fResolvedAssembly = true; @@ -1049,7 +1046,7 @@ public static int BindUsingHostAssemblyResolver( // Attempt to resolve it using the ResolveSatelliteAssembly method. tracer.GoToStage(ResolutionAttemptedOperation.Stage.ResolveSatelliteAssembly); - refLoadedAssembly = AssemblyLoadContext.ResolveSatelliteAssembly((IntPtr)pManagedAssemblyLoadContextToBindWithin, refAssemblyName); + refLoadedAssembly = AssemblyLoadContext.ResolveSatelliteAssembly(binder, refAssemblyName); if (refLoadedAssembly != null) { // Set the flag indicating we found the assembly @@ -1067,7 +1064,7 @@ public static int BindUsingHostAssemblyResolver( // attempt to resolve it using the Resolving event. tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextResolvingEvent); - refLoadedAssembly = AssemblyLoadContext.ResolveUsingResolvingEvent((IntPtr)pManagedAssemblyLoadContextToBindWithin, refAssemblyName); + refLoadedAssembly = AssemblyLoadContext.ResolveUsingResolvingEvent(binder, refAssemblyName); if (refLoadedAssembly != null) { // Set the flag indicating we found the assembly @@ -1168,7 +1165,7 @@ public static int BindUsingPEImage(AssemblyLoadContext binder, AssemblyName asse ApplicationContext applicationContext = binder.AppContext; // Tracing happens outside the binder lock to avoid calling into managed code within the lock - using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, pManagedALC: default, ref hr); + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); Retry: bool mvidMismatch = false; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 08ecf366a97811..b04258d2a1ef9e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -103,13 +103,14 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) } } #endif - - // This method is invoked by the VM to resolve a satellite assembly reference - // after trying assembly resolution via Load override without success. - internal static Assembly? ResolveSatelliteAssembly(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + internal static Assembly? Resolve(AssemblyLoadContext context, AssemblyName assemblyName) { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; + // Invoke the ResolveUsingLoad method + return context.ResolveUsingLoad(assemblyName); + } + internal static Assembly? ResolveSatelliteAssembly(AssemblyLoadContext context, AssemblyName assemblyName) + { // Invoke the ResolveSatelliteAssembly method return context.ResolveSatelliteAssembly(assemblyName); } @@ -130,11 +131,8 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass return context.GetResolvedUnmanagedDll(assembly, unmanagedDllName); } - // This method is invoked by the VM to resolve an assembly reference using the Resolving event - // after trying assembly resolution via Load override and TPA load context without success. - internal static Assembly? ResolveUsingResolvingEvent(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + internal static Assembly? ResolveUsingResolvingEvent(AssemblyLoadContext context, AssemblyName assemblyName) { - AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; // Invoke the AssemblyResolve event callbacks if wired up return context.ResolveUsingEvent(assemblyName); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index 7a6b8228a2e0d0..d1f2858d6b1c46 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -60,7 +60,7 @@ internal virtual int BindUsingAssemblyName(AssemblyName assemblyName, out Assemb // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly // that has been loaded. - hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(ManagedAssemblyLoadContext, assemblyName, Default, this, out coreCLRFoundAssembly); + hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(assemblyName, Default, this, out coreCLRFoundAssembly); if (hr >= 0) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index 8c3fa46574bc95..3e97e0e521f439 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -48,35 +48,23 @@ internal override int BindUsingAssemblyName(AssemblyName assemblyName, out Assem // // Attempt to resolve the assembly via managed ALC instance. This can either fail the bind or return reference to an existing // assembly that has been loaded - GCHandle pManagedAssemblyLoadContext = ManagedAssemblyLoadContext; - if (!pManagedAssemblyLoadContext.IsAllocated) - { - // For satellite assemblies, the managed ALC has additional resolution logic (defined by the runtime) which - // should be run even if the managed default ALC has not yet been used. (For non-satellite assemblies, any - // additional logic comes through a user-defined event handler which would have initialized the managed ALC, - // so if the managed ALC is not set yet, there is no additional logic to run) - if (!assemblyName.IsNeutralCulture) - { - // Make sure the managed default ALC is initialized. - InitializeDefaultContext(); - } - pManagedAssemblyLoadContext = ManagedAssemblyLoadContext; - Debug.Assert(pManagedAssemblyLoadContext.IsAllocated); - } + // For satellite assemblies, the managed ALC has additional resolution logic (defined by the runtime) which + // should be run even if the managed default ALC has not yet been used. (For non-satellite assemblies, any + // additional logic comes through a user-defined event handler which would have initialized the managed ALC, + // so if the managed ALC is not set yet, there is no additional logic to run) - if (pManagedAssemblyLoadContext.IsAllocated) - { - hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, assemblyName, null, this, out coreCLRFoundAssembly); + // The logic was folded from native ALC. We are the managed ALC now and no additional initialization is required. - if (hr >= 0) - { - // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. - // In such a case, we will not overwrite the binding context (which would be wrong since it would not - // be present in the cache of the current binding context). - Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder ??= this; - } + hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(assemblyName, null, this, out coreCLRFoundAssembly); + + if (hr >= 0) + { + // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. + // In such a case, we will not overwrite the binding context (which would be wrong since it would not + // be present in the cache of the current binding context). + Debug.Assert(coreCLRFoundAssembly != null); + coreCLRFoundAssembly.Binder ??= this; } } diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index df729e0af7dfd5..e6237e92a53515 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -889,11 +889,8 @@ DEFINE_FIELD_U(_id, AssemblyLoadContextBaseObject, _id) DEFINE_FIELD_U(_state, AssemblyLoadContextBaseObject, _state) DEFINE_FIELD_U(_isCollectible, AssemblyLoadContextBaseObject, _isCollectible) DEFINE_CLASS(ASSEMBLYLOADCONTEXT, Loader, AssemblyLoadContext) -DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVE, Resolve, SM_IntPtr_AssemblyName_RetAssemblyBase) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVEUNMANAGEDDLL, ResolveUnmanagedDll, SM_Str_IntPtr_RetIntPtr) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVEUNMANAGEDDLLUSINGEVENT, ResolveUnmanagedDllUsingEvent, SM_Str_AssemblyBase_IntPtr_RetIntPtr) -DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVEUSINGEVENT, ResolveUsingResolvingEvent, SM_IntPtr_AssemblyName_RetAssemblyBase) -DEFINE_METHOD(ASSEMBLYLOADCONTEXT, RESOLVESATELLITEASSEMBLY, ResolveSatelliteAssembly, SM_IntPtr_AssemblyName_RetAssemblyBase) DEFINE_FIELD(ASSEMBLYLOADCONTEXT, ASSEMBLY_LOAD, AssemblyLoad) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, ON_ASSEMBLY_LOAD, OnAssemblyLoad, SM_Assembly_RetVoid) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, ON_RESOURCE_RESOLVE, OnResourceResolve, SM_Assembly_Str_RetAssembly) From 680b6bcef21df61a41c889f8dd5af34af1100162 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 11:30:15 +0800 Subject: [PATCH 098/136] Move LoaderAllocator usage to native side --- .../src/System/Reflection/LoaderAllocator.cs | 7 +------ .../AssemblyLoadContext.BinderCommon.cs | 16 +++------------- .../AssemblyLoadContext.CustomBinder.cs | 4 ---- .../AssemblyLoadContext.DefaultBinder.cs | 4 ---- src/coreclr/vm/assemblynative.cpp | 19 ++++++++++++------- src/coreclr/vm/assemblynative.hpp | 2 +- src/coreclr/vm/loaderallocator.cpp | 11 ----------- src/coreclr/vm/loaderallocator.hpp | 1 - src/coreclr/vm/qcallentrypoints.cpp | 3 +-- 9 files changed, 18 insertions(+), 49 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs index 181d9914892617..166485dc95b88b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs @@ -44,7 +44,7 @@ internal sealed partial class LoaderAllocatorScout } } - internal sealed partial class LoaderAllocator + internal sealed class LoaderAllocator { private LoaderAllocator() { @@ -60,10 +60,5 @@ private LoaderAllocator() internal CerHashtable m_methodInstantiations; private int m_slotsUsed; #pragma warning restore CA1823, 414, 169 - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "LoaderAllocator_EnsureReference")] - internal static partial void EnsureReference(IntPtr nativeLoaderAllocator, IntPtr otherNativeLoaderAllocator); - - internal void EnsureReference(IntPtr otherNativeLA) => EnsureReference(m_scout.m_nativeLoaderAllocator, otherNativeLA); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 59f43e5356c055..62182968ed631e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -12,7 +12,6 @@ namespace System.Runtime.Loader { - internal enum CorPEKind { peNot = 0x00000000, // not a PE file @@ -46,8 +45,8 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEAssembly_GetHostAssembly")] private static partial IntPtr PEAssembly_GetHostAssembly(IntPtr pPEAssembly); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetLoaderAllocator")] - private static partial IntPtr DomainAssembly_GetLoaderAllocator(IntPtr pDomainAssembly); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_EnsureReferenceBinder")] + private static partial IntPtr DomainAssembly_EnsureReferenceBinder(IntPtr pDomainAssembly, IntPtr pBinder); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_AppIsBundle")] [return: MarshalAs(UnmanagedType.Bool)] @@ -1114,16 +1113,7 @@ public static int BindUsingHostAssemblyResolver( // alive for all its lifetime. if (rtAssembly.IsCollectible) { - IntPtr resultAssemblyLoaderAllocator = DomainAssembly_GetLoaderAllocator(pDomainAssembly); - System.Reflection.LoaderAllocator? parentLoaderAllocator = binder.GetLoaderAllocator(); - if (parentLoaderAllocator == null) - { - // The AssemblyLoadContext for which we are resolving the Assembly is not collectible. - throw new NotSupportedException(SR.NotSupported_CollectibleBoundNonCollectible); - } - - Debug.Assert(resultAssemblyLoaderAllocator != IntPtr.Zero); - parentLoaderAllocator.EnsureReference(resultAssemblyLoaderAllocator); + DomainAssembly_EnsureReferenceBinder(pDomainAssembly, binder._nativeAssemblyLoadContext); } resolvedAssembly = GCHandle.FromIntPtr(PEAssembly_GetHostAssembly(pLoadedPEAssembly)).Target as Assembly; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index d1f2858d6b1c46..f4f247831cc02d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -8,10 +8,6 @@ namespace System.Runtime.Loader { public partial class AssemblyLoadContext { - private Reflection.LoaderAllocator _loaderAllocator; - - internal virtual Reflection.LoaderAllocator? GetLoaderAllocator() => _loaderAllocator; - private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly) { // CoreLib should be bound using BindToSystem diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index 3e97e0e521f439..1f3370334cc539 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -2,16 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Runtime.InteropServices; using Internal.Runtime.Binder; namespace System.Runtime.Loader { internal partial class DefaultAssemblyLoadContext { - // Not supported by this binder - internal override Reflection.LoaderAllocator? GetLoaderAllocator() => null; - // called by vm private Assembly CreateCoreLib(IntPtr pCoreLibPEImage) => new Assembly(pCoreLibPEImage, true) { Binder = this }; diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 18fa2f0ac765bb..c4c15c719f3cc1 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1660,19 +1660,24 @@ extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * return result; } -extern "C" LoaderAllocator * QCALLTYPE DomainAssembly_GetLoaderAllocator(DomainAssembly * pDomainAssembly) +extern "C" void QCALLTYPE DomainAssembly_EnsureReferenceBinder(DomainAssembly * pDomainAssembly, AssemblyBinder * pBinder) { QCALL_CONTRACT; - - LoaderAllocator * result = NULL; - + BEGIN_QCALL; - result = pDomainAssembly->GetLoaderAllocator(); + LoaderAllocator *pResultAssemblyLoaderAllocator = pDomainAssembly->GetLoaderAllocator(); + LoaderAllocator *pParentLoaderAllocator = pBinder->GetLoaderAllocator(); + if (pParentLoaderAllocator == NULL) + { + // The AssemblyLoadContext for which we are resolving the Assembly is not collectible. + COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible")); + } + + _ASSERTE(pResultAssemblyLoaderAllocator); + pParentLoaderAllocator->EnsureReference(pResultAssemblyLoaderAllocator); END_QCALL; - - return result; } extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly) diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index c7b3ab2fd0acc6..74b324160bedc8 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -169,7 +169,7 @@ extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID); extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly); -extern "C" LoaderAllocator * QCALLTYPE DomainAssembly_GetLoaderAllocator(DomainAssembly * pDomainAssembly); +extern "C" void QCALLTYPE DomainAssembly_EnsureReferenceBinder(DomainAssembly * pDomainAssembly, AssemblyBinder * pBinder); extern "C" INT_PTR QCALLTYPE PEAssembly_GetHostAssembly(PEAssembly * pPEAssembly); diff --git a/src/coreclr/vm/loaderallocator.cpp b/src/coreclr/vm/loaderallocator.cpp index 29a343d0accc96..604aa8218b683d 100644 --- a/src/coreclr/vm/loaderallocator.cpp +++ b/src/coreclr/vm/loaderallocator.cpp @@ -253,17 +253,6 @@ BOOL LoaderAllocator::EnsureReference(LoaderAllocator *pOtherLA) return CheckAddReference_Unlocked(pOtherLA); } -extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocatorHandle pLA, QCall::LoaderAllocatorHandle pOtherLA) -{ - QCALL_CONTRACT; - - BEGIN_QCALL; - - pLA->EnsureReference(pOtherLA); - - END_QCALL; -} - BOOL LoaderAllocator::EnsureInstantiation(Module *pDefiningModule, Instantiation inst) { CONTRACTL diff --git a/src/coreclr/vm/loaderallocator.hpp b/src/coreclr/vm/loaderallocator.hpp index 3b6a4efcca01d0..365063b0b5220c 100644 --- a/src/coreclr/vm/loaderallocator.hpp +++ b/src/coreclr/vm/loaderallocator.hpp @@ -837,7 +837,6 @@ class LoaderAllocator typedef VPTR(LoaderAllocator) PTR_LoaderAllocator; extern "C" BOOL QCALLTYPE LoaderAllocator_Destroy(QCall::LoaderAllocatorHandle pLoaderAllocator); -extern "C" void QCALLTYPE LoaderAllocator_EnsureReference(QCall::LoaderAllocatorHandle pLA, QCall::LoaderAllocatorHandle pOtherLA); class GlobalLoaderAllocator : public LoaderAllocator { diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index b74f8a31896ca1..562da268089140 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -203,7 +203,7 @@ static const Entry s_QCall[] = DllImportEntry(PEImage_Release) DllImportEntry(PEImage_GetMVID) DllImportEntry(DomainAssembly_GetPEAssembly) - DllImportEntry(DomainAssembly_GetLoaderAllocator) + DllImportEntry(DomainAssembly_EnsureReferenceBinder) DllImportEntry(PEAssembly_GetHostAssembly) DllImportEntry(Bundle_AppIsBundle) DllImportEntry(Bundle_ProbeAppBundle) @@ -213,7 +213,6 @@ static const Entry s_QCall[] = DllImportEntry(MultiCoreJIT_InternalStartProfile) #endif DllImportEntry(LoaderAllocator_Destroy) - DllImportEntry(LoaderAllocator_EnsureReference) DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) DllImportEntry(ThreadNative_InformThreadNameChange) From 06866539f46c4dd26f0794a1ec067b3a094f4eaa Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 11:55:22 +0800 Subject: [PATCH 099/136] Move BindUsingHostAssemblyResolver to ALC --- .../AssemblyLoadContext.BinderCommon.cs | 275 +++++++++--------- .../Loader/AssemblyLoadContext.CoreCLR.cs | 18 -- .../AssemblyLoadContext.CustomBinder.cs | 2 +- .../AssemblyLoadContext.DefaultBinder.cs | 2 +- 4 files changed, 141 insertions(+), 156 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 62182968ed631e..c210141eb36ed9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -39,15 +39,6 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf16)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetPEAssembly")] - private static partial IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEAssembly_GetHostAssembly")] - private static partial IntPtr PEAssembly_GetHostAssembly(IntPtr pPEAssembly); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_EnsureReferenceBinder")] - private static partial IntPtr DomainAssembly_EnsureReferenceBinder(IntPtr pDomainAssembly, IntPtr pBinder); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_AppIsBundle")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool AppIsBundle(); @@ -943,7 +934,142 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi return HResults.S_FALSE; } - public static int BindUsingHostAssemblyResolver( + public static int BindUsingPEImage(AssemblyLoadContext binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) + { + int hr = HResults.S_OK; + + int kContextVersion = 0; + BindResult bindResult = default; + + // Prepare binding data + assembly = null; + ApplicationContext applicationContext = binder.AppContext; + + // Tracing happens outside the binder lock to avoid calling into managed code within the lock + using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); + + Retry: + bool mvidMismatch = false; + + // Lock the application context + lock (applicationContext.ContextCriticalSection) + { + // Attempt uncached bind and register stream if possible + // We skip version compatibility check - so assemblies with same simple name will be reported + // as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check). + hr = BindByName(applicationContext, assemblyName, true, true, excludeAppPaths, ref bindResult); + + if (hr == HResults.E_FILENOTFOUND) + { + // IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); + try + { + bindResult.SetResult(new Assembly(pPEImage, false)); + } + catch (Exception ex) + { + return ex.HResult; + } + } + else if (hr == HResults.S_OK) + { + if (bindResult.Assembly != null) + { + // Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name + // does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being + // requested. + + Guid incomingMVID; + Guid boundMVID; + + try + { + AssemblyLoadContext.PEImage_GetMVID(pPEImage, out incomingMVID); + AssemblyLoadContext.PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); + } + catch (Exception ex) + { + return ex.HResult; + } + + mvidMismatch = incomingMVID != boundMVID; + if (mvidMismatch) + { + // MVIDs do not match, so fail the load. + return HResults.COR_E_FILELOAD; + } + + // MVIDs match - request came in for the same assembly that was previously loaded. + // Let it through... + } + } + + // Remember the post-bind version of the context + kContextVersion = applicationContext.Version; + } + + if (bindResult.Assembly != null) + { + // This has to happen outside the binder lock as it can cause new binds + hr = RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult); + if (hr < 0) return hr; + + if (hr == HResults.S_FALSE) + { + // tracer.TraceBindResult(bindResult); + + // Another bind interfered. We need to retry entire bind. + // This by design loops as long as needed because by construction we eventually + // will succeed or fail the bind. + bindResult = default; + goto Retry; + } + else if (hr == HResults.S_OK) + { + assembly = hostBindResult.Assembly; + } + } + + tracer.TraceBindResult(bindResult, mvidMismatch); + return hr; + } + + // CreateDefaultBinder + + public static bool IsValidArchitecture(PEKind architecture) + { + if (architecture is PEKind.MSIL or PEKind.None) + return true; + + PEKind processArchitecture = +#if TARGET_X86 + PEKind.I386; +#elif TARGET_AMD64 + PEKind.AMD64; +#elif TARGET_ARM + PEKind.ARM; +#elif TARGET_ARM64 + PEKind.ARM64; +#else + PEKind.MSIL; +#endif + + return architecture == processArchitecture; + } + } + + public partial class AssemblyLoadContext + { + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_GetPEAssembly")] + private static partial IntPtr DomainAssembly_GetPEAssembly(IntPtr pDomainAssembly); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEAssembly_GetHostAssembly")] + private static partial IntPtr PEAssembly_GetHostAssembly(IntPtr pPEAssembly); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DomainAssembly_EnsureReferenceBinder")] + private static partial IntPtr DomainAssembly_EnsureReferenceBinder(IntPtr pDomainAssembly, IntPtr pBinder); + + internal static int BindUsingHostAssemblyResolver( AssemblyName assemblyName, AssemblyLoadContext? defaultBinder, AssemblyLoadContext binder, @@ -1012,7 +1138,7 @@ public static int BindUsingHostAssemblyResolver( // This is not invoked for TPA Binder since it always returns NULL. tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextLoad); - refLoadedAssembly = AssemblyLoadContext.Resolve(binder, refAssemblyName); + refLoadedAssembly = binder.ResolveUsingLoad(refAssemblyName); if (refLoadedAssembly != null) { fResolvedAssembly = true; @@ -1045,7 +1171,7 @@ public static int BindUsingHostAssemblyResolver( // Attempt to resolve it using the ResolveSatelliteAssembly method. tracer.GoToStage(ResolutionAttemptedOperation.Stage.ResolveSatelliteAssembly); - refLoadedAssembly = AssemblyLoadContext.ResolveSatelliteAssembly(binder, refAssemblyName); + refLoadedAssembly = binder.ResolveSatelliteAssembly(refAssemblyName); if (refLoadedAssembly != null) { // Set the flag indicating we found the assembly @@ -1063,7 +1189,7 @@ public static int BindUsingHostAssemblyResolver( // attempt to resolve it using the Resolving event. tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextResolvingEvent); - refLoadedAssembly = AssemblyLoadContext.ResolveUsingResolvingEvent(binder, refAssemblyName); + refLoadedAssembly = binder.ResolveUsingEvent(refAssemblyName); if (refLoadedAssembly != null) { // Set the flag indicating we found the assembly @@ -1142,128 +1268,5 @@ public static int BindUsingHostAssemblyResolver( return hr; } - - public static int BindUsingPEImage(AssemblyLoadContext binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) - { - int hr = HResults.S_OK; - - int kContextVersion = 0; - BindResult bindResult = default; - - // Prepare binding data - assembly = null; - ApplicationContext applicationContext = binder.AppContext; - - // Tracing happens outside the binder lock to avoid calling into managed code within the lock - using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); - - Retry: - bool mvidMismatch = false; - - // Lock the application context - lock (applicationContext.ContextCriticalSection) - { - // Attempt uncached bind and register stream if possible - // We skip version compatibility check - so assemblies with same simple name will be reported - // as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check). - hr = BindByName(applicationContext, assemblyName, true, true, excludeAppPaths, ref bindResult); - - if (hr == HResults.E_FILENOTFOUND) - { - // IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); - try - { - bindResult.SetResult(new Assembly(pPEImage, false)); - } - catch (Exception ex) - { - return ex.HResult; - } - } - else if (hr == HResults.S_OK) - { - if (bindResult.Assembly != null) - { - // Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name - // does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being - // requested. - - Guid incomingMVID; - Guid boundMVID; - - try - { - AssemblyLoadContext.PEImage_GetMVID(pPEImage, out incomingMVID); - AssemblyLoadContext.PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); - } - catch (Exception ex) - { - return ex.HResult; - } - - mvidMismatch = incomingMVID != boundMVID; - if (mvidMismatch) - { - // MVIDs do not match, so fail the load. - return HResults.COR_E_FILELOAD; - } - - // MVIDs match - request came in for the same assembly that was previously loaded. - // Let it through... - } - } - - // Remember the post-bind version of the context - kContextVersion = applicationContext.Version; - } - - if (bindResult.Assembly != null) - { - // This has to happen outside the binder lock as it can cause new binds - hr = RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult); - if (hr < 0) return hr; - - if (hr == HResults.S_FALSE) - { - // tracer.TraceBindResult(bindResult); - - // Another bind interfered. We need to retry entire bind. - // This by design loops as long as needed because by construction we eventually - // will succeed or fail the bind. - bindResult = default; - goto Retry; - } - else if (hr == HResults.S_OK) - { - assembly = hostBindResult.Assembly; - } - } - - tracer.TraceBindResult(bindResult, mvidMismatch); - return hr; - } - - // CreateDefaultBinder - - public static bool IsValidArchitecture(PEKind architecture) - { - if (architecture is PEKind.MSIL or PEKind.None) - return true; - - PEKind processArchitecture = -#if TARGET_X86 - PEKind.I386; -#elif TARGET_AMD64 - PEKind.AMD64; -#elif TARGET_ARM - PEKind.ARM; -#elif TARGET_ARM64 - PEKind.ARM64; -#else - PEKind.MSIL; -#endif - - return architecture == processArchitecture; - } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index b04258d2a1ef9e..95a0f50e109d9b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -103,18 +103,6 @@ internal Assembly LoadFromInMemoryModule(IntPtr moduleHandle) } } #endif - internal static Assembly? Resolve(AssemblyLoadContext context, AssemblyName assemblyName) - { - // Invoke the ResolveUsingLoad method - return context.ResolveUsingLoad(assemblyName); - } - - internal static Assembly? ResolveSatelliteAssembly(AssemblyLoadContext context, AssemblyName assemblyName) - { - // Invoke the ResolveSatelliteAssembly method - return context.ResolveSatelliteAssembly(assemblyName); - } - // This method is invoked by the VM when using the host-provided assembly load context // implementation. private static IntPtr ResolveUnmanagedDll(string unmanagedDllName, IntPtr gchManagedAssemblyLoadContext) @@ -131,12 +119,6 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass return context.GetResolvedUnmanagedDll(assembly, unmanagedDllName); } - internal static Assembly? ResolveUsingResolvingEvent(AssemblyLoadContext context, AssemblyName assemblyName) - { - // Invoke the AssemblyResolve event callbacks if wired up - return context.ResolveUsingEvent(assemblyName); - } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetLoadContextForAssembly")] private static partial IntPtr GetLoadContextForAssembly(QCallAssembly assembly); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index f4f247831cc02d..277291223e0fbf 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -56,7 +56,7 @@ internal virtual int BindUsingAssemblyName(AssemblyName assemblyName, out Assemb // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly // that has been loaded. - hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(assemblyName, Default, this, out coreCLRFoundAssembly); + hr = BindUsingHostAssemblyResolver(assemblyName, Default, this, out coreCLRFoundAssembly); if (hr >= 0) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index 1f3370334cc539..271af12e88c620 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -52,7 +52,7 @@ internal override int BindUsingAssemblyName(AssemblyName assemblyName, out Assem // The logic was folded from native ALC. We are the managed ALC now and no additional initialization is required. - hr = AssemblyBinderCommon.BindUsingHostAssemblyResolver(assemblyName, null, this, out coreCLRFoundAssembly); + hr = BindUsingHostAssemblyResolver(assemblyName, null, this, out coreCLRFoundAssembly); if (hr >= 0) { From 5567e6b5aa32a9f35e98e40d4e2277a3321834c2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 19:07:47 +0800 Subject: [PATCH 100/136] Move to S.R.Loader folder --- .../System.Private.CoreLib.csproj | 18 +++++++++--------- .../Runtime/Loader}/ApplicationContext.cs | 0 .../Runtime/Loader}/Assembly.cs | 0 .../Runtime/Loader}/AssemblyIdentity.cs | 0 .../Runtime/Loader}/AssemblyName.cs | 0 .../Runtime/Loader}/AssemblyVersion.cs | 0 .../Runtime/Loader}/BindResult.cs | 0 .../Runtime/Loader}/TextualIdentityParser.cs | 0 .../Tracing/ResolutionAttemptedOperation.cs | 0 9 files changed, 9 insertions(+), 9 deletions(-) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/ApplicationContext.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/Assembly.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/AssemblyIdentity.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/AssemblyName.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/AssemblyVersion.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/BindResult.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/TextualIdentityParser.cs (100%) rename src/coreclr/System.Private.CoreLib/src/{Internal/Runtime/Binder => System/Runtime/Loader}/Tracing/ResolutionAttemptedOperation.cs (100%) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 2336df2c752e91..ce0f07cff252f4 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -119,14 +119,6 @@ - - - - - - - - @@ -240,6 +232,14 @@ + + + + + + + + @@ -363,4 +363,4 @@ - + \ No newline at end of file diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/ApplicationContext.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Assembly.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyIdentity.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyName.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/AssemblyVersion.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/BindResult.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/TextualIdentityParser.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs similarity index 100% rename from src/coreclr/System.Private.CoreLib/src/Internal/Runtime/Binder/Tracing/ResolutionAttemptedOperation.cs rename to src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs From a73f5464fe9137bad5c9207b18a345b64763db90 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 19:21:09 +0800 Subject: [PATCH 101/136] Move namespace and rename. Allows usage of System.Reflection. --- .../System.Private.CoreLib.csproj | 4 +- .../Runtime/Loader/ApplicationContext.cs | 9 +-- .../src/System/Runtime/Loader/Assembly.cs | 15 ++-- .../System/Runtime/Loader/AssemblyIdentity.cs | 3 +- .../Loader/AssemblyLoadContext.Binder.cs | 10 +-- .../AssemblyLoadContext.BinderCommon.cs | 78 +++++++++---------- .../AssemblyLoadContext.CustomBinder.cs | 13 ++-- .../AssemblyLoadContext.DefaultBinder.cs | 15 ++-- .../src/System/Runtime/Loader/AssemblyName.cs | 25 +++--- .../System/Runtime/Loader/AssemblyVersion.cs | 2 +- .../src/System/Runtime/Loader/BindResult.cs | 12 ++- .../Runtime/Loader/TextualIdentityParser.cs | 6 +- .../Tracing/ResolutionAttemptedOperation.cs | 14 ++-- 13 files changed, 97 insertions(+), 109 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index ce0f07cff252f4..7f7453fb28840c 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -227,13 +227,13 @@ + + - - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs index 00276ee08052de..3f34ca0c687787 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs @@ -1,13 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { internal struct TPAEntry { @@ -17,7 +16,7 @@ internal struct TPAEntry internal record struct FailureCacheKey(string SimpleName, AssemblyVersion Version) { - public FailureCacheKey(AssemblyName assemblyName) : this(assemblyName.SimpleName, assemblyName.Version) { } + public FailureCacheKey(BinderAssemblyName assemblyName) : this(assemblyName.SimpleName, assemblyName.Version) { } } internal sealed class ApplicationContext @@ -26,7 +25,7 @@ internal sealed class ApplicationContext public int Version => _version; - public Dictionary ExecutionContext { get; } = new Dictionary(); + public Dictionary ExecutionContext { get; } = new Dictionary(); public Dictionary FailureCache { get; } = new Dictionary(); @@ -280,7 +279,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string } } - public void AddToFailureCache(AssemblyName assemblyName, int hresult) + public void AddToFailureCache(BinderAssemblyName assemblyName, int hresult) { FailureCache.Add(new FailureCacheKey(assemblyName), hresult); IncrementVersion(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs index 042be36ce0fc59..9f9dac97419d1f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs @@ -1,20 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Runtime.Loader; - -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { // BINDER_SPACE::Assembly represents a result of binding to an actual assembly (PEImage) // It is basically a tuple of 1) physical assembly and 2) binder which created/owns this binding // We also store whether it was bound using TPA list - internal sealed class Assembly + internal sealed class BinderAssembly { // fields used by VM #pragma warning disable CA1823, 414, 169 private AssemblyLoadContext? m_binder; - private AssemblyName m_assemblyName; + private BinderAssemblyName m_assemblyName; private IntPtr m_peImage; private IntPtr m_pDomainAssembly; private bool m_isInTPA; @@ -27,16 +24,16 @@ public AssemblyLoadContext? Binder set => m_binder = value; } - public AssemblyName AssemblyName => m_assemblyName; + public BinderAssemblyName AssemblyName => m_assemblyName; public IntPtr PEImage => m_peImage; public bool IsInTPA => m_isInTPA; - public Assembly(nint pPEImage, bool isInTPA) + public BinderAssembly(nint pPEImage, bool isInTPA) { // Get assembly name def from meta data import and store it for later refs access - m_assemblyName = new AssemblyName(pPEImage) + m_assemblyName = new BinderAssemblyName(pPEImage) { IsDefinition = true }; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs index e1820e680ab199..458948e9ad300a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs @@ -1,10 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Reflection; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { internal enum AssemblyIdentityFlags { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index cc90267d01f60b..00675f8da7b319 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -2,9 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using Internal.Runtime.Binder; namespace System.Runtime.Loader { @@ -23,16 +23,16 @@ internal readonly unsafe struct AssemblyNameData public readonly int RevisionNumber; public readonly PEKind ProcessorArchitecture; - public readonly System.Reflection.AssemblyContentType ContentType; + public readonly AssemblyContentType ContentType; public readonly AssemblyIdentityFlags IdentityFlags; } public partial class AssemblyLoadContext { - private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out Assembly? assembly) + private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out BinderAssembly? assembly) { - return BindUsingAssemblyName(new AssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); + return BindUsingAssemblyName(new BinderAssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); } internal ApplicationContext AppContext { get; } = new ApplicationContext(); @@ -135,7 +135,7 @@ private unsafe void DeclareLoadedAssembly(IntPtr loadedAssembly) return; } - var mdImport = new System.Reflection.MetadataImport(Assembly_GetMDImport(loadedAssembly), null); + var mdImport = new MetadataImport(Assembly_GetMDImport(loadedAssembly), null); mdImport.GetScopeProps(out Guid mvid); string simpleName = new MdUtf8String(Assembly_GetSimpleName(loadedAssembly)).ToString(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index c210141eb36ed9..faf18783658779 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -5,10 +5,10 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.IO; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using Internal.Runtime.Binder; -using Internal.Runtime.Binder.Tracing; +using System.Runtime.Loader.Tracing; namespace System.Runtime.Loader { @@ -49,7 +49,7 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_GetAppBundleBasePath")] private static partial void GetAppBundleBasePath(StringHandleOnStack path); - public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, AssemblyName foundName) + public static bool IsCompatibleAssemblyVersion(BinderAssemblyName requestedName, BinderAssemblyName foundName) { AssemblyVersion pRequestedVersion = requestedName.Version; AssemblyVersion pFoundVersion = foundName.Version; @@ -110,7 +110,7 @@ public static bool IsCompatibleAssemblyVersion(AssemblyName requestedName, Assem return true; } - public static void CreateImageAssembly(IntPtr pPEImage, ref BindResult bindResult) => bindResult.SetResult(new Assembly(pPEImage, isInTPA: false)); + public static void CreateImageAssembly(IntPtr pPEImage, ref BindResult bindResult) => bindResult.SetResult(new BinderAssembly(pPEImage, isInTPA: false)); // defined in System.Reflection.PortableExecutable.Machine, but it's in System.Reflection.Metadata // also defined in System.Reflection.ImageFileMachine @@ -196,7 +196,7 @@ public static unsafe PEKind TranslatePEToArchitectureType(int* pdwPAFlags) public const int CLR_E_BIND_TYPE_NOT_FOUND = unchecked((int)0x80132005); public const int CLR_E_BIND_ARCHITECTURE_MISMATCH = unchecked((int)0x80132006); - public static int BindAssembly(AssemblyLoadContext binder, AssemblyName assemblyName, bool excludeAppPaths, out Assembly? result) + public static int BindAssembly(AssemblyLoadContext binder, BinderAssemblyName assemblyName, bool excludeAppPaths, out BinderAssembly? result) { int kContextVersion = 0; BindResult bindResult = default; @@ -245,7 +245,7 @@ public static int BindAssembly(AssemblyLoadContext binder, AssemblyName assembly // Skipped - the managed binder can't bootstrap CoreLib // static Assembly? BindToSystem(string systemDirectory); - private static unsafe int BindToSystemSatellite(char* systemDirectory, char* simpleName, char* cultureName, out Assembly? assembly) + private static unsafe int BindToSystemSatellite(char* systemDirectory, char* simpleName, char* cultureName, out BinderAssembly? assembly) { // Satellite assembly's relative path @@ -284,7 +284,7 @@ private static unsafe int BindToSystemSatellite(char* systemDirectory, char* sim private static int BindByName( ApplicationContext applicationContext, - AssemblyName assemblyName, + BinderAssemblyName assemblyName, bool skipFailureChecking, bool skipVersionCompatibilityCheck, bool excludeAppPaths, @@ -354,13 +354,13 @@ private static int BindByName( private static int BindLocked( ApplicationContext applicationContext, - AssemblyName assemblyName, + BinderAssemblyName assemblyName, bool skipVersionCompatibilityCheck, bool excludeAppPaths, ref BindResult bindResult) { bool isTpaListProvided = applicationContext.TrustedPlatformAssemblyMap != null; - int hr = FindInExecutionContext(applicationContext, assemblyName, out Assembly? assembly); + int hr = FindInExecutionContext(applicationContext, assemblyName, out BinderAssembly? assembly); // Add the attempt to the bind result on failure / not found. On success, it will be added after the version check. if (hr < 0 || assembly == null) @@ -415,7 +415,7 @@ private static int BindLocked( return hr; } - private static int FindInExecutionContext(ApplicationContext applicationContext, AssemblyName assemblyName, out Assembly? assembly) + private static int FindInExecutionContext(ApplicationContext applicationContext, BinderAssemblyName assemblyName, out BinderAssembly? assembly) { applicationContext.ExecutionContext.TryGetValue(assemblyName, out assembly); @@ -438,7 +438,7 @@ private static int FindInExecutionContext(ApplicationContext applicationContext, // This does not do a version check. The binder applies version policy // further up the stack once it gets a successful bind. // - private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyName, AssemblyName boundAssemblyName, bool tpaListAssembly) + private static bool TestCandidateRefMatchesDef(BinderAssemblyName requestedAssemblyName, BinderAssemblyName boundAssemblyName, bool tpaListAssembly) { AssemblyNameIncludeFlags includeFlags = AssemblyNameIncludeFlags.INCLUDE_DEFAULT; @@ -458,7 +458,7 @@ private static bool TestCandidateRefMatchesDef(AssemblyName requestedAssemblyNam return boundAssemblyName.Equals(requestedAssemblyName, includeFlags); } - private static int BindSatelliteResourceFromBundle(AssemblyName requestedAssemblyName, string relativePath, ref BindResult bindResult) + private static int BindSatelliteResourceFromBundle(BinderAssemblyName requestedAssemblyName, string relativePath, ref BindResult bindResult) { int hr = HResults.S_OK; @@ -468,7 +468,7 @@ private static int BindSatelliteResourceFromBundle(AssemblyName requestedAssembl return hr; } - hr = GetAssembly(relativePath, isInTPA: false, out Assembly? assembly, bundleFileLocation); + hr = GetAssembly(relativePath, isInTPA: false, out BinderAssembly? assembly, bundleFileLocation); NativeRuntimeEventSource.Log.KnownPathProbed(relativePath, (ushort)PathSource.Bundle, hr); @@ -483,7 +483,7 @@ private static int BindSatelliteResourceFromBundle(AssemblyName requestedAssembl return hr; Debug.Assert(assembly != null); - AssemblyName boundAssemblyName = assembly.AssemblyName; + BinderAssemblyName boundAssemblyName = assembly.AssemblyName; if (TestCandidateRefMatchesDef(requestedAssemblyName, boundAssemblyName, tpaListAssembly: false)) { bindResult.SetResult(assembly); @@ -500,7 +500,7 @@ private static int BindSatelliteResourceFromBundle(AssemblyName requestedAssembl private static int BindSatelliteResourceByProbingPaths( List resourceRoots, - AssemblyName requestedAssemblyName, + BinderAssemblyName requestedAssemblyName, string relativePath, ref BindResult bindResult, PathSource pathSource) @@ -508,7 +508,7 @@ private static int BindSatelliteResourceByProbingPaths( foreach (string bindingPath in resourceRoots) { string fileName = Path.Combine(relativePath, bindingPath); - int hr = GetAssembly(fileName, isInTPA: false, out Assembly? assembly); + int hr = GetAssembly(fileName, isInTPA: false, out BinderAssembly? assembly); NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); // Missing files are okay and expected when probing @@ -518,7 +518,7 @@ private static int BindSatelliteResourceByProbingPaths( } Debug.Assert(assembly != null); - AssemblyName boundAssemblyName = assembly.AssemblyName; + BinderAssemblyName boundAssemblyName = assembly.AssemblyName; if (TestCandidateRefMatchesDef(requestedAssemblyName, boundAssemblyName, tpaListAssembly: false)) { bindResult.SetResult(assembly); @@ -537,7 +537,7 @@ private static int BindSatelliteResourceByProbingPaths( return HResults.S_OK; } - private static int BindSatelliteResource(ApplicationContext applicationContext, AssemblyName requestedAssemblyName, ref BindResult bindResult) + private static int BindSatelliteResource(ApplicationContext applicationContext, BinderAssemblyName requestedAssemblyName, ref BindResult bindResult) { Debug.Assert(!requestedAssemblyName.IsNeutralCulture); @@ -571,7 +571,7 @@ private static int BindSatelliteResource(ApplicationContext applicationContext, return hr; } - private static int BindAssemblyByProbingPaths(List bindingPaths, AssemblyName requestedAssemblyName, out Assembly? result) + private static int BindAssemblyByProbingPaths(List bindingPaths, BinderAssemblyName requestedAssemblyName, out BinderAssembly? result) { PathSource pathSource = PathSource.AppPaths; @@ -583,7 +583,7 @@ private static int BindAssemblyByProbingPaths(List bindingPaths, Assembl // Look for a matching dll first string fileName = fileNameWithoutExtension + ".dll"; - int hr = GetAssembly(fileName, isInTPA: false, out Assembly? assembly); + int hr = GetAssembly(fileName, isInTPA: false, out BinderAssembly? assembly); NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); if (hr < 0) @@ -644,7 +644,7 @@ private static int BindAssemblyByProbingPaths(List bindingPaths, Assembl * */ - public static int BindByTpaList(ApplicationContext applicationContext, AssemblyName requestedAssemblyName, bool excludeAppPaths, ref BindResult bindResult) + public static int BindByTpaList(ApplicationContext applicationContext, BinderAssemblyName requestedAssemblyName, bool excludeAppPaths, ref BindResult bindResult) { bool fPartialMatchOnTpa = false; @@ -656,7 +656,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN } else { - Assembly? tpaAssembly = null; + BinderAssembly? tpaAssembly = null; // Is assembly in the bundle? // Single-file bundle contents take precedence over TPA. @@ -744,7 +744,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN { // Probe AppPaths - int hr = BindAssemblyByProbingPaths(applicationContext.AppPaths, requestedAssemblyName, out Assembly? assembly); + int hr = BindAssemblyByProbingPaths(applicationContext.AppPaths, requestedAssemblyName, out BinderAssembly? assembly); bindResult.SetAttemptResult(hr, assembly); if (hr != HResults.E_FILENOTFOUND) @@ -790,7 +790,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, AssemblyN return HResults.S_FALSE; } - private static int GetAssembly(string assemblyPath, bool isInTPA, out Assembly? assembly, BundleFileLocation bundleFileLocation = default) + private static int GetAssembly(string assemblyPath, bool isInTPA, out BinderAssembly? assembly, BundleFileLocation bundleFileLocation = default) { int hr = BinderAcquirePEImage(assemblyPath, out IntPtr pPEImage, bundleFileLocation); @@ -831,7 +831,7 @@ or RO_E_METADATA_NAME_NOT_FOUND return hr; } - assembly = new Assembly(pPEImage, isInTPA); + assembly = new BinderAssembly(pPEImage, isInTPA); pPEImage = IntPtr.Zero; return HResults.S_OK; } @@ -857,7 +857,7 @@ public static int Register(ApplicationContext applicationContext, ref BindResult // Register the bindResult in the ExecutionContext only if we dont have it already. // This method is invoked under a lock (by its caller), so we are thread safe. - int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out Assembly? assembly); + int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out BinderAssembly? assembly); if (hr < 0) return hr; @@ -922,7 +922,7 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi // Look for already cached binding failure (ignore PA, every PA will lock the context) if (!applicationContext.FailureCache.ContainsKey(new FailureCacheKey(bindResult.Assembly.AssemblyName))) // hr == S_OK { - int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out Assembly? assembly); + int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out BinderAssembly? assembly); if (hr >= 0 && assembly != null) { // We can accept this bind in the domain @@ -934,7 +934,7 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi return HResults.S_FALSE; } - public static int BindUsingPEImage(AssemblyLoadContext binder, AssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out Assembly? assembly) + public static int BindUsingPEImage(AssemblyLoadContext binder, BinderAssemblyName assemblyName, IntPtr pPEImage, bool excludeAppPaths, out BinderAssembly? assembly) { int hr = HResults.S_OK; @@ -964,7 +964,7 @@ public static int BindUsingPEImage(AssemblyLoadContext binder, AssemblyName asse // IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); try { - bindResult.SetResult(new Assembly(pPEImage, false)); + bindResult.SetResult(new BinderAssembly(pPEImage, false)); } catch (Exception ex) { @@ -1070,22 +1070,22 @@ public partial class AssemblyLoadContext private static partial IntPtr DomainAssembly_EnsureReferenceBinder(IntPtr pDomainAssembly, IntPtr pBinder); internal static int BindUsingHostAssemblyResolver( - AssemblyName assemblyName, + BinderAssemblyName assemblyName, AssemblyLoadContext? defaultBinder, AssemblyLoadContext binder, - out Assembly? loadedAssembly) + out BinderAssembly? loadedAssembly) { int hr = HResults.E_FAIL; loadedAssembly = null; - Assembly? resolvedAssembly = null; + BinderAssembly? resolvedAssembly = null; // body of RuntimeInvokeHostAssemblyResolver bool fResolvedAssembly = false; - System.Reflection.Assembly? refLoadedAssembly = null; + Assembly? refLoadedAssembly = null; using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); // Allocate an AssemblyName managed object - System.Reflection.AssemblyName refAssemblyName; + AssemblyName refAssemblyName; // Initialize the AssemblyName object // AssemblySpec::InitializeAssemblyNameRef @@ -1102,7 +1102,7 @@ internal static int BindUsingHostAssemblyResolver( fixed (char* pCulture = culture) fixed (byte* pPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB) { - var nativeAssemblyNameParts = new System.Reflection.NativeAssemblyNameParts + var nativeAssemblyNameParts = new NativeAssemblyNameParts { _pName = pName, _pCultureName = pCulture, @@ -1125,7 +1125,7 @@ internal static int BindUsingHostAssemblyResolver( // Content type unused - refAssemblyName = new System.Reflection.AssemblyName(&nativeAssemblyNameParts); + refAssemblyName = new AssemblyName(&nativeAssemblyNameParts); } } @@ -1154,7 +1154,7 @@ internal static int BindUsingHostAssemblyResolver( // If we could not resolve the assembly using Load method, then attempt fallback with TPA Binder. // Since TPA binder cannot fallback to itself, this fallback does not happen for binds within TPA binder. - hr = defaultBinder.BindUsingAssemblyName(assemblyName, out Assembly? coreCLRFoundAssembly); + hr = defaultBinder.BindUsingAssemblyName(assemblyName, out BinderAssembly? coreCLRFoundAssembly); if (hr >= 0) { Debug.Assert(coreCLRFoundAssembly != null); @@ -1206,7 +1206,7 @@ internal static int BindUsingHostAssemblyResolver( // We were able to get the assembly loaded. Now, get its name since the host could have // performed the resolution using an assembly with different name. - System.Reflection.RuntimeAssembly? rtAssembly = + RuntimeAssembly? rtAssembly = AssemblyLoadContext.GetRuntimeAssembly(refLoadedAssembly) ?? throw new InvalidOperationException(SR.Arg_MustBeRuntimeAssembly); @@ -1242,7 +1242,7 @@ internal static int BindUsingHostAssemblyResolver( DomainAssembly_EnsureReferenceBinder(pDomainAssembly, binder._nativeAssemblyLoadContext); } - resolvedAssembly = GCHandle.FromIntPtr(PEAssembly_GetHostAssembly(pLoadedPEAssembly)).Target as Assembly; + resolvedAssembly = GCHandle.FromIntPtr(PEAssembly_GetHostAssembly(pLoadedPEAssembly)).Target as BinderAssembly; } if (fResolvedAssembly) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index 277291223e0fbf..6adc821e1a7157 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -2,13 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using Internal.Runtime.Binder; namespace System.Runtime.Loader { public partial class AssemblyLoadContext { - private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly) + private int BindAssemblyByNameWorker(BinderAssemblyName assemblyName, out BinderAssembly? coreCLRFoundAssembly) { // CoreLib should be bound using BindToSystem Debug.Assert(!assemblyName.IsCoreLib); @@ -24,10 +23,10 @@ private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? co return hr; } - internal virtual int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) + internal virtual int BindUsingAssemblyName(BinderAssemblyName assemblyName, out BinderAssembly? assembly) { int hr; - Assembly? coreCLRFoundAssembly; + BinderAssembly? coreCLRFoundAssembly; // When LoadContext needs to resolve an assembly reference, it will go through the following lookup order: // @@ -73,15 +72,15 @@ internal virtual int BindUsingAssemblyName(AssemblyName assemblyName, out Assemb return hr; } - internal virtual int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) + internal virtual int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out BinderAssembly? assembly) { assembly = null; int hr; try { - Assembly? coreCLRFoundAssembly; - AssemblyName assemblyName = new AssemblyName(pPEImage); + BinderAssembly? coreCLRFoundAssembly; + BinderAssemblyName assemblyName = new BinderAssemblyName(pPEImage); // Validate architecture if (!AssemblyBinderCommon.IsValidArchitecture(assemblyName.ProcessorArchitecture)) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index 271af12e88c620..b73f81dd305163 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -2,17 +2,16 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using Internal.Runtime.Binder; namespace System.Runtime.Loader { internal partial class DefaultAssemblyLoadContext { // called by vm - private Assembly CreateCoreLib(IntPtr pCoreLibPEImage) => new Assembly(pCoreLibPEImage, true) { Binder = this }; + private BinderAssembly CreateCoreLib(IntPtr pCoreLibPEImage) => new BinderAssembly(pCoreLibPEImage, true) { Binder = this }; // Helper functions - private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? coreCLRFoundAssembly, bool excludeAppPaths) + private int BindAssemblyByNameWorker(BinderAssemblyName assemblyName, out BinderAssembly? coreCLRFoundAssembly, bool excludeAppPaths) { // CoreLib should be bound using BindToSystem Debug.Assert(!assemblyName.IsCoreLib); @@ -28,11 +27,11 @@ private int BindAssemblyByNameWorker(AssemblyName assemblyName, out Assembly? co return hr; } - internal override int BindUsingAssemblyName(AssemblyName assemblyName, out Assembly? assembly) + internal override int BindUsingAssemblyName(BinderAssemblyName assemblyName, out BinderAssembly? assembly) { assembly = null; - int hr = BindAssemblyByNameWorker(assemblyName, out Assembly? coreCLRFoundAssembly, excludeAppPaths: false); + int hr = BindAssemblyByNameWorker(assemblyName, out BinderAssembly? coreCLRFoundAssembly, excludeAppPaths: false); if (hr is HResults.E_FILENOTFOUND or AssemblyBinderCommon.FUSION_E_APP_DOMAIN_LOCKED or HResults.FUSION_E_REF_DEF_MISMATCH) { @@ -70,15 +69,15 @@ internal override int BindUsingAssemblyName(AssemblyName assemblyName, out Assem return hr; } - internal override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out Assembly? assembly) + internal override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out BinderAssembly? assembly) { assembly = null; int hr; try { - Assembly? coreCLRFoundAssembly; - AssemblyName assemblyName = new AssemblyName(pPEImage); + BinderAssembly? coreCLRFoundAssembly; + BinderAssemblyName assemblyName = new BinderAssemblyName(pPEImage); // Validate architecture if (!AssemblyBinderCommon.IsValidArchitecture(assemblyName.ProcessorArchitecture)) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index 5bb3fd57202293..33bee27511c72d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -1,12 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Diagnostics; using System.Numerics; -using System.Runtime.Loader; +using System.Reflection; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { internal unsafe struct AssemblyMetaDataInternal { @@ -62,18 +61,18 @@ internal enum AssemblyNameIncludeFlags | INCLUDE_PUBLIC_KEY_TOKEN, } - internal sealed unsafe class AssemblyName : AssemblyIdentity, IEquatable + internal sealed unsafe class BinderAssemblyName : AssemblyIdentity, IEquatable { public bool IsDefinition; - public AssemblyName(IntPtr pPEImage) + public BinderAssemblyName(IntPtr pPEImage) { IdentityFlags |= AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE | AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL; int* dwPAFlags = stackalloc int[2]; IntPtr pIMetaDataAssemblyImport = AssemblyBinderCommon.BinderAcquireImport(pPEImage, dwPAFlags); - var scope = new System.Reflection.MetadataImport(pIMetaDataAssemblyImport, null); + var scope = new MetadataImport(pIMetaDataAssemblyImport, null); ProcessorArchitecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); @@ -126,7 +125,7 @@ public AssemblyName(IntPtr pPEImage) // Set ContentType if ((dwRefOrDefFlags & CorAssemblyFlags.afContentType_Mask) == CorAssemblyFlags.afContentType_Default) { - ContentType = System.Reflection.AssemblyContentType.Default; + ContentType = AssemblyContentType.Default; } else { @@ -152,7 +151,7 @@ public AssemblyName(IntPtr pPEImage) { if ((dwRefOrDefFlags & CorAssemblyFlags.afPublicKey) != 0) { - byte[]? publicKeyToken = System.Reflection.AssemblyNameHelpers.ComputePublicKeyToken(new ReadOnlySpan(pvPublicKeyToken, (int)dwPublicKeyToken)); + byte[]? publicKeyToken = AssemblyNameHelpers.ComputePublicKeyToken(new ReadOnlySpan(pvPublicKeyToken, (int)dwPublicKeyToken)); Debug.Assert(publicKeyToken != null); PublicKeyOrTokenBLOB = publicKeyToken; @@ -166,7 +165,7 @@ public AssemblyName(IntPtr pPEImage) } } - public unsafe AssemblyName(AssemblyNameData* data) + public unsafe BinderAssemblyName(AssemblyNameData* data) { AssemblyIdentityFlags flags = data->IdentityFlags; SimpleName = new MdUtf8String(data->Name).ToString(); @@ -184,7 +183,7 @@ public unsafe AssemblyName(AssemblyNameData* data) { // Convert public key to token - byte[]? publicKeyToken = System.Reflection.AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrTokenBLOB); + byte[]? publicKeyToken = AssemblyNameHelpers.ComputePublicKeyToken(PublicKeyOrTokenBLOB); Debug.Assert(publicKeyToken != null); PublicKeyOrTokenBLOB = publicKeyToken; @@ -312,9 +311,9 @@ static uint HashBytes(ReadOnlySpan bytes) return (int)dwHash; } - public override bool Equals(object? obj) => obj is AssemblyName other && Equals(other); + public override bool Equals(object? obj) => obj is BinderAssemblyName other && Equals(other); - public bool Equals(AssemblyName? other) => Equals(other, AssemblyNameIncludeFlags.INCLUDE_ALL); + public bool Equals(BinderAssemblyName? other) => Equals(other, AssemblyNameIncludeFlags.INCLUDE_ALL); public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFlags) { @@ -323,7 +322,7 @@ public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFl bool fEquals = false; - if (ContentType == System.Reflection.AssemblyContentType.WindowsRuntime) + if (ContentType == AssemblyContentType.WindowsRuntime) { // Assembly is meaningless for WinRT, all assemblies form one joint type namespace return ContentType == other.ContentType; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs index d860e3930d14db..55398e832dc5c4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { internal record struct AssemblyVersion { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs index f0eda0d346162b..f5737aa111c09b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs @@ -1,26 +1,24 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; - -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { internal struct BindResult { public struct AttemptResult { - public Assembly? Assembly; + public BinderAssembly? Assembly; public int HResult; public bool Attempted; } public bool IsContextBound { get; private set; } - public Assembly? Assembly { get; private set; } + public BinderAssembly? Assembly { get; private set; } private AttemptResult _inContextAttempt; private AttemptResult _applicationAssembliesResult; - public void SetAttemptResult(int hResult, Assembly? assembly, bool isInContext = false) + public void SetAttemptResult(int hResult, BinderAssembly? assembly, bool isInContext = false) { ref AttemptResult result = ref (isInContext ? ref _inContextAttempt : ref _applicationAssembliesResult); result.HResult = hResult; @@ -34,7 +32,7 @@ public void SetAttemptResult(int hResult, Assembly? assembly, bool isInContext = return result.Attempted ? result : null; } - public void SetResult(Assembly assembly, bool isInContext = false) + public void SetResult(BinderAssembly assembly, bool isInContext = false) { Assembly = assembly; IsContextBound = isInContext; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs index 2c1be6a1f086ca..f821d631b702b9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs @@ -1,11 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Diagnostics; +using System.Reflection; using System.Text; -namespace Internal.Runtime.Binder +namespace System.Runtime.Loader { internal static class TextualIdentityParser { @@ -75,7 +75,7 @@ public static string ToString(AssemblyIdentity pAssemblyIdentity, AssemblyIdenti if ((includeFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CONTENT_TYPE) != 0) { - textualIdentity.Append($", ContentType={nameof(System.Reflection.AssemblyContentType.WindowsRuntime)}"); + textualIdentity.Append($", ContentType={nameof(AssemblyContentType.WindowsRuntime)}"); } return textualIdentity.ToString(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs index 580b892c2e54f7..7bb91dae84f4c1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs @@ -1,13 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; -using System.Runtime.Loader; -namespace Internal.Runtime.Binder.Tracing +namespace System.Runtime.Loader.Tracing { // An object of this class manages firing events for all the stages during a binder resolving // attempt operation. It has minimal cost if tracing for this event is disabled. @@ -55,8 +53,8 @@ private enum Result : ushort private ref readonly int _hr; private Stage _stage; private bool _tracingEnabled; - private AssemblyName? _assemblyNameObject; - private Assembly? _foundAssembly; + private BinderAssemblyName? _assemblyNameObject; + private BinderAssembly? _foundAssembly; private string _assemblyName = string.Empty; private string _assemblyLoadContextName = string.Empty; private string? _exceptionMessage; @@ -67,7 +65,7 @@ internal static bool IsEnabled() } // One of native bindContext or binder is expected to be non-zero. If the managed ALC is set, binder is ignored. - public ResolutionAttemptedOperation(AssemblyName? assemblyName, AssemblyLoadContext binder, ref int hResult) + public ResolutionAttemptedOperation(BinderAssemblyName? assemblyName, AssemblyLoadContext binder, ref int hResult) { _hr = ref hResult; _stage = Stage.NotYetStarted; @@ -120,7 +118,7 @@ public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) } } - public void SetFoundAssembly(Assembly assembly) => _foundAssembly = assembly; + public void SetFoundAssembly(BinderAssembly assembly) => _foundAssembly = assembly; public void GoToStage(Stage stage) { @@ -161,7 +159,7 @@ public void Dispose() [MethodImpl(MethodImplOptions.InternalCall)] private static extern string PEImage_GetPath(IntPtr pPEImage); - public void TraceStage(Stage stage, int hResult, Assembly? resultAssembly, string? customError = null) + public void TraceStage(Stage stage, int hResult, BinderAssembly? resultAssembly, string? customError = null) { if (!_tracingEnabled || stage == Stage.NotYetStarted) return; From 82fe4586c62c85672b7924c3121c5f7898ac10d9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 10 Nov 2023 20:18:09 +0800 Subject: [PATCH 102/136] Remove unused QCall and accessibility change, arrange QCall --- .../Loader/AssemblyLoadContext.BinderCommon.cs | 12 +++++++++--- .../Runtime/Loader/AssemblyLoadContext.CoreCLR.cs | 11 +---------- src/coreclr/vm/assemblynative.cpp | 15 --------------- src/coreclr/vm/assemblynative.hpp | 2 -- src/coreclr/vm/qcallentrypoints.cpp | 1 - .../System/Runtime/Loader/AssemblyLoadContext.cs | 2 +- 6 files changed, 11 insertions(+), 32 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index faf18783658779..0aad0f59822912 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -39,6 +39,12 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf16)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_Release")] + internal static partial void PEImage_Release(IntPtr pPEImage); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetMVID")] + internal static partial void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_AppIsBundle")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool AppIsBundle(); @@ -844,7 +850,7 @@ or RO_E_METADATA_NAME_NOT_FOUND { // SAFE_RELEASE(pPEImage); if (pPEImage != IntPtr.Zero) - AssemblyLoadContext.PEImage_Release(pPEImage); + PEImage_Release(pPEImage); } } @@ -984,8 +990,8 @@ public static int BindUsingPEImage(AssemblyLoadContext binder, BinderAssemblyNam try { - AssemblyLoadContext.PEImage_GetMVID(pPEImage, out incomingMVID); - AssemblyLoadContext.PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); + PEImage_GetMVID(pPEImage, out incomingMVID); + PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); } catch (Exception ex) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 95a0f50e109d9b..ea014cf3e4aae0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -17,9 +17,6 @@ public partial class AssemblyLoadContext [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_PrepareForAssemblyLoadContextRelease")] private static partial void PrepareForAssemblyLoadContextRelease(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyLoadContextStrong); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetDefaultAssemblyBinder")] - internal static partial IntPtr GetDefaultAssemblyBinder(); - [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_LoadFromStream")] private static partial void LoadFromStream(IntPtr ptrNativeAssemblyBinder, IntPtr ptrAssemblyArray, int iAssemblyArrayLen, IntPtr ptrSymbols, int iSymbolArrayLen, ObjectHandleOnStack retAssembly); @@ -122,12 +119,6 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetLoadContextForAssembly")] private static partial IntPtr GetLoadContextForAssembly(QCallAssembly assembly); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_Release")] - internal static partial void PEImage_Release(IntPtr pPEImage); - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetMVID")] - internal static partial void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); - // Returns the load context in which the specified assembly has been loaded public static AssemblyLoadContext? GetLoadContext(Assembly assembly) { @@ -168,7 +159,7 @@ public void StartProfileOptimization(string? profile) InternalStartProfile(profile, _nativeAssemblyLoadContext); } - internal static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) + private static RuntimeAssembly? GetRuntimeAssembly(Assembly? asm) { return asm == null ? null : diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index c4c15c719f3cc1..a1d12986013c09 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1306,21 +1306,6 @@ extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(IN END_QCALL; } -extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder() -{ - QCALL_CONTRACT; - - INT_PTR ptrDefaultAssemblyBinder = NULL; - - BEGIN_QCALL; - - ptrDefaultAssemblyBinder = (INT_PTR)GetAppDomain()->GetDefaultBinder(); - - END_QCALL; - - return ptrDefaultAssemblyBinder; -} - /*static*/ extern "C" INT_PTR QCALLTYPE AssemblyNative_GetLoadContextForAssembly(QCall::AssemblyHandle pAssembly) { diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 74b324160bedc8..007c7f23cdf12d 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -117,8 +117,6 @@ extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PT extern "C" void QCALLTYPE AssemblyNative_PrepareForAssemblyLoadContextRelease(INT_PTR ptrNativeAssemblyBinder, INT_PTR ptrManagedStrongAssemblyLoadContext); -extern "C" INT_PTR QCALLTYPE AssemblyNative_GetDefaultAssemblyBinder(); - extern "C" void QCALLTYPE AssemblyNative_InternalLoad(NativeAssemblyNameParts* pAssemblyName, QCall::ObjectHandleOnStack requestingAssembly, QCall::StackCrawlMarkHandle stackMark,BOOL fThrowOnFileNotFound, QCall::ObjectHandleOnStack assemblyLoadContext, QCall::ObjectHandleOnStack retAssembly); extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 562da268089140..9360caed6d4723 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -184,7 +184,6 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_GetExposedObject) DllImportEntry(AssemblyNative_GetPEImage) DllImportEntry(AssemblyNative_SetSymbolBytes) - DllImportEntry(AssemblyNative_GetDefaultAssemblyBinder) DllImportEntry(AssemblyNative_LoadFromPath) DllImportEntry(AssemblyNative_LoadFromStream) #ifdef TARGET_WINDOWS diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 02fcdf62420ea6..2941d11bb36469 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -609,7 +609,7 @@ public void Dispose() #if !NATIVEAOT // This method is invoked by the VM when using the host-provided assembly load context // implementation. - internal static Assembly? Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) + private static Assembly? Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName) { AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target)!; From ce4204c3b9db29daa61b18de2fd0dd37fbb6ac01 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 14 Nov 2023 16:17:34 +0800 Subject: [PATCH 103/136] Update the structure of BindUsingHostAssemblyResolver --- .../AssemblyLoadContext.BinderCommon.cs | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 0aad0f59822912..d61847cae53586 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -1062,6 +1062,47 @@ public static bool IsValidArchitecture(PEKind architecture) return architecture == processArchitecture; } + + // AssemblySpec::InitializeAssemblyNameRef + public static unsafe AssemblyName InitializeAssemblyNameRef(BinderAssemblyName assemblyName) + { + string culture = string.Empty; + + if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) + { + culture = assemblyName.IsNeutralCulture ? string.Empty : assemblyName.CultureOrLanguage; + } + + fixed (char* pName = assemblyName.SimpleName) + fixed (char* pCulture = culture) + fixed (byte* pPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB) + { + var nativeAssemblyNameParts = new NativeAssemblyNameParts + { + _pName = pName, + _pCultureName = pCulture, + _major = (ushort)assemblyName.Version.Major, + _minor = (ushort)assemblyName.Version.Minor, + _build = (ushort)assemblyName.Version.Build, + _revision = (ushort)assemblyName.Version.Revision, + _pPublicKeyOrToken = pPublicKeyOrToken, + _cbPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB.Length, + }; + + if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0) + nativeAssemblyNameParts._flags |= System.Reflection.AssemblyNameFlags.PublicKey; + + // Architecture unused + + // Retargetable + if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE) != 0) + nativeAssemblyNameParts._flags |= System.Reflection.AssemblyNameFlags.Retargetable; + + // Content type unused + + return new AssemblyName(&nativeAssemblyNameParts); + } + } } public partial class AssemblyLoadContext @@ -1091,49 +1132,8 @@ internal static int BindUsingHostAssemblyResolver( using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); // Allocate an AssemblyName managed object - AssemblyName refAssemblyName; - // Initialize the AssemblyName object - // AssemblySpec::InitializeAssemblyNameRef - unsafe - { - string culture = string.Empty; - - if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) - { - culture = assemblyName.IsNeutralCulture ? string.Empty : assemblyName.CultureOrLanguage; - } - - fixed (char* pName = assemblyName.SimpleName) - fixed (char* pCulture = culture) - fixed (byte* pPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB) - { - var nativeAssemblyNameParts = new NativeAssemblyNameParts - { - _pName = pName, - _pCultureName = pCulture, - _major = (ushort)assemblyName.Version.Major, - _minor = (ushort)assemblyName.Version.Minor, - _build = (ushort)assemblyName.Version.Build, - _revision = (ushort)assemblyName.Version.Revision, - _pPublicKeyOrToken = pPublicKeyOrToken, - _cbPublicKeyOrToken = assemblyName.PublicKeyOrTokenBLOB.Length, - }; - - if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0) - nativeAssemblyNameParts._flags |= System.Reflection.AssemblyNameFlags.PublicKey; - - // Architecture unused - - // Retargetable - if ((assemblyName.IdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_RETARGETABLE) != 0) - nativeAssemblyNameParts._flags |= System.Reflection.AssemblyNameFlags.Retargetable; - - // Content type unused - - refAssemblyName = new AssemblyName(&nativeAssemblyNameParts); - } - } + AssemblyName refAssemblyName = AssemblyBinderCommon.InitializeAssemblyNameRef(assemblyName); bool isSatelliteAssemblyRequest = !assemblyName.IsNeutralCulture; try @@ -1208,12 +1208,13 @@ internal static int BindUsingHostAssemblyResolver( if (fResolvedAssembly && resolvedAssembly == null) { // If we are here, assembly was successfully resolved via Load or Resolving events. + Debug.Assert(refLoadedAssembly != null); // We were able to get the assembly loaded. Now, get its name since the host could have // performed the resolution using an assembly with different name. RuntimeAssembly? rtAssembly = - AssemblyLoadContext.GetRuntimeAssembly(refLoadedAssembly) + GetRuntimeAssembly(refLoadedAssembly) ?? throw new InvalidOperationException(SR.Arg_MustBeRuntimeAssembly); IntPtr pDomainAssembly = rtAssembly.GetUnderlyingNativeHandle(); From 2dc24bdc7bbf8419b4ee61345b598fcf67ae2d91 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Tue, 14 Nov 2023 22:45:42 +0800 Subject: [PATCH 104/136] Cleanup unused binder implementation --- src/coreclr/binder/CMakeLists.txt | 1 - src/coreclr/binder/assemblybindercommon.cpp | 991 +----------------- src/coreclr/binder/customassemblybinder.cpp | 133 --- src/coreclr/binder/defaultassemblybinder.cpp | 214 ---- .../binder/inc/assemblybindercommon.hpp | 62 -- src/coreclr/binder/inc/customassemblybinder.h | 9 - .../binder/inc/defaultassemblybinder.h | 22 - src/coreclr/vm/appdomain.cpp | 229 ---- src/coreclr/vm/assemblybinder.cpp | 19 - src/coreclr/vm/assemblybinder.h | 4 - src/coreclr/vm/assemblynative.cpp | 18 - 11 files changed, 2 insertions(+), 1700 deletions(-) delete mode 100644 src/coreclr/binder/defaultassemblybinder.cpp diff --git a/src/coreclr/binder/CMakeLists.txt b/src/coreclr/binder/CMakeLists.txt index f52dcb6bb44ef7..cc7965a766917d 100644 --- a/src/coreclr/binder/CMakeLists.txt +++ b/src/coreclr/binder/CMakeLists.txt @@ -9,7 +9,6 @@ set(BINDER_COMMON_SOURCES assemblybindercommon.cpp assemblyname.cpp bindertracing.cpp - defaultassemblybinder.cpp failurecache.cpp textualidentityparser.cpp utils.cpp diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 83ed302f6b3104..39f7f894dc6d42 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -26,13 +26,6 @@ #if !defined(DACCESS_COMPILE) #include "defaultassemblybinder.h" -// Helper function in the VM, invoked by the Binder, to invoke the host assembly resolver -extern HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, - BINDER_SPACE::AssemblyName *pAssemblyName, - DefaultAssemblyBinder *pDefaultBinder, - AssemblyBinder *pBinder, - BINDER_SPACE::Assembly **ppLoadedAssembly); - #endif // !defined(DACCESS_COMPILE) STDAPI BinderAcquirePEImage(LPCTSTR szAssemblyPath, @@ -188,67 +181,7 @@ namespace BINDER_SPACE Exit: return hr; } - - HRESULT AssemblyBinderCommon::BindAssembly(/* in */ AssemblyBinder *pBinder, - /* in */ AssemblyName *pAssemblyName, - /* in */ bool excludeAppPaths, - /* out */ Assembly **ppAssembly) - { - HRESULT hr = S_OK; - LONG kContextVersion = 0; - BindResult bindResult; - ApplicationContext* pApplicationContext = pBinder->GetAppContext(); - - // Tracing happens outside the binder lock to avoid calling into managed code within the lock - BinderTracing::ResolutionAttemptedOperation tracer{pAssemblyName, pBinder, 0 /*managedALC*/, hr}; - - Retry: - { - // Lock the binding application context - CRITSEC_Holder contextLock(pApplicationContext->GetCriticalSectionCookie()); - - _ASSERTE(pAssemblyName != NULL); - IF_FAIL_GO(BindByName(pApplicationContext, - pAssemblyName, - false, // skipFailureCaching - false, // skipVersionCompatibilityCheck - excludeAppPaths, - &bindResult)); - - // Remember the post-bind version - kContextVersion = pApplicationContext->GetVersion(); - - } // lock(pApplicationContext) - - Exit: - tracer.TraceBindResult(bindResult); - - if (bindResult.HaveResult()) - { - BindResult hostBindResult; - - hr = RegisterAndGetHostChosen(pApplicationContext, - kContextVersion, - &bindResult, - &hostBindResult); - - if (hr == S_FALSE) - { - // Another bind interfered. We need to retry the entire bind. - // This by design loops as long as needed because by construction we eventually - // will succeed or fail the bind. - bindResult.Reset(); - goto Retry; - } - else if (hr == S_OK) - { - *ppAssembly = hostBindResult.GetAssembly(TRUE /* fAddRef */); - } - } - - return hr; - } - + \ /* static */ HRESULT AssemblyBinderCommon::BindToSystem(SString &systemDirectory, PEImage **ppPEImage) @@ -328,233 +261,7 @@ namespace BINDER_SPACE Exit: return hr; } - - - /* static */ - HRESULT AssemblyBinderCommon::BindToSystemSatellite(SString& systemDirectory, - SString& simpleName, - SString& cultureName, - Assembly** ppSystemAssembly) - { - HRESULT hr = S_OK; - - _ASSERTE(ppSystemAssembly != NULL); - - // Satellite assembly's relative path - StackSString relativePath; - - // append culture name - if (!cultureName.IsEmpty()) - { - CombinePath(relativePath, cultureName, relativePath); - } - - // append satellite assembly's simple name - CombinePath(relativePath, simpleName, relativePath); - - // append extension - relativePath.Append(W(".dll")); - - // Satellite assembly's path: - // * Absolute path when looking for a file on disk - // * Bundle-relative path when looking within the single-file bundle. - StackSString sCoreLibSatellite; - - BinderTracing::PathSource pathSource = BinderTracing::PathSource::Bundle; - BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /*pathIsBundleRelative */ true); - if (!bundleFileLocation.IsValid()) - { - sCoreLibSatellite.Set(systemDirectory); - pathSource = BinderTracing::PathSource::ApplicationAssemblies; - } - CombinePath(sCoreLibSatellite, relativePath, sCoreLibSatellite); - - ReleaseHolder pSystemAssembly; - IF_FAIL_GO(AssemblyBinderCommon::GetAssembly(sCoreLibSatellite, - TRUE /* fIsInTPA */, - &pSystemAssembly, - bundleFileLocation)); - BinderTracing::PathProbed(sCoreLibSatellite, pathSource, hr); - - *ppSystemAssembly = pSystemAssembly.Extract(); - - Exit: - return hr; - } - - /* static */ - HRESULT AssemblyBinderCommon::BindByName(ApplicationContext *pApplicationContext, - AssemblyName *pAssemblyName, - bool skipFailureCaching, - bool skipVersionCompatibilityCheck, - bool excludeAppPaths, - BindResult *pBindResult) - { - HRESULT hr = S_OK; - PathString assemblyDisplayName; - - // Look for already cached binding failure (ignore PA, every PA will lock the context) - pAssemblyName->GetDisplayName(assemblyDisplayName, - AssemblyName::INCLUDE_VERSION); - - hr = pApplicationContext->GetFailureCache()->Lookup(assemblyDisplayName); - if (FAILED(hr)) - { - if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) && skipFailureCaching) - { - // Ignore pre-existing transient bind error (re-bind will succeed) - pApplicationContext->GetFailureCache()->Remove(assemblyDisplayName); - } - - goto LogExit; - } - else if (hr == S_FALSE) - { - // workaround: Special case for byte arrays. Rerun the bind to create binding log. - pAssemblyName->SetIsDefinition(TRUE); - hr = S_OK; - } - - if (!IsValidArchitecture(pAssemblyName->GetArchitecture())) - { - // Assembly reference contains wrong architecture - IF_FAIL_GO(FUSION_E_INVALID_NAME); - } - - IF_FAIL_GO(BindLocked(pApplicationContext, - pAssemblyName, - skipVersionCompatibilityCheck, - excludeAppPaths, - pBindResult)); - - if (!pBindResult->HaveResult()) - { - // Behavior rules are clueless now - IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); - } - - Exit: - if (FAILED(hr)) - { - if (skipFailureCaching) - { - if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - // Cache non-transient bind error for byte-array - hr = S_FALSE; - } - else - { - // Ignore transient bind error (re-bind will succeed) - goto LogExit; - } - } - - hr = pApplicationContext->AddToFailureCache(assemblyDisplayName, hr); - } - - LogExit: - return hr; - } - - /* static */ - HRESULT AssemblyBinderCommon::BindLocked(ApplicationContext *pApplicationContext, - AssemblyName *pAssemblyName, - bool skipVersionCompatibilityCheck, - bool excludeAppPaths, - BindResult *pBindResult) - { - HRESULT hr = S_OK; - - bool isTpaListProvided = pApplicationContext->IsTpaListProvided(); - Assembly *pAssembly = NULL; - hr = FindInExecutionContext(pApplicationContext, pAssemblyName, &pAssembly); - - // Add the attempt to the bind result on failure / not found. On success, it will be added after the version check. - if (FAILED(hr) || pAssembly == NULL) - pBindResult->SetAttemptResult(hr, pAssembly, /*isInContext*/ true); - - IF_FAIL_GO(hr); - if (pAssembly != NULL) - { - if (!skipVersionCompatibilityCheck) - { - // Can't give higher version than already bound - bool isCompatible = IsCompatibleAssemblyVersion(pAssemblyName, pAssembly->GetAssemblyName()); - hr = isCompatible ? S_OK : FUSION_E_APP_DOMAIN_LOCKED; - pBindResult->SetAttemptResult(hr, pAssembly, /*isInContext*/ true); - - // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version - if (hr == FUSION_E_APP_DOMAIN_LOCKED && isTpaListProvided) - hr = FUSION_E_REF_DEF_MISMATCH; - } - else - { - pBindResult->SetAttemptResult(hr, pAssembly, /*isInContext*/ true); - } - - IF_FAIL_GO(hr); - - pBindResult->SetResult(pAssembly, /*isInContext*/ true); - } - else - if (isTpaListProvided) - { - // BindByTpaList handles setting attempt results on the bind result - hr = BindByTpaList(pApplicationContext, - pAssemblyName, - excludeAppPaths, - pBindResult); - if (SUCCEEDED(hr) && pBindResult->HaveResult()) - { - bool isCompatible = IsCompatibleAssemblyVersion(pAssemblyName, pBindResult->GetAssemblyName()); - hr = isCompatible ? S_OK : FUSION_E_APP_DOMAIN_LOCKED; - pBindResult->SetAttemptResult(hr, pBindResult->GetAssembly()); - - // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version - if (hr == FUSION_E_APP_DOMAIN_LOCKED && isTpaListProvided) - hr = FUSION_E_REF_DEF_MISMATCH; - } - - if (FAILED(hr)) - { - pBindResult->SetNoResult(); - } - IF_FAIL_GO(hr); - } - Exit: - return hr; - } - - /* static */ - HRESULT AssemblyBinderCommon::FindInExecutionContext(ApplicationContext *pApplicationContext, - AssemblyName *pAssemblyName, - Assembly **ppAssembly) - { - _ASSERTE(pApplicationContext != NULL); - _ASSERTE(pAssemblyName != NULL); - _ASSERTE(ppAssembly != NULL); - - ExecutionContext *pExecutionContext = pApplicationContext->GetExecutionContext(); - Assembly *pAssembly = pExecutionContext->Lookup(pAssemblyName); - - // Set any found context entry. It is up to the caller to check the returned HRESULT - // for errors due to validation - *ppAssembly = pAssembly; - if (pAssembly == NULL) - return S_FALSE; - - AssemblyName *pContextName = pAssembly->GetAssemblyName(); - if (pAssemblyName->GetIsDefinition() && - (pContextName->GetArchitecture() != pAssemblyName->GetArchitecture())) - { - return FUSION_E_APP_DOMAIN_LOCKED; - } - - return S_OK; - } - - + // // Tests whether a candidate assembly's name matches the requested. // This does not do a version check. The binder applies version policy @@ -582,701 +289,7 @@ namespace BINDER_SPACE return pBoundAssemblyName->Equals(pRequestedAssemblyName, dwIncludeFlags); } - namespace - { - HRESULT BindSatelliteResourceFromBundle( - AssemblyName* pRequestedAssemblyName, - SString &relativePath, - BindResult* pBindResult) - { - HRESULT hr = S_OK; - - BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(relativePath, /* pathIsBundleRelative */ true); - if (!bundleFileLocation.IsValid()) - { - return hr; - } - - ReleaseHolder pAssembly; - hr = AssemblyBinderCommon::GetAssembly(relativePath, - FALSE /* fIsInTPA */, - &pAssembly, - bundleFileLocation); - - BinderTracing::PathProbed(relativePath, BinderTracing::PathSource::Bundle, hr); - - // Missing files are okay and expected when probing - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - return S_OK; - } - - pBindResult->SetAttemptResult(hr, pAssembly); - if (FAILED(hr)) - return hr; - - AssemblyName* pBoundAssemblyName = pAssembly->GetAssemblyName(); - if (TestCandidateRefMatchesDef(pRequestedAssemblyName, pBoundAssemblyName, false /*tpaListAssembly*/)) - { - pBindResult->SetResult(pAssembly); - hr = S_OK; - } - else - { - hr = FUSION_E_REF_DEF_MISMATCH; - } - - pBindResult->SetAttemptResult(hr, pAssembly); - return hr; - } - - HRESULT BindSatelliteResourceByProbingPaths( - const StringArrayList *pResourceRoots, - AssemblyName *pRequestedAssemblyName, - SString &relativePath, - BindResult *pBindResult, - BinderTracing::PathSource pathSource) - { - HRESULT hr = S_OK; - - for (UINT i = 0; i < pResourceRoots->GetCount(); i++) - { - ReleaseHolder pAssembly; - SString &wszBindingPath = (*pResourceRoots)[i]; - SString fileName(wszBindingPath); - CombinePath(fileName, relativePath, fileName); - - hr = AssemblyBinderCommon::GetAssembly(fileName, - FALSE /* fIsInTPA */, - &pAssembly); - BinderTracing::PathProbed(fileName, pathSource, hr); - - // Missing files are okay and expected when probing - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - continue; - } - - pBindResult->SetAttemptResult(hr, pAssembly); - if (FAILED(hr)) - return hr; - - AssemblyName *pBoundAssemblyName = pAssembly->GetAssemblyName(); - if (TestCandidateRefMatchesDef(pRequestedAssemblyName, pBoundAssemblyName, false /*tpaListAssembly*/)) - { - pBindResult->SetResult(pAssembly); - hr = S_OK; - } - else - { - hr = FUSION_E_REF_DEF_MISMATCH; - } - - pBindResult->SetAttemptResult(hr, pAssembly); - return hr; - } - - // Up-stack expects S_OK when we don't find any candidate assemblies and no fatal error occurred (ie, no S_FALSE) - return S_OK; - } - - HRESULT BindSatelliteResource( - ApplicationContext* pApplicationContext, - AssemblyName* pRequestedAssemblyName, - BindResult* pBindResult) - { - // Satellite resource probing strategy is to look: - // * First within the single-file bundle - // * Then under each of the Platform Resource Roots - // * Then under each of the App Paths. - // - // During each search, if we find a platform resource file with matching file name, but whose ref-def didn't match, - // fall back to application resource lookup to handle case where a user creates resources with the same - // names as platform ones. - - HRESULT hr = S_OK; - const SString& simpleNameRef = pRequestedAssemblyName->GetSimpleName(); - SString& cultureRef = pRequestedAssemblyName->GetCulture(); - - _ASSERTE(!pRequestedAssemblyName->IsNeutralCulture()); - - ReleaseHolder pAssembly; - SString fileName; - CombinePath(fileName, cultureRef, fileName); - CombinePath(fileName, simpleNameRef, fileName); - fileName.Append(W(".dll")); - - hr = BindSatelliteResourceFromBundle(pRequestedAssemblyName, fileName, pBindResult); - - if (pBindResult->HaveResult() || FAILED(hr)) - { - return hr; - } - - hr = BindSatelliteResourceByProbingPaths(pApplicationContext->GetPlatformResourceRoots(), - pRequestedAssemblyName, - fileName, - pBindResult, - BinderTracing::PathSource::PlatformResourceRoots); - - if (pBindResult->HaveResult() || FAILED(hr)) - { - return hr; - } - - hr = BindSatelliteResourceByProbingPaths(pApplicationContext->GetAppPaths(), - pRequestedAssemblyName, - fileName, - pBindResult, - BinderTracing::PathSource::AppPaths); - - return hr; - } - - HRESULT BindAssemblyByProbingPaths( - const StringArrayList *pBindingPaths, - AssemblyName *pRequestedAssemblyName, - Assembly **ppAssembly) - { - const SString &simpleName = pRequestedAssemblyName->GetSimpleName(); - BinderTracing::PathSource pathSource = BinderTracing::PathSource::AppPaths; - // Loop through the binding paths looking for a matching assembly - for (DWORD i = 0; i < pBindingPaths->GetCount(); i++) - { - HRESULT hr; - ReleaseHolder pAssembly; - LPCWSTR wszBindingPath = (*pBindingPaths)[i]; - - PathString fileNameWithoutExtension(wszBindingPath); - CombinePath(fileNameWithoutExtension, simpleName, fileNameWithoutExtension); - - // Look for a matching dll first - PathString fileName(fileNameWithoutExtension); - fileName.Append(W(".dll")); - hr = AssemblyBinderCommon::GetAssembly(fileName, - FALSE, // fIsInTPA - &pAssembly); - BinderTracing::PathProbed(fileName, pathSource, hr); - - if (FAILED(hr)) - { - fileName.Set(fileNameWithoutExtension); - fileName.Append(W(".exe")); - hr = AssemblyBinderCommon::GetAssembly(fileName, - FALSE, // fIsInTPA - &pAssembly); - BinderTracing::PathProbed(fileName, pathSource, hr); - } - - // Since we're probing, file not founds are ok and we should just try another - // probing path - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - continue; - } - - // Set any found assembly. It is up to the caller to check the returned HRESULT for errors due to validation - *ppAssembly = pAssembly.Extract(); - if (FAILED(hr)) - return hr; - - // We found a candidate. - // - // Below this point, we either establish that the ref-def matches, or - // we fail the bind. - - // Compare requested AssemblyName with that from the candidate assembly - if (!TestCandidateRefMatchesDef(pRequestedAssemblyName, pAssembly->GetAssemblyName(), false /*tpaListAssembly*/)) - return FUSION_E_REF_DEF_MISMATCH; - - return S_OK; - } - - return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - } - - /* - * BindByTpaList is the entry-point for the custom binding algorithm in CoreCLR. - * - * The search for assemblies will proceed in the following order: - * - * If this application is a single-file bundle, the meta-data contained in the bundle - * will be probed to find the requested assembly. If the assembly is not found, - * The list of platform assemblies (TPAs) are considered next. - * - * Platform assemblies are specified as a list of files. This list is the only set of - * assemblies that we will load as platform. They can be specified as IL or NIs. - * - * Resources for platform assemblies are located by probing starting at the Platform Resource Roots, - * a set of folders configured by the host. - * - * If a requested assembly identity cannot be found in the TPA list or the resource roots, - * it is considered an application assembly. We probe for application assemblies in the - * AppPaths, a list of paths containing IL files and satellite resource folders. - * - */ - /* static */ - HRESULT AssemblyBinderCommon::BindByTpaList(ApplicationContext *pApplicationContext, - AssemblyName *pRequestedAssemblyName, - bool excludeAppPaths, - BindResult *pBindResult) - { - HRESULT hr = S_OK; - - bool fPartialMatchOnTpa = false; - - if (!pRequestedAssemblyName->IsNeutralCulture()) - { - IF_FAIL_GO(BindSatelliteResource(pApplicationContext, pRequestedAssemblyName, pBindResult)); - } - else - { - ReleaseHolder pTPAAssembly; - const SString& simpleName = pRequestedAssemblyName->GetSimpleName(); - - // Is assembly in the bundle? - // Single-file bundle contents take precedence over TPA. - // The list of bundled assemblies is contained in the bundle manifest, and NOT in the TPA. - // Therefore the bundle is first probed using the assembly's simple name. - // If found, the assembly is loaded from the bundle. - if (Bundle::AppIsBundle()) - { - // Search Assembly.ni.dll, then Assembly.dll - // The Assembly.ni.dll paths are rare, and intended for supporting managed C++ R2R assemblies. - const WCHAR* const candidates[] = { W(".ni.dll"), W(".dll") }; - - // Loop through the binding paths looking for a matching assembly - for (int i = 0; i < 2; i++) - { - SString assemblyFileName(simpleName); - assemblyFileName.Append(candidates[i]); - - SString assemblyFilePath(Bundle::AppBundle->BasePath()); - assemblyFilePath.Append(assemblyFileName); - - BundleFileLocation bundleFileLocation = Bundle::ProbeAppBundle(assemblyFileName, /* pathIsBundleRelative */ true); - if (bundleFileLocation.IsValid()) - { - hr = GetAssembly(assemblyFilePath, - TRUE, // fIsInTPA - &pTPAAssembly, - bundleFileLocation); - - BinderTracing::PathProbed(assemblyFilePath, BinderTracing::PathSource::Bundle, hr); - - if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - // Any other error is fatal - IF_FAIL_GO(hr); - - if (TestCandidateRefMatchesDef(pRequestedAssemblyName, pTPAAssembly->GetAssemblyName(), true /*tpaListAssembly*/)) - { - // We have found the requested assembly match in the bundle with validation of the full-qualified name. - // Bind to it. - pBindResult->SetResult(pTPAAssembly); - GO_WITH_HRESULT(S_OK); - } - } - } - } - } - - // Is assembly on TPA list? - SimpleNameToFileNameMap * tpaMap = pApplicationContext->GetTpaList(); - const SimpleNameToFileNameMapEntry *pTpaEntry = tpaMap->LookupPtr(simpleName.GetUnicode()); - if (pTpaEntry != nullptr) - { - if (pTpaEntry->m_wszNIFileName != nullptr) - { - SString fileName(pTpaEntry->m_wszNIFileName); - - hr = GetAssembly(fileName, - TRUE, // fIsInTPA - &pTPAAssembly); - BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); - } - else - { - _ASSERTE(pTpaEntry->m_wszILFileName != nullptr); - SString fileName(pTpaEntry->m_wszILFileName); - - hr = GetAssembly(fileName, - TRUE, // fIsInTPA - &pTPAAssembly); - BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); - } - - pBindResult->SetAttemptResult(hr, pTPAAssembly); - - // On file not found, simply fall back to app path probing - if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - // Any other error is fatal - IF_FAIL_GO(hr); - - if (TestCandidateRefMatchesDef(pRequestedAssemblyName, pTPAAssembly->GetAssemblyName(), true /*tpaListAssembly*/)) - { - // We have found the requested assembly match on TPA with validation of the full-qualified name. Bind to it. - pBindResult->SetResult(pTPAAssembly); - pBindResult->SetAttemptResult(S_OK, pTPAAssembly); - GO_WITH_HRESULT(S_OK); - } - else - { - // We found the assembly on TPA but it didn't match the RequestedAssembly assembly-name. In this case, lets proceed to see if we find the requested - // assembly in the App paths. - pBindResult->SetAttemptResult(FUSION_E_REF_DEF_MISMATCH, pTPAAssembly); - fPartialMatchOnTpa = true; - } - } - - // We either didn't find a candidate, or the ref-def failed. Either way; fall back to app path probing. - } - - if (!excludeAppPaths) - { - // Probe AppPaths - ReleaseHolder pAssembly; - hr = BindAssemblyByProbingPaths(pApplicationContext->GetAppPaths(), - pRequestedAssemblyName, - &pAssembly); - - pBindResult->SetAttemptResult(hr, pAssembly); - if (hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - IF_FAIL_GO(hr); - - // At this point, we have found an assembly with the expected name in the App paths. If this was also found on TPA, - // make sure that the app assembly has the same fullname (excluding version) as the TPA version. If it does, then - // we should bind to the TPA assembly. If it does not, then bind to the app assembly since it has a different fullname than the - // TPA assembly. - if (fPartialMatchOnTpa) - { - if (TestCandidateRefMatchesDef(pAssembly->GetAssemblyName(), pTPAAssembly->GetAssemblyName(), true /*tpaListAssembly*/)) - { - // Fullname (SimpleName+Culture+PKT) matched for TPA and app assembly - so bind to TPA instance. - pBindResult->SetResult(pTPAAssembly); - pBindResult->SetAttemptResult(hr, pTPAAssembly); - GO_WITH_HRESULT(S_OK); - } - else - { - // Fullname (SimpleName+Culture+PKT) did not match for TPA and app assembly - so bind to app instance. - pBindResult->SetResult(pAssembly); - GO_WITH_HRESULT(S_OK); - } - } - else - { - // We didn't see this assembly on TPA - so simply bind to the app instance. - pBindResult->SetResult(pAssembly); - GO_WITH_HRESULT(S_OK); - } - } - } - } - - // Couldn't find a matching assembly in any of the probing paths - // Return S_FALSE here. BindByName will interpret a successful HRESULT - // and lack of BindResult as a failure to find a matching assembly. - hr = S_FALSE; - - Exit: - return hr; - } - - /* static */ - HRESULT AssemblyBinderCommon::GetAssembly(SString &assemblyPath, - BOOL fIsInTPA, - Assembly **ppAssembly, - BundleFileLocation bundleFileLocation) - { - HRESULT hr = S_OK; - - _ASSERTE(ppAssembly != NULL); - - ReleaseHolder pAssembly; - PEImage *pPEImage = NULL; - - // Allocate assembly object - SAFE_NEW(pAssembly, Assembly); - - // Obtain assembly meta data - { - LPCTSTR szAssemblyPath = const_cast(assemblyPath.GetUnicode()); - - hr = BinderAcquirePEImage(szAssemblyPath, &pPEImage, bundleFileLocation); - IF_FAIL_GO(hr); - } - - // Initialize assembly object - IF_FAIL_GO(pAssembly->Init(pPEImage, fIsInTPA)); - - // We're done - *ppAssembly = pAssembly.Extract(); - - Exit: - - SAFE_RELEASE(pPEImage); - - // Normalize file not found - if ((FAILED(hr)) && IsFileNotFound(hr)) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - - return hr; - } - - - /* static */ - HRESULT AssemblyBinderCommon::Register(ApplicationContext *pApplicationContext, - BindResult *pBindResult) - { - _ASSERTE(!pBindResult->GetIsContextBound()); - - pApplicationContext->IncrementVersion(); - - // Register the bindResult in the ExecutionContext only if we dont have it already. - // This method is invoked under a lock (by its caller), so we are thread safe. - Assembly *pAssembly = NULL; - HRESULT hr = FindInExecutionContext(pApplicationContext, pBindResult->GetAssemblyName(), &pAssembly); - if (FAILED(hr)) - return hr; - - if (pAssembly == NULL) - { - ExecutionContext *pExecutionContext = pApplicationContext->GetExecutionContext(); - pExecutionContext->Add(pBindResult->GetAssembly(/*fAddRef*/ TRUE)); - } - else - { - // Update the BindResult with the assembly we found - pBindResult->SetResult(pAssembly, /*isContextBound*/ true); - } - - return S_OK; - } - - /* static */ - HRESULT AssemblyBinderCommon::RegisterAndGetHostChosen(ApplicationContext *pApplicationContext, - LONG kContextVersion, - BindResult *pBindResult, - BindResult *pHostBindResult) - { - HRESULT hr = S_OK; - - _ASSERTE(pBindResult != NULL); - _ASSERTE(pBindResult->HaveResult()); - _ASSERTE(pHostBindResult != NULL); - - if (!pBindResult->GetIsContextBound()) - { - pHostBindResult->SetResult(pBindResult); - - { - // Lock the application context - CRITSEC_Holder contextLock(pApplicationContext->GetCriticalSectionCookie()); - - // Only perform costly validation if other binds succeeded before us - if (kContextVersion != pApplicationContext->GetVersion()) - { - IF_FAIL_GO(AssemblyBinderCommon::OtherBindInterfered(pApplicationContext, - pBindResult)); - - if (hr == S_FALSE) - { - // Another bind interfered - GO_WITH_HRESULT(hr); - } - } - - // No bind interfered, we can now register - IF_FAIL_GO(Register(pApplicationContext, - pHostBindResult)); - } - } - else - { - // No work required. Return the input - pHostBindResult->SetResult(pBindResult); - } - - Exit: - return hr; - } - - /* static */ - HRESULT AssemblyBinderCommon::OtherBindInterfered(ApplicationContext *pApplicationContext, - BindResult *pBindResult) - { - HRESULT hr = S_FALSE; - AssemblyName *pAssemblyName = pBindResult->GetAssemblyName(); - PathString assemblyDisplayName; - - _ASSERTE(pAssemblyName != NULL); - - // Look for already cached binding failure (ignore PA, every PA will lock the context) - pAssemblyName->GetDisplayName(assemblyDisplayName, AssemblyName::INCLUDE_VERSION); - hr = pApplicationContext->GetFailureCache()->Lookup(assemblyDisplayName); - - if (hr == S_OK) - { - Assembly *pAssembly = NULL; - hr = FindInExecutionContext(pApplicationContext, pAssemblyName, &pAssembly); - if (SUCCEEDED(hr) && (pAssembly == NULL)) - { - // We can accept this bind in the domain - GO_WITH_HRESULT(S_OK); - } - } - - // Some other bind interfered - GO_WITH_HRESULT(S_FALSE); - - Exit: - return hr; - } - - #if !defined(DACCESS_COMPILE) -HRESULT AssemblyBinderCommon::BindUsingHostAssemblyResolver(/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin, - /* in */ AssemblyName *pAssemblyName, - /* in */ DefaultAssemblyBinder *pDefaultBinder, - /* in */ AssemblyBinder *pBinder, - /* out */ Assembly **ppAssembly) -{ - HRESULT hr = E_FAIL; - - _ASSERTE(pManagedAssemblyLoadContextToBindWithin != NULL); - - // RuntimeInvokeHostAssemblyResolver will perform steps 2-4 of CustomAssemblyBinder::BindAssemblyByName. - BINDER_SPACE::Assembly *pLoadedAssembly = NULL; - hr = RuntimeInvokeHostAssemblyResolver(pManagedAssemblyLoadContextToBindWithin, - pAssemblyName, pDefaultBinder, pBinder, &pLoadedAssembly); - if (SUCCEEDED(hr)) - { - _ASSERTE(pLoadedAssembly != NULL); - *ppAssembly = pLoadedAssembly; - } - - return hr; -} - -/* static */ -HRESULT AssemblyBinderCommon::BindUsingPEImage(/* in */ AssemblyBinder* pBinder, - /* in */ BINDER_SPACE::AssemblyName *pAssemblyName, - /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, - /* [retval] [out] */ Assembly **ppAssembly) -{ - HRESULT hr = E_FAIL; - - LONG kContextVersion = 0; - BindResult bindResult; - - // Prepare binding data - *ppAssembly = NULL; - ApplicationContext* pApplicationContext = pBinder->GetAppContext(); - - // Tracing happens outside the binder lock to avoid calling into managed code within the lock - BinderTracing::ResolutionAttemptedOperation tracer{pAssemblyName, pBinder, 0 /*managedALC*/, hr}; - - // Attempt the actual bind (eventually more than once) -Retry: - bool mvidMismatch = false; - { - // Lock the application context - CRITSEC_Holder contextLock(pApplicationContext->GetCriticalSectionCookie()); - - // Attempt uncached bind and register stream if possible - // We skip version compatibility check - so assemblies with same simple name will be reported - // as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check). - hr = BindByName(pApplicationContext, - pAssemblyName, - true, // skipFailureCaching - true, // skipVersionCompatibilityCheck - excludeAppPaths, // excludeAppPaths - &bindResult); - - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); - } - else if (hr == S_OK) - { - if (bindResult.HaveResult()) - { - // Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name - // does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being - // requested. - - GUID incomingMVID; - GUID boundMVID; - - // GetMVID can throw exception - EX_TRY - { - pPEImage->GetMVID(&incomingMVID); - bindResult.GetAssembly()->GetPEImage()->GetMVID(&boundMVID); - } - EX_CATCH - { - hr = GET_EXCEPTION()->GetHR(); - goto Exit; - } - EX_END_CATCH(SwallowAllExceptions); - - - mvidMismatch = incomingMVID != boundMVID; - if (mvidMismatch) - { - // MVIDs do not match, so fail the load. - IF_FAIL_GO(COR_E_FILELOAD); - } - - // MVIDs match - request came in for the same assembly that was previously loaded. - // Let it through... - } - } - - // Remember the post-bind version of the context - kContextVersion = pApplicationContext->GetVersion(); - - } // lock(pApplicationContext) - - if (bindResult.HaveResult()) - { - BindResult hostBindResult; - - // This has to happen outside the binder lock as it can cause new binds - IF_FAIL_GO(RegisterAndGetHostChosen(pApplicationContext, - kContextVersion, - &bindResult, - &hostBindResult)); - - if (hr == S_FALSE) - { - tracer.TraceBindResult(bindResult); - - // Another bind interfered. We need to retry entire bind. - // This by design loops as long as needed because by construction we eventually - // will succeed or fail the bind. - bindResult.Reset(); - goto Retry; - } - else if (hr == S_OK) - { - *ppAssembly = hostBindResult.GetAssembly(TRUE /* fAddRef */); - } - } - -Exit: - tracer.TraceBindResult(bindResult, mvidMismatch); - return hr; -} - HRESULT AssemblyBinderCommon::CreateDefaultBinder(DefaultAssemblyBinder** ppDefaultBinder) { HRESULT hr = S_OK; diff --git a/src/coreclr/binder/customassemblybinder.cpp b/src/coreclr/binder/customassemblybinder.cpp index ac1cf61bcf6a2e..053c0af98e121b 100644 --- a/src/coreclr/binder/customassemblybinder.cpp +++ b/src/coreclr/binder/customassemblybinder.cpp @@ -10,139 +10,6 @@ using namespace BINDER_SPACE; -// ============================================================================ -// CustomAssemblyBinder implementation -// ============================================================================ -HRESULT CustomAssemblyBinder::BindAssemblyByNameWorker(BINDER_SPACE::AssemblyName *pAssemblyName, - BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly) -{ - VALIDATE_ARG_RET(pAssemblyName != nullptr && ppCoreCLRFoundAssembly != nullptr); - HRESULT hr = S_OK; - -#ifdef _DEBUG - // CoreLib should be bound using BindToSystem - _ASSERTE(!pAssemblyName->IsCoreLib()); -#endif - - // Do we have the assembly already loaded in the context of the current binder? - hr = AssemblyBinderCommon::BindAssembly(this, - pAssemblyName, - false, //excludeAppPaths, - ppCoreCLRFoundAssembly); - if (!FAILED(hr)) - { - _ASSERTE(*ppCoreCLRFoundAssembly != NULL); - (*ppCoreCLRFoundAssembly)->SetBinder(this); - } - - return hr; -} - -HRESULT CustomAssemblyBinder::BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, - BINDER_SPACE::Assembly** ppAssembly) -{ - // When LoadContext needs to resolve an assembly reference, it will go through the following lookup order: - // - // 1) Lookup the assembly within the LoadContext itself. If assembly is found, use it. - // 2) Invoke the LoadContext's Load method implementation. If assembly is found, use it. - // 3) Lookup the assembly within DefaultBinder (except for satellite requests). If assembly is found, use it. - // 4) Invoke the LoadContext's ResolveSatelliteAssembly method (for satellite requests). If assembly is found, use it. - // 5) Invoke the LoadContext's Resolving event. If assembly is found, use it. - // 6) Raise exception. - // - // This approach enables a LoadContext to override assemblies that have been loaded in TPA context by loading - // a different (or even the same!) version. - - HRESULT hr = S_OK; - ReleaseHolder pCoreCLRFoundAssembly; - - { - // Step 1 - Try to find the assembly within the LoadContext. - hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly); - if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || - (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH)) - { - // If we are here, one of the following is possible: - // - // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR - // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def - // mismatch (either due to version difference or strong-name difference). - // - // Thus, if default binder has been overridden, then invoke it in an attempt to perform the binding for it make the call - // of what to do next. The host-overridden binder can either fail the bind or return reference to an existing assembly - // that has been loaded. - // - hr = AssemblyBinderCommon::BindUsingHostAssemblyResolver(GetManagedAssemblyLoadContext(), pAssemblyName, - m_pDefaultBinder, this, &pCoreCLRFoundAssembly); - if (SUCCEEDED(hr)) - { - // We maybe returned an assembly that was bound to a different AssemblyBinder instance. - // In such a case, we will not overwrite the binder (which would be wrong since the assembly would not - // be present in the cache of the current binding context). - if (pCoreCLRFoundAssembly->GetBinder() == NULL) - { - pCoreCLRFoundAssembly->SetBinder(this); - } - } - } - } - - IF_FAIL_GO(hr); - - // Extract the assembly reference. - // - // For TPA assemblies that were bound, DefaultBinder - // would have already set the binder reference for the assembly, so we just need to - // extract the reference now. - *ppAssembly = pCoreCLRFoundAssembly.Extract(); - -Exit:; - - return hr; -} - -HRESULT CustomAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, - /* [retval][out] */ BINDER_SPACE::Assembly **ppAssembly) -{ - HRESULT hr = S_OK; - - EX_TRY - { - ReleaseHolder pCoreCLRFoundAssembly; - ReleaseHolder pAssemblyName; - - // Using the information we just got, initialize the assemblyname - SAFE_NEW(pAssemblyName, BINDER_SPACE::AssemblyName); - IF_FAIL_GO(pAssemblyName->Init(pPEImage)); - - // Validate architecture - if (!AssemblyBinderCommon::IsValidArchitecture(pAssemblyName->GetArchitecture())) - { - IF_FAIL_GO(CLR_E_BIND_ARCHITECTURE_MISMATCH); - } - - // Disallow attempt to bind to the core library. Aside from that, - // the LoadContext can load any assembly (even if it was in a different LoadContext like TPA). - if (pAssemblyName->IsCoreLib()) - { - IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); - } - - hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, excludeAppPaths, &pCoreCLRFoundAssembly); - if (hr == S_OK) - { - _ASSERTE(pCoreCLRFoundAssembly != NULL); - pCoreCLRFoundAssembly->SetBinder(this); - *ppAssembly = pCoreCLRFoundAssembly.Extract(); - } -Exit:; - } - EX_CATCH_HRESULT(hr); - - return hr; -} - AssemblyLoaderAllocator* CustomAssemblyBinder::GetLoaderAllocator() { return m_pAssemblyLoaderAllocator; diff --git a/src/coreclr/binder/defaultassemblybinder.cpp b/src/coreclr/binder/defaultassemblybinder.cpp deleted file mode 100644 index 3b98997bf46461..00000000000000 --- a/src/coreclr/binder/defaultassemblybinder.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "common.h" -#include "assemblybindercommon.hpp" -#include "defaultassemblybinder.h" - -using namespace BINDER_SPACE; - -//============================================================================= -// Helper functions -//----------------------------------------------------------------------------- - -HRESULT DefaultAssemblyBinder::BindAssemblyByNameWorker(BINDER_SPACE::AssemblyName *pAssemblyName, - BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly, - bool excludeAppPaths) -{ - VALIDATE_ARG_RET(pAssemblyName != nullptr && ppCoreCLRFoundAssembly != nullptr); - HRESULT hr = S_OK; - -#ifdef _DEBUG - // CoreLib should be bound using BindToSystem - _ASSERTE(!pAssemblyName->IsCoreLib()); -#endif - - hr = AssemblyBinderCommon::BindAssembly(this, - pAssemblyName, - excludeAppPaths, - ppCoreCLRFoundAssembly); - if (!FAILED(hr)) - { - (*ppCoreCLRFoundAssembly)->SetBinder(this); - } - - return hr; -} - -// ============================================================================ -// DefaultAssemblyBinder implementation -// ============================================================================ -HRESULT DefaultAssemblyBinder::BindUsingAssemblyName(BINDER_SPACE::AssemblyName *pAssemblyName, - BINDER_SPACE::Assembly **ppAssembly) -{ - HRESULT hr = S_OK; - VALIDATE_ARG_RET(pAssemblyName != nullptr && ppAssembly != nullptr); - - *ppAssembly = nullptr; - - ReleaseHolder pCoreCLRFoundAssembly; - - hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, false /* excludeAppPaths */); - -#if !defined(DACCESS_COMPILE) - if ((hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || - (hr == FUSION_E_APP_DOMAIN_LOCKED) || (hr == FUSION_E_REF_DEF_MISMATCH)) - { - // If we are here, one of the following is possible: - // - // 1) The assembly has not been found in the current binder's application context (i.e. it has not already been loaded), OR - // 2) An assembly with the same simple name was already loaded in the context of the current binder but we ran into a Ref/Def - // mismatch (either due to version difference or strong-name difference). - // - // Attempt to resolve the assembly via managed ALC instance. This can either fail the bind or return reference to an existing - // assembly that has been loaded - INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(); - if (pManagedAssemblyLoadContext == NULL) - { - // For satellite assemblies, the managed ALC has additional resolution logic (defined by the runtime) which - // should be run even if the managed default ALC has not yet been used. (For non-satellite assemblies, any - // additional logic comes through a user-defined event handler which would have initialized the managed ALC, - // so if the managed ALC is not set yet, there is no additional logic to run) - if (!pAssemblyName->IsNeutralCulture()) - { - // Make sure the managed default ALC is initialized. - GCX_COOP(); - PREPARE_NONVIRTUAL_CALLSITE(METHOD__ASSEMBLYLOADCONTEXT__INITIALIZE_DEFAULT_CONTEXT); - DECLARE_ARGHOLDER_ARRAY(args, 0); - CALL_MANAGED_METHOD_NORET(args) - - pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(); - _ASSERTE(pManagedAssemblyLoadContext != NULL); - } - } - - if (pManagedAssemblyLoadContext != NULL) - { - hr = AssemblyBinderCommon::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, - NULL, this, &pCoreCLRFoundAssembly); - if (SUCCEEDED(hr)) - { - // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. - // In such a case, we will not overwrite the binding context (which would be wrong since it would not - // be present in the cache of the current binding context). - if (pCoreCLRFoundAssembly->GetBinder() == NULL) - { - pCoreCLRFoundAssembly->SetBinder(this); - } - } - } - } -#endif // !defined(DACCESS_COMPILE) - - IF_FAIL_GO(hr); - - *ppAssembly = pCoreCLRFoundAssembly.Extract(); - -Exit:; - - return hr; -} - -#if !defined(DACCESS_COMPILE) -HRESULT DefaultAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, - /* [retval][out] */ BINDER_SPACE::Assembly **ppAssembly) -{ - HRESULT hr = S_OK; - - EX_TRY - { - ReleaseHolder pCoreCLRFoundAssembly; - ReleaseHolder pAssemblyName; - - // Using the information we just got, initialize the assemblyname - SAFE_NEW(pAssemblyName, AssemblyName); - IF_FAIL_GO(pAssemblyName->Init(pPEImage)); - - // Validate architecture - if (!AssemblyBinderCommon::IsValidArchitecture(pAssemblyName->GetArchitecture())) - { - IF_FAIL_GO(CLR_E_BIND_ARCHITECTURE_MISMATCH); - } - - // Easy out for CoreLib - if (pAssemblyName->IsCoreLib()) - { - IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); - } - - { - // Ensure we are not being asked to bind to a TPA assembly - // - const SString& simpleName = pAssemblyName->GetSimpleName(); - SimpleNameToFileNameMap* tpaMap = GetAppContext()->GetTpaList(); - if (tpaMap->LookupPtr(simpleName.GetUnicode()) != NULL) - { - // The simple name of the assembly being requested to be bound was found in the TPA list. - // Now, perform the actual bind to see if the assembly was really in the TPA assembly list or not. - hr = BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */); - if (SUCCEEDED(hr)) - { - if (pCoreCLRFoundAssembly->GetIsInTPA()) - { - *ppAssembly = pCoreCLRFoundAssembly.Extract(); - goto Exit; - } - } - } - } - - hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, excludeAppPaths, &pCoreCLRFoundAssembly); - if (hr == S_OK) - { - _ASSERTE(pCoreCLRFoundAssembly != NULL); - pCoreCLRFoundAssembly->SetBinder(this); - *ppAssembly = pCoreCLRFoundAssembly.Extract(); - } -Exit:; - } - EX_CATCH_HRESULT(hr); - - return hr; -} -#endif // !defined(DACCESS_COMPILE) - -HRESULT DefaultAssemblyBinder::SetupBindingPaths(SString &sTrustedPlatformAssemblies, - SString &sPlatformResourceRoots, - SString &sAppPaths) -{ - HRESULT hr = S_OK; - - EX_TRY - { - hr = GetAppContext()->SetupBindingPaths(sTrustedPlatformAssemblies, sPlatformResourceRoots, sAppPaths, TRUE /* fAcquireLock */); - } - EX_CATCH_HRESULT(hr); - return hr; -} - -HRESULT DefaultAssemblyBinder::BindToSystem(BINDER_SPACE::Assembly** ppSystemAssembly) -{ - //HRESULT hr = S_OK; - //_ASSERTE(ppSystemAssembly != NULL); - - //EX_TRY - //{ - // ReleaseHolder pAsm; - // StackSString systemPath(SystemDomain::System()->SystemDirectory()); - // hr = AssemblyBinderCommon::BindToSystem(systemPath, &pAsm); - // if (SUCCEEDED(hr)) - // { - // _ASSERTE(pAsm != NULL); - // *ppSystemAssembly = pAsm.Extract(); - // (*ppSystemAssembly)->SetBinder(this); - // } - - //} - //EX_CATCH_HRESULT(hr); - - //return hr; - - return E_FAIL; // unused -} - diff --git a/src/coreclr/binder/inc/assemblybindercommon.hpp b/src/coreclr/binder/inc/assemblybindercommon.hpp index 70fea4fdb4789d..fa26243a43750c 100644 --- a/src/coreclr/binder/inc/assemblybindercommon.hpp +++ b/src/coreclr/binder/inc/assemblybindercommon.hpp @@ -28,76 +28,14 @@ namespace BINDER_SPACE class AssemblyBinderCommon { public: - static HRESULT BindAssembly(/* in */ AssemblyBinder *pBinder, - /* in */ AssemblyName *pAssemblyName, - /* in */ bool excludeAppPaths, - /* out */ Assembly **ppAssembly); - static HRESULT BindToSystem(/* in */ SString &systemDirectory, /* out */ PEImage **ppPEImage); - static HRESULT BindToSystemSatellite(/* in */ SString &systemDirectory, - /* in */ SString &simpleName, - /* in */ SString &cultureName, - /* out */ Assembly **ppSystemAssembly); - - static HRESULT GetAssembly(/* in */ SString &assemblyPath, - /* in */ BOOL fIsInTPA, - /* out */ Assembly **ppAssembly, - /* in */ BundleFileLocation bundleFileLocation = BundleFileLocation::Invalid()); - -#if !defined(DACCESS_COMPILE) - static HRESULT BindUsingHostAssemblyResolver (/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin, - /* in */ AssemblyName *pAssemblyName, - /* in */ DefaultAssemblyBinder *pDefaultBinder, - /* in */ AssemblyBinder *pBinder, - /* out */ Assembly **ppAssembly); - - static HRESULT BindUsingPEImage(/* in */ AssemblyBinder *pBinder, - /* in */ BINDER_SPACE::AssemblyName *pAssemblyName, - /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, - /* [retval] [out] */ Assembly **ppAssembly); -#endif // !defined(DACCESS_COMPILE) - static HRESULT TranslatePEToArchitectureType(DWORD *pdwPAFlags, PEKIND *PeKind); static HRESULT CreateDefaultBinder(DefaultAssemblyBinder** ppDefaultBinder); static BOOL IsValidArchitecture(PEKIND kArchitecture); - - private: - static HRESULT BindByName(/* in */ ApplicationContext *pApplicationContext, - /* in */ AssemblyName *pAssemblyName, - /* in */ bool skipFailureCaching, - /* in */ bool skipVersionCompatibilityCheck, - /* in */ bool excludeAppPaths, - /* out */ BindResult *pBindResult); - - static HRESULT BindLocked(/* in */ ApplicationContext *pApplicationContext, - /* in */ AssemblyName *pAssemblyName, - /* in */ bool skipVersionCompatibilityCheck, - /* in */ bool excludeAppPaths, - /* out */ BindResult *pBindResult); - - static HRESULT FindInExecutionContext(/* in */ ApplicationContext *pApplicationContext, - /* in */ AssemblyName *pAssemblyName, - /* out */ Assembly **ppAssembly); - - static HRESULT BindByTpaList(/* in */ ApplicationContext *pApplicationContext, - /* in */ AssemblyName *pRequestedAssemblyName, - /* in */ bool excludeAppPaths, - /* out */ BindResult *pBindResult); - - static HRESULT Register(/* in */ ApplicationContext *pApplicationContext, - /* in */ BindResult *pBindResult); - static HRESULT RegisterAndGetHostChosen(/* in */ ApplicationContext *pApplicationContext, - /* in */ LONG kContextVersion, - /* in */ BindResult *pBindResult, - /* out */ BindResult *pHostBindResult); - - static HRESULT OtherBindInterfered(/* in */ ApplicationContext *pApplicationContext, - /* in */ BindResult *pBindResult); }; }; diff --git a/src/coreclr/binder/inc/customassemblybinder.h b/src/coreclr/binder/inc/customassemblybinder.h index 7a89c5033b9e50..0b98afe54bef26 100644 --- a/src/coreclr/binder/inc/customassemblybinder.h +++ b/src/coreclr/binder/inc/customassemblybinder.h @@ -17,13 +17,6 @@ class CustomAssemblyBinder final : public AssemblyBinder { public: - HRESULT BindUsingPEImage(PEImage* pPEImage, - bool excludeAppPaths, - BINDER_SPACE::Assembly** ppAssembly) override; - - HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, - BINDER_SPACE::Assembly** ppAssembly) override; - AssemblyLoaderAllocator* GetLoaderAllocator() override; bool IsDefault() override @@ -48,8 +41,6 @@ class CustomAssemblyBinder final : public AssemblyBinder void ReleaseLoadContext(); private: - HRESULT BindAssemblyByNameWorker(BINDER_SPACE::AssemblyName *pAssemblyName, BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly); - DefaultAssemblyBinder *m_pDefaultBinder; // A strong GC handle to the managed AssemblyLoadContext. This handle is set when the unload of the AssemblyLoadContext is initiated diff --git a/src/coreclr/binder/inc/defaultassemblybinder.h b/src/coreclr/binder/inc/defaultassemblybinder.h index 3d35854e09f3ff..e690a51369b560 100644 --- a/src/coreclr/binder/inc/defaultassemblybinder.h +++ b/src/coreclr/binder/inc/defaultassemblybinder.h @@ -15,13 +15,6 @@ class DefaultAssemblyBinder final : public AssemblyBinder { public: - HRESULT BindUsingPEImage(PEImage* pPEImage, - bool excludeAppPaths, - BINDER_SPACE::Assembly** ppAssembly) override; - - HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, - BINDER_SPACE::Assembly** ppAssembly) override; - AssemblyLoaderAllocator* GetLoaderAllocator() override { // Not supported by this binder @@ -32,21 +25,6 @@ class DefaultAssemblyBinder final : public AssemblyBinder { return true; } - -public: - - HRESULT SetupBindingPaths(SString &sTrustedPlatformAssemblies, - SString &sPlatformResourceRoots, - SString &sAppPaths); - - HRESULT BindToSystem(BINDER_SPACE::Assembly **ppSystemAssembly); - -private: - - HRESULT BindAssemblyByNameWorker( - BINDER_SPACE::AssemblyName *pAssemblyName, - BINDER_SPACE::Assembly **ppCoreCLRFoundAssembly, - bool excludeAppPaths); }; #endif // __DEFAULT_ASSEMBLY_BINDER_H__ diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 748c9d52223347..742e4366254a3a 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -4912,235 +4912,6 @@ AppDomain::AssemblyIterator::Next_Unlocked( return FALSE; } // AppDomain::AssemblyIterator::Next_Unlocked -#if !defined(DACCESS_COMPILE) - -// Returns S_OK if the assembly was successfully loaded -HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, BINDER_SPACE::AssemblyName *pAssemblyName, DefaultAssemblyBinder *pDefaultBinder, AssemblyBinder *pBinder, BINDER_SPACE::Assembly **ppLoadedAssembly) -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(pAssemblyName != NULL); - PRECONDITION(ppLoadedAssembly != NULL); - } - CONTRACTL_END; - - HRESULT hr = E_FAIL; - - // Switch to COOP mode since we are going to work with managed references - GCX_COOP(); - - struct - { - ASSEMBLYNAMEREF oRefAssemblyName; - ASSEMBLYREF oRefLoadedAssembly; - } _gcRefs; - - ZeroMemory(&_gcRefs, sizeof(_gcRefs)); - - GCPROTECT_BEGIN(_gcRefs); - - BINDER_SPACE::Assembly *pResolvedAssembly = NULL; - - bool fResolvedAssembly = false; - BinderTracing::ResolutionAttemptedOperation tracer{pAssemblyName, 0 /*binderID*/, pManagedAssemblyLoadContextToBindWithin, hr}; - - // Allocate an AssemblyName managed object - _gcRefs.oRefAssemblyName = (ASSEMBLYNAMEREF) AllocateObject(CoreLibBinder::GetClass(CLASS__ASSEMBLY_NAME)); - - // Initialize the AssemblyName object - AssemblySpec::InitializeAssemblyNameRef(pAssemblyName, &_gcRefs.oRefAssemblyName); - - bool isSatelliteAssemblyRequest = !pAssemblyName->IsNeutralCulture(); - - EX_TRY - { - if (pDefaultBinder != NULL) - { - // Step 2 (of CustomAssemblyBinder::BindAssemblyByName) - Invoke Load method - // This is not invoked for TPA Binder since it always returns NULL. - tracer.GoToStage(BinderTracing::ResolutionAttemptedOperation::Stage::AssemblyLoadContextLoad); - - // Finally, setup arguments for invocation - MethodDescCallSite methLoadAssembly(METHOD__ASSEMBLYLOADCONTEXT__RESOLVE); - - // Setup the arguments for the call - ARG_SLOT args[2] = - { - PtrToArgSlot(pManagedAssemblyLoadContextToBindWithin), // IntPtr for managed assembly load context instance - ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance - }; - - // Make the call - _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methLoadAssembly.Call_RetOBJECTREF(args); - if (_gcRefs.oRefLoadedAssembly != NULL) - { - fResolvedAssembly = true; - } - - hr = fResolvedAssembly ? S_OK : COR_E_FILENOTFOUND; - - // Step 3 (of CustomAssemblyBinder::BindAssemblyByName) - if (!fResolvedAssembly && !isSatelliteAssemblyRequest) - { - tracer.GoToStage(BinderTracing::ResolutionAttemptedOperation::Stage::DefaultAssemblyLoadContextFallback); - - // If we could not resolve the assembly using Load method, then attempt fallback with TPA Binder. - // Since TPA binder cannot fallback to itself, this fallback does not happen for binds within TPA binder. - // - // Switch to pre-emp mode before calling into the binder - GCX_PREEMP(); - BINDER_SPACE::Assembly *pCoreCLRFoundAssembly = NULL; - hr = pDefaultBinder->BindUsingAssemblyName(pAssemblyName, &pCoreCLRFoundAssembly); - if (SUCCEEDED(hr)) - { - _ASSERTE(pCoreCLRFoundAssembly != NULL); - pResolvedAssembly = pCoreCLRFoundAssembly; - fResolvedAssembly = true; - } - } - } - - if (!fResolvedAssembly && isSatelliteAssemblyRequest) - { - // Step 4 (of CustomAssemblyBinder::BindAssemblyByName) - // - // Attempt to resolve it using the ResolveSatelliteAssembly method. - // Finally, setup arguments for invocation - tracer.GoToStage(BinderTracing::ResolutionAttemptedOperation::Stage::ResolveSatelliteAssembly); - - MethodDescCallSite methResolveSateliteAssembly(METHOD__ASSEMBLYLOADCONTEXT__RESOLVESATELLITEASSEMBLY); - - // Setup the arguments for the call - ARG_SLOT args[2] = - { - PtrToArgSlot(pManagedAssemblyLoadContextToBindWithin), // IntPtr for managed assembly load context instance - ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance - }; - - // Make the call - _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methResolveSateliteAssembly.Call_RetOBJECTREF(args); - if (_gcRefs.oRefLoadedAssembly != NULL) - { - // Set the flag indicating we found the assembly - fResolvedAssembly = true; - } - - hr = fResolvedAssembly ? S_OK : COR_E_FILENOTFOUND; - } - - if (!fResolvedAssembly) - { - // Step 5 (of CustomAssemblyBinder::BindAssemblyByName) - // - // If we couldn't resolve the assembly using TPA LoadContext as well, then - // attempt to resolve it using the Resolving event. - // Finally, setup arguments for invocation - tracer.GoToStage(BinderTracing::ResolutionAttemptedOperation::Stage::AssemblyLoadContextResolvingEvent); - - MethodDescCallSite methResolveUsingEvent(METHOD__ASSEMBLYLOADCONTEXT__RESOLVEUSINGEVENT); - - // Setup the arguments for the call - ARG_SLOT args[2] = - { - PtrToArgSlot(pManagedAssemblyLoadContextToBindWithin), // IntPtr for managed assembly load context instance - ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance - }; - - // Make the call - _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methResolveUsingEvent.Call_RetOBJECTREF(args); - if (_gcRefs.oRefLoadedAssembly != NULL) - { - // Set the flag indicating we found the assembly - fResolvedAssembly = true; - } - - hr = fResolvedAssembly ? S_OK : COR_E_FILENOTFOUND; - } - - if (fResolvedAssembly && pResolvedAssembly == NULL) - { - // If we are here, assembly was successfully resolved via Load or Resolving events. - _ASSERTE(_gcRefs.oRefLoadedAssembly != NULL); - - // We were able to get the assembly loaded. Now, get its name since the host could have - // performed the resolution using an assembly with different name. - DomainAssembly *pDomainAssembly = _gcRefs.oRefLoadedAssembly->GetDomainAssembly(); - PEAssembly *pLoadedPEAssembly = NULL; - bool fFailLoad = false; - if (!pDomainAssembly) - { - // Reflection emitted assemblies will not have a domain assembly. - fFailLoad = true; - } - else - { - pLoadedPEAssembly = pDomainAssembly->GetPEAssembly(); - if (!pLoadedPEAssembly->HasHostAssembly()) - { - // Reflection emitted assemblies will not have a domain assembly. - fFailLoad = true; - } - } - - // The loaded assembly's BINDER_SPACE::Assembly* is saved as HostAssembly in PEAssembly - if (fFailLoad) - { - PathString name; - pAssemblyName->GetDisplayName(name, BINDER_SPACE::AssemblyName::INCLUDE_ALL); - COMPlusThrowHR(COR_E_INVALIDOPERATION, IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED, name); - } - - // For collectible assemblies, ensure that the parent loader allocator keeps the assembly's loader allocator - // alive for all its lifetime. - if (pDomainAssembly->IsCollectible()) - { - LoaderAllocator *pResultAssemblyLoaderAllocator = pDomainAssembly->GetLoaderAllocator(); - LoaderAllocator *pParentLoaderAllocator = pBinder->GetLoaderAllocator(); - if (pParentLoaderAllocator == NULL) - { - // The AssemblyLoadContext for which we are resolving the Assembly is not collectible. - COMPlusThrow(kNotSupportedException, W("NotSupported_CollectibleBoundNonCollectible")); - } - - _ASSERTE(pResultAssemblyLoaderAllocator); - pParentLoaderAllocator->EnsureReference(pResultAssemblyLoaderAllocator); - } - - // unused with managed binder - // pResolvedAssembly = pLoadedPEAssembly->GetHostAssembly(); - } - - if (fResolvedAssembly) - { - _ASSERTE(pResolvedAssembly != NULL); - - // Get the BINDER_SPACE::Assembly reference to return back to. - *ppLoadedAssembly = clr::SafeAddRef(pResolvedAssembly); - hr = S_OK; - - tracer.SetFoundAssembly(static_cast(pResolvedAssembly)); - } - else - { - hr = COR_E_FILENOTFOUND; - } - } - EX_HOOK - { - Exception* ex = GET_EXCEPTION(); - tracer.SetException(ex); - } - EX_END_HOOK - - GCPROTECT_END(); - - return hr; -} -#endif // !defined(DACCESS_COMPILE) - //approximate size of loader data //maintained for each assembly #define APPROX_LOADER_DATA_PER_ASSEMBLY 8196 diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index 3fa911bdec8fe3..c20f2c1407d4cd 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -8,25 +8,6 @@ #ifndef DACCESS_COMPILE -HRESULT AssemblyBinder::BindAssemblyByName(AssemblyNameData* pAssemblyNameData, - BINDER_SPACE::Assembly** ppAssembly) -{ - _ASSERTE(pAssemblyNameData != nullptr && ppAssembly != nullptr); - - HRESULT hr = S_OK; - *ppAssembly = nullptr; - - ReleaseHolder pAssemblyName; - SAFE_NEW(pAssemblyName, BINDER_SPACE::AssemblyName); - IF_FAIL_GO(pAssemblyName->Init(*pAssemblyNameData)); - - hr = BindUsingAssemblyName(pAssemblyName, ppAssembly); - -Exit: - return hr; -} - - NativeImage* AssemblyBinder::LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName) { STANDARD_VM_CONTRACT; diff --git a/src/coreclr/vm/assemblybinder.h b/src/coreclr/vm/assemblybinder.h index 8fa57302cfa401..50506cf72d96f2 100644 --- a/src/coreclr/vm/assemblybinder.h +++ b/src/coreclr/vm/assemblybinder.h @@ -18,10 +18,6 @@ class AssemblyBinder { public: - HRESULT BindAssemblyByName(AssemblyNameData* pAssemblyNameData, BINDER_SPACE::Assembly** ppAssembly); - virtual HRESULT BindUsingPEImage(PEImage* pPEImage, bool excludeAppPaths, BINDER_SPACE::Assembly** ppAssembly) = 0; - virtual HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, BINDER_SPACE::Assembly** ppAssembly) = 0; - /// /// Get LoaderAllocator for binders that contain it. For other binders, return NULL. /// diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index a1d12986013c09..b7b7754a425189 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -197,24 +197,6 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma RETURN pDomainAssembly->GetAssembly(); } -LoaderAllocator* AssemblyBinder_GetNativeLoaderAllocator(ASSEMBLYBINDERREF pBinder) -{ - GCX_COOP(); - - LoaderAllocator* pNativeLA = NULL; - - GCPROTECT_BEGIN(pBinder); - - MethodDescCallSite getLA(METHOD__BINDER_ASSEMBLYBINDER__GETLOADERALLOCATOR); - ARG_SLOT arg = ObjToArgSlot(pBinder); - LOADERALLOCATORREF pManagedLA = (LOADERALLOCATORREF)getLA.Call_RetOBJECTREF(&arg); - pNativeLA = pManagedLA->GetNativeLoaderAllocator(); - - GCPROTECT_END(); - - return pNativeLA; -} - extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyBinder, LPCWSTR pwzILPath, LPCWSTR pwzNIPath, QCall::ObjectHandleOnStack retLoadedAssembly) { QCALL_CONTRACT; From 7108a482b5c5ea760a04ba55807330b8f25d9f6b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 15 Nov 2023 01:26:32 +0800 Subject: [PATCH 105/136] Redo CoreLib bootstrap changes --- src/coreclr/vm/appdomain.cpp | 5 +++++ src/coreclr/vm/assemblyspec.cpp | 8 ++++++-- src/coreclr/vm/baseassemblyspec.cpp | 2 +- src/coreclr/vm/util.cpp | 6 +----- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 742e4366254a3a..6c95299e7c8411 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -2757,10 +2757,15 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, { LoaderAllocator *pLoaderAllocator = NULL; + // AssemblyBinder isn't set for CoreLib during bootstrap + if (!pPEAssembly->IsSystem()) + { AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if // marked as collectible pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator(); + } + if (pLoaderAllocator == NULL) { pLoaderAllocator = this->GetLoaderAllocator(); diff --git a/src/coreclr/vm/assemblyspec.cpp b/src/coreclr/vm/assemblyspec.cpp index 416f0491365d74..451a72ed816b68 100644 --- a/src/coreclr/vm/assemblyspec.cpp +++ b/src/coreclr/vm/assemblyspec.cpp @@ -210,8 +210,12 @@ void AssemblySpec::InitializeSpec(PEAssembly * pFile) { AssemblyBinder* pExpectedBinder = pFile->GetAssemblyBinder(); // We should always have the binding context in the PEAssembly. - _ASSERTE(pExpectedBinder != NULL); - SetBinder(pExpectedBinder); + if (!IsCoreLib()) + { + // Binder of CoreLib will be set afterwards. + _ASSERTE(pExpectedBinder != NULL); + SetBinder(pExpectedBinder); + } } } diff --git a/src/coreclr/vm/baseassemblyspec.cpp b/src/coreclr/vm/baseassemblyspec.cpp index fbc0afad966c01..8dfab5ce5625d0 100644 --- a/src/coreclr/vm/baseassemblyspec.cpp +++ b/src/coreclr/vm/baseassemblyspec.cpp @@ -22,7 +22,7 @@ BOOL BaseAssemblySpec::IsCoreLib() { THROWS; INSTANCE_CHECK; - GC_TRIGGERS; + GC_NOTRIGGER; MODE_ANY; INJECT_FAULT(COMPlusThrowOM();); } diff --git a/src/coreclr/vm/util.cpp b/src/coreclr/vm/util.cpp index 7412b03b3b4aed..7ca9e19b52de21 100644 --- a/src/coreclr/vm/util.cpp +++ b/src/coreclr/vm/util.cpp @@ -1797,16 +1797,12 @@ int GetRandomInt(int maxVal) // These wrap the SString:L:CompareCaseInsensitive function in a way that makes it // easy to fix code that uses _stricmp. _stricmp should be avoided as it uses the current // C-runtime locale rather than the invariance culture. -// -// Note that unlike the real _stricmp, these functions unavoidably have a throws/gc_triggers/inject_fault -// contract. So if need a case-insensitive comparison in a place where you can't tolerate this contract, -// you've got a problem. int __cdecl stricmpUTF8(const char* szStr1, const char* szStr2) { CONTRACTL { THROWS; - GC_TRIGGERS; + GC_NOTRIGGER; INJECT_FAULT(COMPlusThrowOM()); } CONTRACTL_END From 3f7c634a77f9a6da216978b1b034a1ad86deeb90 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 01:38:43 +0800 Subject: [PATCH 106/136] Remove BinderAssemblyObject and reorder vm to corelib call to ALC --- .../Loader/AssemblyLoadContext.Binder.cs | 7 ++- .../AssemblyLoadContext.BinderCommon.cs | 1 + .../Loader/AssemblyLoadContext.CoreCLR.cs | 8 --- .../AssemblyLoadContext.CustomBinder.cs | 1 + .../AssemblyLoadContext.DefaultBinder.cs | 24 ++++++--- src/coreclr/vm/appdomain.cpp | 42 +++++++++------- src/coreclr/vm/assemblynative.cpp | 5 +- src/coreclr/vm/common.h | 1 - src/coreclr/vm/coreassemblyspec.cpp | 4 +- src/coreclr/vm/corelib.h | 50 ++++++++----------- src/coreclr/vm/corhost.cpp | 12 +---- src/coreclr/vm/metasig.h | 4 +- src/coreclr/vm/namespace.h | 1 - src/coreclr/vm/object.h | 24 ++++----- 14 files changed, 83 insertions(+), 101 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index 00675f8da7b319..689377637ae791 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -30,10 +30,9 @@ internal readonly unsafe struct AssemblyNameData public partial class AssemblyLoadContext { + // called by vm private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out BinderAssembly? assembly) - { - return BindUsingAssemblyName(new BinderAssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); - } + => BindUsingAssemblyName(new BinderAssemblyName((AssemblyNameData*)pAssemblyNameData), out assembly); internal ApplicationContext AppContext { get; } = new ApplicationContext(); @@ -74,7 +73,7 @@ private static void MvidMismatchFatalError(Guid mvidActual, Guid mvidExpected, s Environment.FailFast(message); } - // used by vm + // called by vm private unsafe void DeclareDependencyOnMvid(byte* simpleName, in Guid mvid, bool compositeComponent, byte* imageName) => DeclareDependencyOnMvid(new MdUtf8String(simpleName).ToString(), mvid, compositeComponent, new MdUtf8String(imageName).ToString()); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index d61847cae53586..ba62ffee34e59b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -251,6 +251,7 @@ public static int BindAssembly(AssemblyLoadContext binder, BinderAssemblyName as // Skipped - the managed binder can't bootstrap CoreLib // static Assembly? BindToSystem(string systemDirectory); + // called by vm private static unsafe int BindToSystemSatellite(char* systemDirectory, char* simpleName, char* cultureName, out BinderAssembly? assembly) { // Satellite assembly's relative path diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index ea014cf3e4aae0..509f4eefec4858 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -191,13 +191,5 @@ private static void StopAssemblyLoad(ref Guid activityId) // Don't use trace to TPL event source in ActivityTracker - that event source is a singleton and its instantiation may have triggered the load. ActivityTracker.Instance.OnStop(NativeRuntimeEventSource.Log.Name, AssemblyLoadName, 0, ref activityId, useTplSource: false); } - - /// - /// Called by the runtime to make sure the default ALC is initialized - /// - internal static void InitializeDefaultContext() - { - _ = Default; - } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index 6adc821e1a7157..9af11d075bad3a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -72,6 +72,7 @@ internal virtual int BindUsingAssemblyName(BinderAssemblyName assemblyName, out return hr; } + // called by vm internal virtual int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out BinderAssembly? assembly) { assembly = null; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index b73f81dd305163..bb360abf6c1f58 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -5,11 +5,25 @@ namespace System.Runtime.Loader { - internal partial class DefaultAssemblyLoadContext + public partial class AssemblyLoadContext { // called by vm - private BinderAssembly CreateCoreLib(IntPtr pCoreLibPEImage) => new BinderAssembly(pCoreLibPEImage, true) { Binder = this }; + private static BinderAssembly InitializeDefault(IntPtr pCoreLibAssembly) + { + // ensure to touch Default to make it initialized + Default.AddLoadedAssembly(pCoreLibAssembly); + return new BinderAssembly(Assembly_GetPEImage(pCoreLibAssembly), true) { Binder = Default }; + } + + // called by VM + private static unsafe void SetupBindingPaths(char* trustedPlatformAssemblies, char* platformResourceRoots, char* appPaths) + { + Default.AppContext.SetupBindingPaths(new string(trustedPlatformAssemblies), new string(platformResourceRoots), new string(appPaths), acquireLock: true); + } + } + internal partial class DefaultAssemblyLoadContext + { // Helper functions private int BindAssemblyByNameWorker(BinderAssemblyName assemblyName, out BinderAssembly? coreCLRFoundAssembly, bool excludeAppPaths) { @@ -124,11 +138,5 @@ internal override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out return hr; } - - // called by VM - private unsafe void SetupBindingPaths(char* trustedPlatformAssemblies, char* platformResourceRoots, char* appPaths) - { - AppContext.SetupBindingPaths(new string(trustedPlatformAssemblies), new string(platformResourceRoots), new string(appPaths), acquireLock: true); - } } } diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 6c95299e7c8411..045e700abcc667 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1162,25 +1162,23 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); - ASSEMBLYLOADCONTEXTREF defaultBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()); - + // AdHoc setting logic for CoreLib, since managed code isn't available during CoreLib bootstrap { - // AdHoc setup for corelib PEAssembly - GCPROTECT_BEGIN(defaultBinder); + // Initialize managed default binder and set binder assembly for CoreLib + MethodDescCallSite initializeDefault(METHOD__ASSEMBLYLOADCONTEXT__INITIALIZE_DEFAULT); + ARG_SLOT arg = PtrToArgSlot(m_pSystemAssembly); + OBJECTREF coreLibHostAssembly = initializeDefault.Call_RetOBJECTREF(&arg); + + // Default binder should be initialized + _ASSERTE(GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext() != NULL); - // Set binder assembly for CoreLib - MethodDescCallSite createCoreLib(METHOD__BINDER_DEFAULTASSEMBLYBINDER__CREATECORELIB); - ARG_SLOT args[2] = - { - ObjToArgSlot(defaultBinder), - PtrToArgSlot(m_pSystemPEAssembly->GetPEImage()) - }; - OBJECTREF coreLibHostAssembly = createCoreLib.Call_RetOBJECTREF(args); m_pSystemPEAssembly->SetHostAssemblyAdHoc(CreateHandle(coreLibHostAssembly)); m_pSystemAssembly->GetDomainAssembly()->RegisterWithHostAssembly(); - GCPROTECT_END(); + // Managed and unmanaged representations of CoreLib should be correctly linked + _ASSERTE(((BINDERASSEMBLYREF)coreLibHostAssembly)->m_pDomainAssembly == m_pSystemAssembly->GetDomainAssembly()); + _ASSERTE(ObjectFromHandle(m_pSystemPEAssembly->GetHostAssembly()) == coreLibHostAssembly); // Add CoreLib to AssemblyBindingCache AssemblySpec spec; @@ -2760,10 +2758,10 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, // AssemblyBinder isn't set for CoreLib during bootstrap if (!pPEAssembly->IsSystem()) { - AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); - // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if - // marked as collectible - pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator(); + AssemblyBinder *pAssemblyBinder = pPEAssembly->GetAssemblyBinder(); + // Assemblies loaded with CustomAssemblyBinder need to use a different LoaderAllocator if + // marked as collectible + pLoaderAllocator = pAssemblyBinder->GetLoaderAllocator(); } if (pLoaderAllocator == NULL) @@ -2823,13 +2821,19 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, { GCX_COOP(); - MethodDescCallSite methAddLoadedAssem(METHOD__BINDER_ASSEMBLYBINDER__ADDLOADEDASSEMBLY); + ASSEMBLYLOADCONTEXTREF managedALC = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)(pPEAssembly->GetAssemblyBinder()->GetManagedAssemblyLoadContext())); + + GCPROTECT_BEGIN(managedALC); + + MethodDescCallSite methAddLoadedAssem(METHOD__ASSEMBLYLOADCONTEXT__ADD_LOADED_EDASSEMBLY); ARG_SLOT args[2] = { - ObjToArgSlot((ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)(pPEAssembly->GetAssemblyBinder()))), + ObjToArgSlot(managedALC), PtrToArgSlot(pDomainAssembly->GetAssembly()) }; methAddLoadedAssem.Call(args); + + GCPROTECT_END(); } } else diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index b7b7754a425189..c3e8b006b80e53 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -156,9 +156,12 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma BINDERASSEMBLYREF pAssembly; } gc; + gc.pBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)(pBinder->GetManagedAssemblyLoadContext())); + gc.pAssembly = NULL; + GCPROTECT_BEGIN(gc); - MethodDescCallSite methBind(METHOD__BINDER_ASSEMBLYBINDER__BINDUSINGPEIMAGE, &gc.pBinder); + MethodDescCallSite methBind(METHOD__ASSEMBLYLOADCONTEXT__BIND_USING_PEIMAGE, &gc.pBinder); ARG_SLOT args[4] = { ObjToArgSlot(gc.pBinder), diff --git a/src/coreclr/vm/common.h b/src/coreclr/vm/common.h index 5223608af31bf4..c8eadd75ee8780 100644 --- a/src/coreclr/vm/common.h +++ b/src/coreclr/vm/common.h @@ -101,7 +101,6 @@ typedef VPTR(class AppDomain) PTR_AppDomain; typedef DPTR(class ArrayBase) PTR_ArrayBase; typedef DPTR(class Assembly) PTR_Assembly; typedef DPTR(class AssemblyBaseObject) PTR_AssemblyBaseObject; -typedef DPTR(class AssemblyBinderObject) PTR_AssemblyBinderObject; typedef DPTR(class BinderAssemblyObject) PTR_BinderAssemblyObject; typedef DPTR(class AssemblyLoadContextBaseObject) PTR_AssemblyLoadContextBaseObject; typedef DPTR(class AssemblyBinder) PTR_AssemblyBinder; diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 2c8298226126b6..437f138cc9eaac 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -70,7 +70,7 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly if (m_context.szLocale != NULL) SString(SString::Utf8Literal, m_context.szLocale).ConvertToUnicode(sCultureName); - MethodDescCallSite methSatellite(METHOD__BINDER_ASSEMBLYBINDERCOMMON__BINDTOSYSTEMSATELLITE); + MethodDescCallSite methSatellite(METHOD__ASSEMBLYBINDERCOMMON__BIND_TO_SYSTEM_SATELLITE); ARG_SLOT args[4] = { PtrToArgSlot(sSystemDirectory.GetUnicode()), @@ -86,7 +86,7 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly AssemblyNameData assemblyNameData = { 0 }; PopulateAssemblyNameData(assemblyNameData); - MethodDescCallSite methBindAssemblyByName(METHOD__BINDER_ASSEMBLYBINDER__BINDASSEMBLYBYNAME); + MethodDescCallSite methBindAssemblyByName(METHOD__ASSEMBLYLOADCONTEXT__BIND_ASSEMBLY_BY_NAME); ARG_SLOT args[3] = { ObjToArgSlot(gc.pBinder), diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index e6237e92a53515..f919c1421f4887 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -898,7 +898,26 @@ DEFINE_METHOD(ASSEMBLYLOADCONTEXT, ON_TYPE_RESOLVE, OnTypeResolve, DEFINE_METHOD(ASSEMBLYLOADCONTEXT, ON_ASSEMBLY_RESOLVE, OnAssemblyResolve, SM_Assembly_Str_RetAssembly) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, START_ASSEMBLY_LOAD, StartAssemblyLoad, SM_RefGuid_RefGuid_RetVoid) DEFINE_METHOD(ASSEMBLYLOADCONTEXT, STOP_ASSEMBLY_LOAD, StopAssemblyLoad, SM_RefGuid_RetVoid) -DEFINE_METHOD(ASSEMBLYLOADCONTEXT, INITIALIZE_DEFAULT_CONTEXT, InitializeDefaultContext, SM_RetVoid) +DEFINE_METHOD(ASSEMBLYLOADCONTEXT, INITIALIZE_DEFAULT, InitializeDefault, SM_IntPtr_RetBinderAssembly) +DEFINE_METHOD(ASSEMBLYLOADCONTEXT, ADD_LOADED_EDASSEMBLY, AddLoadedAssembly, IM_IntPtr_RetVoid) +DEFINE_METHOD(ASSEMBLYLOADCONTEXT, BIND_USING_PEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefBinderAssembly_RetInt) +DEFINE_METHOD(ASSEMBLYLOADCONTEXT, BIND_ASSEMBLY_BY_NAME, BindAssemblyByName, IM_PtrVoid_RefBinderAssembly_RetInt) +DEFINE_METHOD(ASSEMBLYLOADCONTEXT, DECLARE_DEPENDENCY_ON_MVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) +DEFINE_METHOD(ASSEMBLYLOADCONTEXT, SETUP_BINDING_PATHS, SetupBindingPaths, SM_PtrChar_PtrChar_PtrChar_RetVoid) + +DEFINE_CLASS(ASSEMBLYBINDERCOMMON, Loader, AssemblyBinderCommon) +DEFINE_METHOD(ASSEMBLYBINDERCOMMON, BIND_TO_SYSTEM_SATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefBinderAssembly_RetInt) + +// Managed binder types + +DEFINE_CLASS(BINDER_ASSEMBLY, Loader, BinderAssembly) +DEFINE_CLASS_U(Loader, BinderAssembly, BinderAssemblyObject) +DEFINE_FIELD_U(m_binder, BinderAssemblyObject, m_binder) +DEFINE_FIELD_U(m_assemblyName, BinderAssemblyObject, m_assemblyName) +DEFINE_FIELD_U(m_peImage, BinderAssemblyObject, m_peImage) +DEFINE_FIELD_U(m_pDomainAssembly, BinderAssemblyObject, m_pDomainAssembly) +DEFINE_FIELD_U(m_isInTPA, BinderAssemblyObject, m_isInTPA) +DEFINE_FIELD_U(m_isCoreLib, BinderAssemblyObject, m_isCoreLib) DEFINE_CLASS(VALUE_TYPE, System, ValueType) DEFINE_METHOD(VALUE_TYPE, GET_HASH_CODE, GetHashCode, IM_RetInt) @@ -1191,35 +1210,6 @@ DEFINE_METHOD(EH, RH_RETHROW, RhRethrow, SM_RefExInfo_RefExInfo_RetVoid) DEFINE_CLASS(EXINFO, Runtime, EH+ExInfo) #endif // FOR_ILLINK -// Managed binder types -DEFINE_CLASS(BINDER_ASSEMBLYBINDER, InternalBinder, AssemblyBinder) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, GETLOADERALLOCATOR, GetLoaderAllocator, IM_RetLoaderAllocator) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, ADDLOADEDASSEMBLY, AddLoadedAssembly, IM_IntPtr_RetVoid) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDUSINGPEIMAGE, BindUsingPEImage, IM_IntPtr_Bool_RefBinderAssembly_RetInt) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, BINDASSEMBLYBYNAME, BindAssemblyByName, IM_PtrVoid_RefBinderAssembly_RetInt) -DEFINE_METHOD(BINDER_ASSEMBLYBINDER, DECLAREDEPENDENCYONMVID, DeclareDependencyOnMvid, IM_PtrByte_RefGuid_Bool_PtrByte_RetVoid) - -DEFINE_CLASS_U(InternalBinder, AssemblyBinder, AssemblyBinderObject) -DEFINE_FIELD_U(m_managedALC, AssemblyBinderObject, m_managedALC) -DEFINE_FIELD_U(m_isDefault, AssemblyBinderObject, m_isDefault) - -DEFINE_CLASS(BINDER_DEFAULTASSEMBLYBINDER, InternalBinder, DefaultAssemblyBinder) -DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CTOR, .ctor, IM_RetVoid) -DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, SETUP_BINDING_PATHS, SetupBindingPaths, IM_PtrChar_PtrChar_PtrChar_RetVoid) -DEFINE_METHOD(BINDER_DEFAULTASSEMBLYBINDER, CREATECORELIB, CreateCoreLib, IM_IntPtr_RetBinderAssembly) - -DEFINE_CLASS(BINDER_ASSEMBLY, InternalBinder, Assembly) -DEFINE_CLASS_U(InternalBinder, Assembly, BinderAssemblyObject) -DEFINE_FIELD_U(m_binder, BinderAssemblyObject, m_binder) -DEFINE_FIELD_U(m_assemblyName, BinderAssemblyObject, m_assemblyName) -DEFINE_FIELD_U(m_peImage, BinderAssemblyObject, m_peImage) -DEFINE_FIELD_U(m_pDomainAssembly, BinderAssemblyObject, m_pDomainAssembly) -DEFINE_FIELD_U(m_isInTPA, BinderAssemblyObject, m_isInTPA) -DEFINE_FIELD_U(m_isCoreLib, BinderAssemblyObject, m_isCoreLib) - -DEFINE_CLASS(BINDER_ASSEMBLYBINDERCOMMON, InternalBinder, AssemblyBinderCommon) -DEFINE_METHOD(BINDER_ASSEMBLYBINDERCOMMON, BINDTOSYSTEMSATELLITE, BindToSystemSatellite, SM_PtrChar_PtrChar_PtrChar_RefBinderAssembly_RetInt) - DEFINE_CLASS_U(System, GCMemoryInfoData, GCMemoryInfoData) DEFINE_FIELD_U(_highMemoryLoadThresholdBytes, GCMemoryInfoData, highMemLoadThresholdBytes) DEFINE_FIELD_U(_totalAvailableMemoryBytes, GCMemoryInfoData, totalAvailableMemoryBytes) diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 3dbaef9876cac0..2cdf254e37cab4 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -620,23 +620,15 @@ HRESULT CorHost2::CreateAppDomainWithManager( { GCX_COOP(); - ASSEMBLYLOADCONTEXTREF pBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)pDomain->GetDefaultBinder()->GetManagedAssemblyLoadContext()); - _ASSERTE(pBinder != NULL); - - GCPROTECT_BEGIN(pBinder); - - MethodDescCallSite methSetupBindingPaths(METHOD__BINDER_DEFAULTASSEMBLYBINDER__SETUP_BINDING_PATHS); - ARG_SLOT args[4] = + MethodDescCallSite methSetupBindingPaths(METHOD__ASSEMBLYLOADCONTEXT__SETUP_BINDING_PATHS); + ARG_SLOT args[3] = { - ObjToArgSlot(pBinder), PtrToArgSlot(pwzTrustedPlatformAssemblies), PtrToArgSlot(pwzPlatformResourceRoots), PtrToArgSlot(pwzAppPaths) }; methSetupBindingPaths.Call(args); - - GCPROTECT_END(); } #if defined(TARGET_UNIX) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index bed3a6d2fe164a..b31f6df3455170 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -616,13 +616,13 @@ DEFINE_METASIG(SM(PtrByte_RetStr, P(b), s)) DEFINE_METASIG(SM(Str_RetPtrByte, s, P(b))) DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v)) -DEFINE_METASIG(IM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) +DEFINE_METASIG(SM(PtrChar_PtrChar_PtrChar_RetVoid, P(u) P(u) P(u), v)) DEFINE_METASIG_T(IM(IntPtr_Bool_RefBinderAssembly_RetInt, I F r(C(BINDER_ASSEMBLY)), i)) DEFINE_METASIG_T(IM(PtrVoid_RefBinderAssembly_RetInt, P(v) r(C(BINDER_ASSEMBLY)), i)) DEFINE_METASIG_T(SM(PtrChar_PtrChar_PtrChar_RefBinderAssembly_RetInt, P(u) P(u) P(u) r(C(BINDER_ASSEMBLY)), i)) DEFINE_METASIG_T(IM(PtrByte_RefGuid_Bool_PtrByte_RetVoid, P(b) r(g(GUID)) F P(b), v)) DEFINE_METASIG_T(IM(RetLoaderAllocator, ,C(LOADERALLOCATOR))) -DEFINE_METASIG_T(IM(IntPtr_RetBinderAssembly, I, C(BINDER_ASSEMBLY))) +DEFINE_METASIG_T(SM(IntPtr_RetBinderAssembly, I, C(BINDER_ASSEMBLY))) // Undefine macros in case we include the file again in the compilation unit diff --git a/src/coreclr/vm/namespace.h b/src/coreclr/vm/namespace.h index 11a60b6ea0be30..8b51f9ca623915 100644 --- a/src/coreclr/vm/namespace.h +++ b/src/coreclr/vm/namespace.h @@ -70,4 +70,3 @@ #define g_ExceptionServicesNS g_RuntimeNS ".ExceptionServices" #define g_LoaderNS g_RuntimeNS ".Loader" -#define g_InternalBinderNS "Internal.Runtime.Binder" diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 0ba22f929cb411..e08cbc26aa7f88 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1440,17 +1440,6 @@ class AssemblyBaseObject : public Object NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive); #define FC_RETURN_ASSEMBLY_OBJECT(pAssembly, refKeepAlive) FC_INNER_RETURN(AssemblyBaseObject*, GetRuntimeAssemblyHelper(__me, pAssembly, refKeepAlive)) -// managed Internal.Runtime.Binder.AssemblyBinder -class AssemblyBinderObject : public Object -{ - OBJECTREF m_appContext; - OBJECTREF m_assemblySimpleNameMvidCheckHash; - OBJECTREF m_loadedAssemblies; -public: - CLR_BOOL m_isDefault; - INT_PTR m_managedALC; -}; - // AssemblyLoadContextBaseObject // This class is the base class for AssemblyLoadContext // @@ -1466,6 +1455,9 @@ class AssemblyLoadContextBaseObject : public Object // Modifying the order or fields of this object may require other changes to the // classlib class definition of this object. #ifdef TARGET_64BIT + OBJECTREF _appContext; + OBJECTREF _assemblySimpleNameMvidCheckHash; + OBJECTREF _loadedAssemblies; OBJECTREF _unloadLock; OBJECTREF _resolvingUnmanagedDll; OBJECTREF _resolving; @@ -1477,6 +1469,9 @@ class AssemblyLoadContextBaseObject : public Object CLR_BOOL _isCollectible; #else // TARGET_64BIT int64_t _id; // On 32-bit platforms this 64-bit value type is larger than a pointer so JIT places it first + OBJECTREF _appContext; + OBJECTREF _assemblySimpleNameMvidCheckHash; + OBJECTREF _loadedAssemblies; OBJECTREF _unloadLock; OBJECTREF _resolvingUnmanagedDll; OBJECTREF _resolving; @@ -1536,8 +1531,6 @@ typedef REF THREADBASEREF; typedef REF ASSEMBLYREF; -typedef REF ASSEMBLYBINDERREF; - typedef REF BINDERASSEMBLYREF; typedef REF ASSEMBLYLOADCONTEXTREF; @@ -1584,7 +1577,6 @@ typedef PTR_ReflectMethodObject REFLECTMETHODREF; typedef PTR_ReflectFieldObject REFLECTFIELDREF; typedef PTR_ThreadBaseObject THREADBASEREF; typedef PTR_AssemblyBaseObject ASSEMBLYREF; -typedef PTR_AssemblyBinderObject ASSEMBLYBINDERREF; typedef PTR_BinderAssemblyObject BINDERASSEMBLYREF; typedef PTR_AssemblyLoadContextBaseObject ASSEMBLYLOADCONTEXTREF; typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; @@ -1599,7 +1591,8 @@ typedef PTR_AssemblyNameBaseObject ASSEMBLYNAMEREF; class PEImage; -// managed Internal.Runtime.Binder.Assembly +#include +// managed System.Runtime.Loader.BinderAssembly class BinderAssemblyObject : public Object { public: @@ -1615,6 +1608,7 @@ class BinderAssemblyObject : public Object return (PTR_AssemblyBinder)m_binder->GetNativeAssemblyBinder(); } }; +#include #define PtrToArgSlot(ptr) ((ARG_SLOT)(SIZE_T)(ptr)) #define ArgSlotToPtr(s) ((LPVOID)(SIZE_T)(s)) From 6836892c306f0a2219f89ff96f43aa6a4fc8e677 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 02:45:09 +0800 Subject: [PATCH 107/136] Uncomment remaining native binder related code --- src/coreclr/vm/assemblybinder.cpp | 18 +++++++-------- src/coreclr/vm/excep.cpp | 3 +-- src/coreclr/vm/readytoruninfo.cpp | 38 +++++++++++++++++-------------- src/coreclr/vm/vars.hpp | 1 - 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index c20f2c1407d4cd..f1db200a14f470 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -13,11 +13,11 @@ NativeImage* AssemblyBinder::LoadNativeImage(Module* componentModule, LPCUTF8 na STANDARD_VM_CONTRACT; BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); - AssemblyBinder* binder = /* componentModule->GetPEAssembly()->GetAssemblyBinder() */ NULL; + AssemblyBinder* binder = componentModule->GetPEAssembly()->GetAssemblyBinder(); PTR_LoaderAllocator moduleLoaderAllocator = componentModule->GetLoaderAllocator(); - // bool isNewNativeImage; - NativeImage* nativeImage = /*NativeImage::Open(componentModule, nativeImageName, binder, moduleLoaderAllocator, &isNewNativeImage)*/ NULL; + bool isNewNativeImage; + NativeImage* nativeImage = NativeImage::Open(componentModule, nativeImageName, binder, moduleLoaderAllocator, &isNewNativeImage); return nativeImage; } @@ -149,11 +149,11 @@ void AssemblyBinder::AddLoadedAssembly(Assembly* loadedAssembly) void AssemblyBinder::GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName) { - /*if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) + if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) { alcName.Set(W("Default")); return; - }*/ + } OBJECTREF* alc = reinterpret_cast(managedALC); @@ -193,11 +193,11 @@ void AssemblyBinder::GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ S _ASSERTE(spec != nullptr); AppDomain* domain = spec->GetAppDomain(); - AssemblyBinder* binder = /* spec->GetBinder() */ NULL; - //if (binder == nullptr) - // binder = spec->GetBinderFromParentAssembly(domain); + AssemblyBinder* binder = spec->GetBinder(); + if (binder == nullptr) + binder = spec->GetBinderFromParentAssembly(domain); - //binder->GetNameForDiagnostics(alcName); + binder->GetNameForDiagnostics(alcName); } #endif //DACCESS_COMPILE diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index aa44d0b50fb90a..4311f7a8f7a0d2 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -11709,8 +11709,7 @@ VOID GetAssemblyDetailInfo(SString &sType, SString detailsUtf8; SString sAlcName; - // TODO: print managed alc name - // pPEAssembly->GetAssemblyBinder()->GetNameForDiagnostics(sAlcName); + pPEAssembly->GetAssemblyBinder()->GetNameForDiagnostics(sAlcName); SString assemblyPath{ pPEAssembly->GetPath() }; if (assemblyPath.IsEmpty()) { diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index d0190ebf9cec82..e35c7738075870 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -503,10 +503,8 @@ static NativeImage *AcquireCompositeImage(Module * pModule, PEImageLayout * pLay if (ownerCompositeExecutableName != NULL) { - //AssemblyBinder *binder = pModule->GetPEAssembly()->GetAssemblyBinder(); - //return binder->LoadNativeImage(pModule, ownerCompositeExecutableName); - - // TODO: implement + AssemblyBinder *binder = pModule->GetPEAssembly()->GetAssemblyBinder(); + return binder->LoadNativeImage(pModule, ownerCompositeExecutableName); } return NULL; @@ -758,7 +756,7 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat int32_t manifestAssemblyCount = 0; GUID emptyGuid = {0}; - // ASSEMBLYBINDERREF binder = pModule != NULL ? pModule->GetPEAssembly()->GetAssemblyBinder() : (ASSEMBLYBINDERREF)ObjectFromHandle(pNativeImage->GetAssemblyBinder()); + AssemblyBinder* binder = pModule != NULL ? pModule->GetPEAssembly()->GetAssemblyBinder() : pNativeImage->GetAssemblyBinder(); auto pComponentAssemblyMvids = FindSection(ReadyToRunSectionType::ManifestAssemblyMvids); if (pComponentAssemblyMvids != NULL) { @@ -782,20 +780,26 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat IfFailThrow(pNativeMDImport->GetAssemblyRefProps(assemblyRef, NULL, NULL, &assemblyName, NULL, NULL, NULL, NULL)); { - // disabled for CoreLib bootstrap + GCX_COOP(); + + OBJECTREF alc = ObjectFromHandle((OBJECTHANDLE)binder->GetManagedAssemblyLoadContext()); + + GCPROTECT_BEGIN(alc); // TODO: GC mode - //MethodDescCallSite methDeclareDependencyOnMvid(METHOD__BINDER_ASSEMBLYBINDER__DECLAREDEPENDENCYONMVID); - //ARG_SLOT args[5] = - //{ - // ObjToArgSlot(binder), - // PtrToArgSlot(componentMvid), - // PtrToArgSlot(assemblyName), - // BoolToArgSlot(pNativeImage != NULL), - // PtrToArgSlot(pModule != NULL ? pModule->GetSimpleName() : pNativeImage->GetFileName()) - //}; - - //methDeclareDependencyOnMvid.Call(args); + MethodDescCallSite methDeclareDependencyOnMvid(METHOD__ASSEMBLYLOADCONTEXT__DECLARE_DEPENDENCY_ON_MVID); + ARG_SLOT args[5] = + { + ObjToArgSlot(alc), + PtrToArgSlot(componentMvid), + PtrToArgSlot(assemblyName), + BoolToArgSlot(pNativeImage != NULL), + PtrToArgSlot(pModule != NULL ? pModule->GetSimpleName() : pNativeImage->GetFileName()) + }; + + methDeclareDependencyOnMvid.Call(args); + + GCPROTECT_END(); } manifestAssemblyCount++; diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 9a623803d90fcb..d824015e3aa380 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -145,7 +145,6 @@ class OBJECTREF { class ReflectClassBaseObject* m_asReflectClass; class ExecutionContextObject* m_asExecutionContext; class AssemblyLoadContextBaseObject* m_asAssemblyLoadContextBase; - class AssemblyBinderObject* m_asAssemblyBinder; class BinderAssemblyObject* m_asBinderAssembly; }; From 55975ced0d7d562b494a40cc6e88ceacfa7513c3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 03:04:00 +0800 Subject: [PATCH 108/136] Cleanup AppContext --- src/coreclr/binder/CMakeLists.txt | 3 - src/coreclr/binder/applicationcontext.cpp | 222 ------------------ src/coreclr/binder/assemblybindercommon.cpp | 3 - src/coreclr/binder/customassemblybinder.cpp | 3 +- src/coreclr/binder/inc/applicationcontext.hpp | 131 ----------- src/coreclr/binder/inc/applicationcontext.inl | 71 ------ src/coreclr/binder/inc/bindertypes.hpp | 2 - src/coreclr/binder/inc/customassemblybinder.h | 1 - .../binder/inc/defaultassemblybinder.h | 1 - src/coreclr/vm/assemblybinder.cpp | 125 ---------- src/coreclr/vm/assemblybinder.h | 75 ------ src/coreclr/vm/coreassemblyspec.cpp | 1 - src/coreclr/vm/peassembly.cpp | 1 - 13 files changed, 1 insertion(+), 638 deletions(-) delete mode 100644 src/coreclr/binder/applicationcontext.cpp delete mode 100644 src/coreclr/binder/inc/applicationcontext.hpp delete mode 100644 src/coreclr/binder/inc/applicationcontext.inl diff --git a/src/coreclr/binder/CMakeLists.txt b/src/coreclr/binder/CMakeLists.txt index cc7965a766917d..310005fbda5625 100644 --- a/src/coreclr/binder/CMakeLists.txt +++ b/src/coreclr/binder/CMakeLists.txt @@ -4,7 +4,6 @@ include_directories(BEFORE "../vm") include_directories(BEFORE "inc") set(BINDER_COMMON_SOURCES - applicationcontext.cpp assembly.cpp assemblybindercommon.cpp assemblyname.cpp @@ -15,8 +14,6 @@ set(BINDER_COMMON_SOURCES ) set(BINDER_COMMON_HEADERS - inc/applicationcontext.hpp - inc/applicationcontext.inl inc/assembly.hpp inc/assembly.inl inc/assemblybindercommon.hpp diff --git a/src/coreclr/binder/applicationcontext.cpp b/src/coreclr/binder/applicationcontext.cpp deleted file mode 100644 index e41b504c8feb61..00000000000000 --- a/src/coreclr/binder/applicationcontext.cpp +++ /dev/null @@ -1,222 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// ApplicationContext.cpp -// - - -// -// Implements the ApplicationContext class -// -// ============================================================ - -#include "applicationcontext.hpp" -#include "assemblyhashtraits.hpp" -#include "stringarraylist.h" -#include "failurecache.hpp" -#include "utils.hpp" -#include "ex.h" -#include "clr/fs/path.h" -using namespace clr::fs; - -namespace BINDER_SPACE -{ - ApplicationContext::ApplicationContext() - { - m_pExecutionContext = NULL; - m_pFailureCache = NULL; - m_contextCS = NULL; - m_pTrustedPlatformAssemblyMap = nullptr; - } - - ApplicationContext::~ApplicationContext() - { - SAFE_DELETE(m_pExecutionContext); - SAFE_DELETE(m_pFailureCache); - - if (m_contextCS != NULL) - { - ClrDeleteCriticalSection(m_contextCS); - } - - if (m_pTrustedPlatformAssemblyMap != nullptr) - { - delete m_pTrustedPlatformAssemblyMap; - } - } - - HRESULT ApplicationContext::Init() - { - HRESULT hr = S_OK; - - NewHolder pExecutionContext; - - FailureCache *pFailureCache = NULL; - - // Allocate context objects - SAFE_NEW(pExecutionContext, ExecutionContext); - - SAFE_NEW(pFailureCache, FailureCache); - - m_contextCS = ClrCreateCriticalSection( - CrstFusionAppCtx, - CRST_REENTRANCY); - if (!m_contextCS) - { - SAFE_DELETE(pFailureCache); - hr = E_OUTOFMEMORY; - } - else - { - m_pExecutionContext = pExecutionContext.Extract(); - - m_pFailureCache = pFailureCache; - } - - Exit: - return hr; - } - - HRESULT ApplicationContext::SetupBindingPaths(SString &sTrustedPlatformAssemblies, - SString &sPlatformResourceRoots, - SString &sAppPaths, - BOOL fAcquireLock) - { - HRESULT hr = S_OK; - - CRITSEC_Holder contextLock(fAcquireLock ? GetCriticalSectionCookie() : NULL); - if (m_pTrustedPlatformAssemblyMap != nullptr) - { - GO_WITH_HRESULT(S_OK); - } - - // - // Parse TrustedPlatformAssemblies - // - m_pTrustedPlatformAssemblyMap = new SimpleNameToFileNameMap(); - - sTrustedPlatformAssemblies.Normalize(); - - for (SString::Iterator i = sTrustedPlatformAssemblies.Begin(); i != sTrustedPlatformAssemblies.End(); ) - { - SString fileName; - SString simpleName; - bool isNativeImage = false; - HRESULT pathResult = S_OK; - IF_FAIL_GO(pathResult = GetNextTPAPath(sTrustedPlatformAssemblies, i, /*dllOnly*/ false, fileName, simpleName, isNativeImage)); - if (pathResult == S_FALSE) - { - break; - } - - const SimpleNameToFileNameMapEntry *pExistingEntry = m_pTrustedPlatformAssemblyMap->LookupPtr(simpleName.GetUnicode()); - - if (pExistingEntry != nullptr) - { - // - // We want to store only the first entry matching a simple name we encounter. - // The exception is if we first store an IL reference and later in the string - // we encounter a native image. Since we don't touch IL in the presence of - // native images, we replace the IL entry with the NI. - // - if ((pExistingEntry->m_wszILFileName != nullptr && !isNativeImage) || - (pExistingEntry->m_wszNIFileName != nullptr && isNativeImage)) - { - continue; - } - } - - LPWSTR wszSimpleName = nullptr; - if (pExistingEntry == nullptr) - { - wszSimpleName = new WCHAR[simpleName.GetCount() + 1]; - if (wszSimpleName == nullptr) - { - GO_WITH_HRESULT(E_OUTOFMEMORY); - } - wcscpy_s(wszSimpleName, simpleName.GetCount() + 1, simpleName.GetUnicode()); - } - else - { - wszSimpleName = pExistingEntry->m_wszSimpleName; - } - - LPWSTR wszFileName = new WCHAR[fileName.GetCount() + 1]; - if (wszFileName == nullptr) - { - GO_WITH_HRESULT(E_OUTOFMEMORY); - } - wcscpy_s(wszFileName, fileName.GetCount() + 1, fileName.GetUnicode()); - - SimpleNameToFileNameMapEntry mapEntry; - mapEntry.m_wszSimpleName = wszSimpleName; - if (isNativeImage) - { - mapEntry.m_wszNIFileName = wszFileName; - mapEntry.m_wszILFileName = pExistingEntry == nullptr ? nullptr : pExistingEntry->m_wszILFileName; - } - else - { - mapEntry.m_wszILFileName = wszFileName; - mapEntry.m_wszNIFileName = pExistingEntry == nullptr ? nullptr : pExistingEntry->m_wszNIFileName; - } - - m_pTrustedPlatformAssemblyMap->AddOrReplace(mapEntry); - } - - // - // Parse PlatformResourceRoots - // - sPlatformResourceRoots.Normalize(); - for (SString::Iterator i = sPlatformResourceRoots.Begin(); i != sPlatformResourceRoots.End(); ) - { - SString pathName; - HRESULT pathResult = S_OK; - - IF_FAIL_GO(pathResult = GetNextPath(sPlatformResourceRoots, i, pathName)); - if (pathResult == S_FALSE) - { - break; - } - - if (Path::IsRelative(pathName)) - { - GO_WITH_HRESULT(E_INVALIDARG); - } - - m_platformResourceRoots.Append(pathName); - } - - // - // Parse AppPaths - // - sAppPaths.Normalize(); - for (SString::Iterator i = sAppPaths.Begin(); i != sAppPaths.End(); ) - { - SString pathName; - HRESULT pathResult = S_OK; - - IF_FAIL_GO(pathResult = GetNextPath(sAppPaths, i, pathName)); - if (pathResult == S_FALSE) - { - break; - } - - if (Path::IsRelative(pathName)) - { - GO_WITH_HRESULT(E_INVALIDARG); - } - - m_appPaths.Append(pathName); - } - - Exit: - return hr; - } - - bool ApplicationContext::IsTpaListProvided() - { - return m_pTrustedPlatformAssemblyMap != nullptr; - } -}; diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 39f7f894dc6d42..1bef16f8ac27b6 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -15,7 +15,6 @@ #include "assemblybindercommon.hpp" #include "assemblyname.hpp" #include "assembly.hpp" -#include "applicationcontext.hpp" #include "assemblyhashtraits.hpp" #include "bindertracing.h" #include "bindresult.inl" @@ -300,8 +299,6 @@ HRESULT AssemblyBinderCommon::CreateDefaultBinder(DefaultAssemblyBinder** ppDefa NewHolder pBinder; SAFE_NEW(pBinder, DefaultAssemblyBinder); - BINDER_SPACE::ApplicationContext* pApplicationContext = pBinder->GetAppContext(); - hr = pApplicationContext->Init(); if (SUCCEEDED(hr)) { pBinder->SetManagedAssemblyLoadContext(NULL); diff --git a/src/coreclr/binder/customassemblybinder.cpp b/src/coreclr/binder/customassemblybinder.cpp index 053c0af98e121b..8c37df193a55b5 100644 --- a/src/coreclr/binder/customassemblybinder.cpp +++ b/src/coreclr/binder/customassemblybinder.cpp @@ -28,7 +28,7 @@ HRESULT CustomAssemblyBinder::SetupContext(DefaultAssemblyBinder *pDefaultBinder UINT_PTR ptrAssemblyLoadContext, CustomAssemblyBinder **ppBindContext) { - HRESULT hr = E_FAIL; + HRESULT hr = S_OK; EX_TRY { if(ppBindContext != NULL) @@ -36,7 +36,6 @@ HRESULT CustomAssemblyBinder::SetupContext(DefaultAssemblyBinder *pDefaultBinder NewHolder pBinder; SAFE_NEW(pBinder, CustomAssemblyBinder); - hr = pBinder->GetAppContext()->Init(); if(SUCCEEDED(hr)) { // Save reference to the DefaultBinder that is required to be present. diff --git a/src/coreclr/binder/inc/applicationcontext.hpp b/src/coreclr/binder/inc/applicationcontext.hpp deleted file mode 100644 index 721f571af1e5d6..00000000000000 --- a/src/coreclr/binder/inc/applicationcontext.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// ApplicationContext.hpp -// - - -// -// Defines the ApplicationContext class -// -// ============================================================ - -#ifndef __BINDER__APPLICATION_CONTEXT_HPP__ -#define __BINDER__APPLICATION_CONTEXT_HPP__ - -#include "bindertypes.hpp" -#include "failurecache.hpp" -#include "stringarraylist.h" - -namespace BINDER_SPACE -{ - //============================================================================================= - // Data structures for Simple Name -> File Name hash - - // Entry in SHash table that maps namespace to list of files - struct SimpleNameToFileNameMapEntry - { - LPWSTR m_wszSimpleName; - LPWSTR m_wszILFileName; - LPWSTR m_wszNIFileName; - }; - - // SHash traits for Namespace -> FileNameList hash - class SimpleNameToFileNameMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits< SimpleNameToFileNameMapEntry > > - { - public: - typedef PCWSTR key_t; - static const SimpleNameToFileNameMapEntry Null() { SimpleNameToFileNameMapEntry e; e.m_wszSimpleName = nullptr; return e; } - static bool IsNull(const SimpleNameToFileNameMapEntry & e) { return e.m_wszSimpleName == nullptr; } - static key_t GetKey(const SimpleNameToFileNameMapEntry & e) - { - key_t key; - key = e.m_wszSimpleName; - return key; - } - static count_t Hash(const key_t &str) - { - SString ssKey(SString::Literal, str); - return ssKey.HashCaseInsensitive(); - } - static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (SString::_wcsicmp(lhs, rhs) == 0); } - - void OnDestructPerEntryCleanupAction(const SimpleNameToFileNameMapEntry & e) - { - if (e.m_wszILFileName == nullptr && e.m_wszNIFileName == nullptr) - { - // Don't delete simple name here since it's a filename only entry and will be cleaned up - // by the SimpleName -> FileName entry which reuses the same filename pointer. - return; - } - - if (e.m_wszSimpleName != nullptr) - { - delete [] e.m_wszSimpleName; - } - if (e.m_wszILFileName != nullptr) - { - delete [] e.m_wszILFileName; - } - if (e.m_wszNIFileName != nullptr) - { - delete [] e.m_wszNIFileName; - } - } - static const bool s_DestructPerEntryCleanupAction = true; - }; - - typedef SHash SimpleNameToFileNameMap; - - class AssemblyHashTraits; - typedef SHash ExecutionContext; - - class ApplicationContext - { - public: - // ApplicationContext methods - ApplicationContext(); - ~ApplicationContext(); - HRESULT Init(); - - inline SString &GetApplicationName(); - - HRESULT SetupBindingPaths(/* in */ SString &sTrustedPlatformAssemblies, - /* in */ SString &sPlatformResourceRoots, - /* in */ SString &sAppPaths, - /* in */ BOOL fAcquireLock); - - // Getters/Setter - inline ExecutionContext *GetExecutionContext(); - inline FailureCache *GetFailureCache(); - inline HRESULT AddToFailureCache(SString &assemblyNameOrPath, - HRESULT hrBindResult); - inline StringArrayList *GetAppPaths(); - inline SimpleNameToFileNameMap *GetTpaList(); - inline StringArrayList *GetPlatformResourceRoots(); - - // Using a host-configured Trusted Platform Assembly list - bool IsTpaListProvided(); - inline CRITSEC_COOKIE GetCriticalSectionCookie(); - inline LONG GetVersion(); - inline void IncrementVersion(); - - private: - Volatile m_cVersion; - SString m_applicationName; - ExecutionContext *m_pExecutionContext; - FailureCache *m_pFailureCache; - CRITSEC_COOKIE m_contextCS; - - StringArrayList m_platformResourceRoots; - StringArrayList m_appPaths; - - SimpleNameToFileNameMap * m_pTrustedPlatformAssemblyMap; - }; - -#include "applicationcontext.inl" - -}; - -#endif diff --git a/src/coreclr/binder/inc/applicationcontext.inl b/src/coreclr/binder/inc/applicationcontext.inl deleted file mode 100644 index 16ec0c6d87de2a..00000000000000 --- a/src/coreclr/binder/inc/applicationcontext.inl +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// ApplicationContext.inl -// - - -// -// Implements inlined methods of ApplicationContext -// -// ============================================================ - -#ifndef __BINDER__APPLICATION_CONTEXT_INL__ -#define __BINDER__APPLICATION_CONTEXT_INL__ - -LONG ApplicationContext::GetVersion() -{ - return m_cVersion; -} - -void ApplicationContext::IncrementVersion() -{ - InterlockedIncrement(&m_cVersion); -} - -SString &ApplicationContext::GetApplicationName() -{ - return m_applicationName; -} - -ExecutionContext *ApplicationContext::GetExecutionContext() -{ - return m_pExecutionContext; -} - -FailureCache *ApplicationContext::GetFailureCache() -{ - _ASSERTE(m_pFailureCache != NULL); - return m_pFailureCache; -} - -HRESULT ApplicationContext::AddToFailureCache(SString &assemblyNameOrPath, - HRESULT hrBindResult) -{ - HRESULT hr = GetFailureCache()->Add(assemblyNameOrPath, hrBindResult); - IncrementVersion(); - return hr; -} - -StringArrayList *ApplicationContext::GetAppPaths() -{ - return &m_appPaths; -} - -SimpleNameToFileNameMap * ApplicationContext::GetTpaList() -{ - return m_pTrustedPlatformAssemblyMap; -} - -StringArrayList * ApplicationContext::GetPlatformResourceRoots() -{ - return &m_platformResourceRoots; -} - -CRITSEC_COOKIE ApplicationContext::GetCriticalSectionCookie() -{ - return m_contextCS; -} - -#endif diff --git a/src/coreclr/binder/inc/bindertypes.hpp b/src/coreclr/binder/inc/bindertypes.hpp index 8ec573f8040d5d..093364336a3484 100644 --- a/src/coreclr/binder/inc/bindertypes.hpp +++ b/src/coreclr/binder/inc/bindertypes.hpp @@ -23,8 +23,6 @@ namespace BINDER_SPACE class AssemblyName; class Assembly; - class ApplicationContext; - class BindResult; }; diff --git a/src/coreclr/binder/inc/customassemblybinder.h b/src/coreclr/binder/inc/customassemblybinder.h index 0b98afe54bef26..1e6c9bda1bfef8 100644 --- a/src/coreclr/binder/inc/customassemblybinder.h +++ b/src/coreclr/binder/inc/customassemblybinder.h @@ -5,7 +5,6 @@ #ifndef __CUSTOM_ASSEMBLY_BINDER_H__ #define __CUSTOM_ASSEMBLY_BINDER_H__ -#include "applicationcontext.hpp" #include "defaultassemblybinder.h" #if !defined(DACCESS_COMPILE) diff --git a/src/coreclr/binder/inc/defaultassemblybinder.h b/src/coreclr/binder/inc/defaultassemblybinder.h index e690a51369b560..420fc6b9e332e9 100644 --- a/src/coreclr/binder/inc/defaultassemblybinder.h +++ b/src/coreclr/binder/inc/defaultassemblybinder.h @@ -5,7 +5,6 @@ #ifndef __DEFAULT_ASSEMBLY_BINDER_H__ #define __DEFAULT_ASSEMBLY_BINDER_H__ -#include "applicationcontext.hpp" #include "assemblybinder.h" class PEAssembly; diff --git a/src/coreclr/vm/assemblybinder.cpp b/src/coreclr/vm/assemblybinder.cpp index f1db200a14f470..2ffc7b97d6e78c 100644 --- a/src/coreclr/vm/assemblybinder.cpp +++ b/src/coreclr/vm/assemblybinder.cpp @@ -22,131 +22,6 @@ NativeImage* AssemblyBinder::LoadNativeImage(Module* componentModule, LPCUTF8 na return nativeImage; } -#ifdef FEATURE_READYTORUN -static void MvidMismatchFatalError(GUID mvidActual, GUID mvidExpected, LPCUTF8 simpleName, bool compositeComponent, LPCUTF8 assemblyRequirementName) -{ - CHAR assemblyMvidText[GUID_STR_BUFFER_LEN]; - GuidToLPSTR(mvidActual, assemblyMvidText); - - CHAR componentMvidText[GUID_STR_BUFFER_LEN]; - GuidToLPSTR(mvidExpected, componentMvidText); - - SString message; - if (compositeComponent) - { - message.Printf("MVID mismatch between loaded assembly '%s' (MVID = %s) and an assembly with the same simple name embedded in the native image '%s' (MVID = %s)", - simpleName, - assemblyMvidText, - assemblyRequirementName, - componentMvidText); - } - else - { - message.Printf("MVID mismatch between loaded assembly '%s' (MVID = %s) and version of assembly '%s' expected by assembly '%s' (MVID = %s)", - simpleName, - assemblyMvidText, - simpleName, - assemblyRequirementName, - componentMvidText); - } - - EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_FAILFAST, message.GetUnicode()); -} - -void AssemblyBinder::DeclareDependencyOnMvid(LPCUTF8 simpleName, GUID mvid, bool compositeComponent, LPCUTF8 imageName) -{ - _ASSERTE(imageName != NULL); - - // If the table is empty, then we didn't fill it with all the loaded assemblies as they were loaded. Record this detail, and fix after adding the dependency - bool addAllLoadedModules = false; - if (m_assemblySimpleNameMvidCheckHash.GetCount() == 0) - { - addAllLoadedModules = true; - } - - SimpleNameToExpectedMVIDAndRequiringAssembly* foundElem = (SimpleNameToExpectedMVIDAndRequiringAssembly*)m_assemblySimpleNameMvidCheckHash.LookupPtr(simpleName); - if (foundElem == NULL) - { - SimpleNameToExpectedMVIDAndRequiringAssembly newElem(simpleName, mvid, compositeComponent, imageName); - m_assemblySimpleNameMvidCheckHash.Add(newElem); - } - else - { - // Elem already exists. Determine if the existing elem is another one with the same mvid, in which case just record that a dependency is in play. - // If the existing elem has a different mvid, fail. - if (IsEqualGUID(mvid, foundElem->Mvid)) - { - // Mvid matches exactly. - if (foundElem->AssemblyRequirementName == NULL) - { - foundElem->AssemblyRequirementName = imageName; - foundElem->CompositeComponent = compositeComponent; - } - } - else - { - MvidMismatchFatalError(foundElem->Mvid, mvid, simpleName, compositeComponent, imageName); - } - } - - if (addAllLoadedModules) - { - for (COUNT_T assemblyIndex = 0; assemblyIndex < m_loadedAssemblies.GetCount(); assemblyIndex++) - { - DeclareLoadedAssembly(m_loadedAssemblies[assemblyIndex]); - } - } -} - -void AssemblyBinder::DeclareLoadedAssembly(Assembly* loadedAssembly) -{ - // If table is empty, then no mvid dependencies have been declared, so we don't need to record this information - if (m_assemblySimpleNameMvidCheckHash.GetCount() == 0) - return; - - GUID mvid; - loadedAssembly->GetMDImport()->GetScopeProps(NULL, &mvid); - - LPCUTF8 simpleName = loadedAssembly->GetSimpleName(); - - SimpleNameToExpectedMVIDAndRequiringAssembly* foundElem = (SimpleNameToExpectedMVIDAndRequiringAssembly*)m_assemblySimpleNameMvidCheckHash.LookupPtr(simpleName); - if (foundElem == NULL) - { - SimpleNameToExpectedMVIDAndRequiringAssembly newElem(simpleName, mvid, false, NULL); - m_assemblySimpleNameMvidCheckHash.Add(newElem); - } - else - { - // Elem already exists. Determine if the existing elem is another one with the same mvid, in which case do nothing. Everything is fine here. - // If the existing elem has a different mvid, but isn't a dependency on exact mvid elem, then set the mvid to all 0. - // If the existing elem has a different mvid, and is a dependency on exact mvid elem, then we've hit a fatal error. - if (IsEqualGUID(mvid, foundElem->Mvid)) - { - // Mvid matches exactly. - } - else if (foundElem->AssemblyRequirementName == NULL) - { - // Another loaded assembly, set the stored Mvid to all zeroes to indicate that it isn't a unique mvid - memset(&foundElem->Mvid, 0, sizeof(GUID)); - } - else - { - MvidMismatchFatalError(mvid, foundElem->Mvid, simpleName, foundElem->CompositeComponent, foundElem->AssemblyRequirementName); - } - } -} -#endif // FEATURE_READYTORUN - -void AssemblyBinder::AddLoadedAssembly(Assembly* loadedAssembly) -{ - BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); - m_loadedAssemblies.Append(loadedAssembly); - -#ifdef FEATURE_READYTORUN - DeclareLoadedAssembly(loadedAssembly); -#endif // FEATURE_READYTORUN -} - void AssemblyBinder::GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName) { if (managedALC == GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext()) diff --git a/src/coreclr/vm/assemblybinder.h b/src/coreclr/vm/assemblybinder.h index 50506cf72d96f2..3d157edbb4ce2c 100644 --- a/src/coreclr/vm/assemblybinder.h +++ b/src/coreclr/vm/assemblybinder.h @@ -5,7 +5,6 @@ #define _ASSEMBLYBINDER_H #include -#include "../binder/inc/applicationcontext.hpp" class PEImage; class NativeImage; @@ -28,11 +27,6 @@ class AssemblyBinder /// virtual bool IsDefault() = 0; - inline BINDER_SPACE::ApplicationContext* GetAppContext() - { - return &m_appContext; - } - INT_PTR GetManagedAssemblyLoadContext() { return m_ptrManagedAssemblyLoadContext; @@ -44,86 +38,17 @@ class AssemblyBinder } NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); - void AddLoadedAssembly(Assembly* loadedAssembly); void GetNameForDiagnostics(/*out*/ SString& alcName); static void GetNameForDiagnosticsFromManagedALC(INT_PTR managedALC, /* out */ SString& alcName); static void GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ SString& alcName); -#ifdef FEATURE_READYTORUN - // Must be called under the LoadLock - void DeclareDependencyOnMvid(LPCUTF8 simpleName, GUID mvid, bool compositeComponent, LPCUTF8 imageName); -#endif // FEATURE_READYTORUN - private: -#ifdef FEATURE_READYTORUN - // Must be called under the LoadLock - void DeclareLoadedAssembly(Assembly* loadedAssembly); - - struct SimpleNameToExpectedMVIDAndRequiringAssembly - { - LPCUTF8 SimpleName; - - // When an assembly is loaded, this Mvid value will be set to the mvid of the assembly. If there are multiple assemblies - // with different mvid's loaded with the same simple name, then the Mvid value will be set to all zeroes. - GUID Mvid; - - // If an assembly of this simple name is not yet loaded, but a depedency on an exact mvid is registered, then this field will - // be filled in with the simple assembly name of the first assembly loaded with an mvid dependency. - LPCUTF8 AssemblyRequirementName; - - // To disambiguate between component images of a composite image and requirements from a non-composite --inputbubble assembly, use this bool - bool CompositeComponent; - - SimpleNameToExpectedMVIDAndRequiringAssembly() : - SimpleName(NULL), - Mvid({0}), - AssemblyRequirementName(NULL), - CompositeComponent(false) - { - } - - SimpleNameToExpectedMVIDAndRequiringAssembly(LPCUTF8 simpleName, GUID mvid, bool compositeComponent, LPCUTF8 AssemblyRequirementName) : - SimpleName(simpleName), - Mvid(mvid), - AssemblyRequirementName(AssemblyRequirementName), - CompositeComponent(compositeComponent) - {} - - static SimpleNameToExpectedMVIDAndRequiringAssembly GetNull() { return SimpleNameToExpectedMVIDAndRequiringAssembly(); } - bool IsNull() const { return SimpleName == NULL; } - }; - - class SimpleNameWithMvidHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef LPCUTF8 key_t; - - static SimpleNameToExpectedMVIDAndRequiringAssembly Null() { return SimpleNameToExpectedMVIDAndRequiringAssembly::GetNull(); } - static bool IsNull(const SimpleNameToExpectedMVIDAndRequiringAssembly& e) { return e.IsNull(); } - - static LPCUTF8 GetKey(const SimpleNameToExpectedMVIDAndRequiringAssembly& e) { return e.SimpleName; } - - static BOOL Equals(LPCUTF8 a, LPCUTF8 b) { return strcmp(a, b) == 0; } // Use a case senstive comparison here even though - // assembly name matching should be case insensitive. Case insensitive - // comparisons are slow and have throwing scenarios, and this hash table - // provides a best-effort match to prevent problems, not perfection - - static count_t Hash(LPCUTF8 a) { return HashStringA(a); } // As above, this is a case sensitive hash - }; - - SHash m_assemblySimpleNameMvidCheckHash; -#endif // FEATURE_READYTORUN - - BINDER_SPACE::ApplicationContext m_appContext; - // A GC handle to the managed AssemblyLoadContext. // It is a long weak handle for collectible AssemblyLoadContexts and strong handle for non-collectible ones. INT_PTR m_ptrManagedAssemblyLoadContext; - - SArray m_loadedAssemblies; }; #endif diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 437f138cc9eaac..63bcea07490bca 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -26,7 +26,6 @@ #include "../binder/inc/assemblyname.hpp" #include "../binder/inc/assemblybindercommon.hpp" -#include "../binder/inc/applicationcontext.hpp" HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly) { diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index da1c3359d0f1bb..715e610764f257 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -18,7 +18,6 @@ #include "strongnameinternal.h" #include "object.h" -#include "../binder/inc/applicationcontext.hpp" #include "../binder/inc/assemblybindercommon.hpp" #include "sha1.h" From e75e64449ce9ea0e9c8cc7076de5b972ffc92162 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 00:29:03 +0800 Subject: [PATCH 109/136] Delete BindResult and FailureCache --- src/coreclr/binder/CMakeLists.txt | 5 - src/coreclr/binder/assemblybindercommon.cpp | 2 - src/coreclr/binder/bindertracing.cpp | 1 - src/coreclr/binder/failurecache.cpp | 76 ----------- .../binder/inc/assemblybindercommon.hpp | 1 - src/coreclr/binder/inc/bindertypes.hpp | 2 - src/coreclr/binder/inc/bindresult.hpp | 68 ---------- src/coreclr/binder/inc/bindresult.inl | 125 ------------------ src/coreclr/binder/inc/failurecache.hpp | 37 ------ .../binder/inc/failurecachehashtraits.hpp | 86 ------------ 10 files changed, 403 deletions(-) delete mode 100644 src/coreclr/binder/failurecache.cpp delete mode 100644 src/coreclr/binder/inc/bindresult.hpp delete mode 100644 src/coreclr/binder/inc/bindresult.inl delete mode 100644 src/coreclr/binder/inc/failurecache.hpp delete mode 100644 src/coreclr/binder/inc/failurecachehashtraits.hpp diff --git a/src/coreclr/binder/CMakeLists.txt b/src/coreclr/binder/CMakeLists.txt index 310005fbda5625..9ac95bf5baf04c 100644 --- a/src/coreclr/binder/CMakeLists.txt +++ b/src/coreclr/binder/CMakeLists.txt @@ -8,7 +8,6 @@ set(BINDER_COMMON_SOURCES assemblybindercommon.cpp assemblyname.cpp bindertracing.cpp - failurecache.cpp textualidentityparser.cpp utils.cpp ) @@ -25,11 +24,7 @@ set(BINDER_COMMON_HEADERS inc/assemblyversion.inl inc/bindertypes.hpp inc/bindertracing.h - inc/bindresult.hpp - inc/bindresult.inl inc/defaultassemblybinder.h - inc/failurecache.hpp - inc/failurecachehashtraits.hpp inc/textualidentityparser.hpp inc/utils.hpp ) diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 1bef16f8ac27b6..b30f21a247ff1a 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -17,8 +17,6 @@ #include "assembly.hpp" #include "assemblyhashtraits.hpp" #include "bindertracing.h" -#include "bindresult.inl" -#include "failurecache.hpp" #include "utils.hpp" #include "stringarraylist.h" #include "configuration.h" diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index 26aedc4aa76862..d17348c202be08 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -13,7 +13,6 @@ #include "common.h" #include "bindertracing.h" -#include "bindresult.hpp" #include "activitytracker.h" diff --git a/src/coreclr/binder/failurecache.cpp b/src/coreclr/binder/failurecache.cpp deleted file mode 100644 index c6e1f286fbb7ed..00000000000000 --- a/src/coreclr/binder/failurecache.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// FailureCache.cpp -// - - -// -// Implements the FailureCache class -// -// ============================================================ - -#include "failurecache.hpp" - -namespace BINDER_SPACE -{ - FailureCache::FailureCache() : SHash::SHash() - { - // Nothing to do here - } - - FailureCache::~FailureCache() - { - // Delete entries and contents array - for (Hash::Iterator i = Hash::Begin(), end = Hash::End(); i != end; i++) - { - const FailureCacheEntry *pFailureCacheEntry = *i; - delete pFailureCacheEntry; - } - RemoveAll(); - } - - HRESULT FailureCache::Add(SString &assemblyNameorPath, - HRESULT hrBindingResult) - { - HRESULT hr = S_OK; - - NewHolder pFailureCacheEntry; - SAFE_NEW(pFailureCacheEntry, FailureCacheEntry); - - // No error occurred; report the original error - hr = hrBindingResult; - - pFailureCacheEntry->GetAssemblyNameOrPath().Set(assemblyNameorPath); - pFailureCacheEntry->SetBindingResult(hrBindingResult); - - Hash::Add(pFailureCacheEntry); - pFailureCacheEntry.SuppressRelease(); - - Exit: - return hr; - } - - HRESULT FailureCache::Lookup(SString &assemblyNameorPath) - { - HRESULT hr = S_OK; - FailureCacheEntry *pFailureCachEntry = Hash::Lookup(assemblyNameorPath); - - if (pFailureCachEntry != NULL) - { - hr = pFailureCachEntry->GetBindingResult(); - } - - return hr; - } - - void FailureCache::Remove(SString &assemblyName) - { - FailureCacheEntry *pFailureCachEntry = Hash::Lookup(assemblyName); - - // Hash::Remove does not clean up entries - Hash::Remove(assemblyName); - SAFE_DELETE(pFailureCachEntry); - } -}; diff --git a/src/coreclr/binder/inc/assemblybindercommon.hpp b/src/coreclr/binder/inc/assemblybindercommon.hpp index fa26243a43750c..d67e859838735d 100644 --- a/src/coreclr/binder/inc/assemblybindercommon.hpp +++ b/src/coreclr/binder/inc/assemblybindercommon.hpp @@ -15,7 +15,6 @@ #define __BINDER__ASSEMBLY_BINDER_COMMON_HPP__ #include "bindertypes.hpp" -#include "bindresult.hpp" #include "bundle.h" class AssemblyBinder; diff --git a/src/coreclr/binder/inc/bindertypes.hpp b/src/coreclr/binder/inc/bindertypes.hpp index 093364336a3484..1188d32a149a58 100644 --- a/src/coreclr/binder/inc/bindertypes.hpp +++ b/src/coreclr/binder/inc/bindertypes.hpp @@ -22,8 +22,6 @@ namespace BINDER_SPACE class AssemblyVersion; class AssemblyName; class Assembly; - - class BindResult; }; typedef enum __AssemblyContentType diff --git a/src/coreclr/binder/inc/bindresult.hpp b/src/coreclr/binder/inc/bindresult.hpp deleted file mode 100644 index 88d1a2f4b221c5..00000000000000 --- a/src/coreclr/binder/inc/bindresult.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// BindResult.hpp -// - - -// -// Defines the BindResult class -// -// ============================================================ - -#ifndef __BINDER__BIND_RESULT_HPP__ -#define __BINDER__BIND_RESULT_HPP__ - -#include "bindertypes.hpp" - -namespace BINDER_SPACE -{ - class BindResult - { - public: - inline BindResult(); - - inline AssemblyName *GetAssemblyName(BOOL fAddRef = FALSE); - inline Assembly *GetAssembly(BOOL fAddRef = FALSE); - - inline BOOL GetIsContextBound(); - - inline void SetResult(Assembly *pAssembly, bool isInContext = false); - inline void SetResult(BindResult *pBindResult); - - inline void SetNoResult(); - inline BOOL HaveResult(); - - inline void Reset(); - - struct AttemptResult - { - HRESULT HResult; - ReleaseHolder Assembly; - bool Attempted = false; - - void Set(const AttemptResult *result); - - void Reset() - { - Assembly = nullptr; - Attempted = false; - } - }; - - // Set attempt result for binding to existing context entry or platform assemblies - void SetAttemptResult(HRESULT hr, Assembly *pAssembly, bool isInContext = false); - - const AttemptResult* GetAttempt(bool foundInContext) const; - - protected: - bool m_isContextBound; - ReleaseHolder m_pAssembly; - - AttemptResult m_inContextAttempt; - AttemptResult m_applicationAssembliesAttempt; - }; -}; - -#endif diff --git a/src/coreclr/binder/inc/bindresult.inl b/src/coreclr/binder/inc/bindresult.inl deleted file mode 100644 index ab4a61c24fbd41..00000000000000 --- a/src/coreclr/binder/inc/bindresult.inl +++ /dev/null @@ -1,125 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// BindResult.inl -// - - -// -// Implements the inline methods of BindResult -// -// ============================================================ - -#ifndef __BINDER__BIND_RESULT_INL__ -#define __BINDER__BIND_RESULT_INL__ - -#include "assembly.hpp" - -namespace BINDER_SPACE -{ -BindResult::BindResult() -{ - m_isContextBound = false; - m_pAssembly = NULL; -} - -AssemblyName *BindResult::GetAssemblyName(BOOL fAddRef /* = FALSE */) -{ - Assembly *pAssembly = m_pAssembly; - if (pAssembly == NULL) - return NULL; - - return pAssembly->GetAssemblyName(fAddRef); -} - -Assembly *BindResult::GetAssembly(BOOL fAddRef /* = FALSE */) -{ - Assembly* pAssembly = m_pAssembly; - - if (fAddRef && (pAssembly != NULL)) - { - pAssembly->AddRef(); - } - - return pAssembly; -} - -BOOL BindResult::GetIsContextBound() -{ - return m_isContextBound; -} - -void BindResult::SetResult(Assembly *pAssembly, bool isInContext) -{ - _ASSERTE(pAssembly != NULL); - - pAssembly->AddRef(); - m_pAssembly = pAssembly; - m_isContextBound = isInContext; -} - -void BindResult::SetResult(BindResult *pBindResult) -{ - _ASSERTE(pBindResult != NULL); - - m_isContextBound = pBindResult->m_isContextBound; - m_pAssembly = pBindResult->GetAssembly(TRUE /* fAddRef */); - - const AttemptResult *attempt = pBindResult->GetAttempt(true /*foundInContext*/); - if (attempt != nullptr) - m_inContextAttempt.Set(attempt); - - attempt = pBindResult->GetAttempt(false /*foundInContext*/); - if (attempt != nullptr) - m_applicationAssembliesAttempt.Set(attempt); -} - -void BindResult::SetNoResult() -{ - m_pAssembly = NULL; -} - -BOOL BindResult::HaveResult() -{ - return m_pAssembly != NULL; -} - -void BindResult::Reset() -{ - m_pAssembly = NULL; - m_isContextBound = false; - m_inContextAttempt.Reset(); - m_applicationAssembliesAttempt.Reset(); -} - -void BindResult::SetAttemptResult(HRESULT hr, Assembly *pAssembly, bool isInContext) -{ - if (pAssembly != nullptr) - pAssembly->AddRef(); - - BindResult::AttemptResult &result = isInContext ? m_inContextAttempt : m_applicationAssembliesAttempt; - result.Assembly = pAssembly; - result.HResult = hr; - result.Attempted = true; -} - -const BindResult::AttemptResult* BindResult::GetAttempt(bool foundInContext) const -{ - const BindResult::AttemptResult &result = foundInContext ? m_inContextAttempt : m_applicationAssembliesAttempt; - return result.Attempted ? &result : nullptr; -} - -void BindResult::AttemptResult::Set(const BindResult::AttemptResult *result) -{ - BINDER_SPACE::Assembly *assembly = result->Assembly; - if (assembly != nullptr) - assembly->AddRef(); - - Assembly = assembly; - HResult = result->HResult; - Attempted = result->Attempted; -} - -} -#endif diff --git a/src/coreclr/binder/inc/failurecache.hpp b/src/coreclr/binder/inc/failurecache.hpp deleted file mode 100644 index bce67b33c50c6c..00000000000000 --- a/src/coreclr/binder/inc/failurecache.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// FailureCache.hpp -// - - -// -// Defines the FailureCache class -// -// ============================================================ - - -#ifndef __BINDER__FAILURE_CACHE_HPP__ -#define __BINDER__FAILURE_CACHE_HPP__ - -#include "failurecachehashtraits.hpp" - -namespace BINDER_SPACE -{ - class FailureCache : protected SHash - { - private: - typedef SHash Hash; - public: - FailureCache(); - ~FailureCache(); - - HRESULT Add(/* in */ SString &assemblyNameorPath, - /* in */ HRESULT hrBindResult); - HRESULT Lookup(/* in */ SString &assemblyNameorPath); - void Remove(/* in */ SString &assemblyName); - }; -}; - -#endif diff --git a/src/coreclr/binder/inc/failurecachehashtraits.hpp b/src/coreclr/binder/inc/failurecachehashtraits.hpp deleted file mode 100644 index 1ffa96f56b1985..00000000000000 --- a/src/coreclr/binder/inc/failurecachehashtraits.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// FailureCache.hpp -// - - -// -// Defines the FailureCache class -// -// ============================================================ - -#ifndef __BINDER__FAILURE_CACHE_HASH_TRAITS_HPP__ -#define __BINDER__FAILURE_CACHE_HASH_TRAITS_HPP__ - -#include "bindertypes.hpp" -#include "sstring.h" -#include "shash.h" - -namespace BINDER_SPACE -{ - class FailureCacheEntry - { - public: - inline FailureCacheEntry() - { - m_hrBindingResult = S_OK; - } - inline ~FailureCacheEntry() - { - // Nothing to do here - } - - // Getters/Setters - inline SString &GetAssemblyNameOrPath() - { - return m_assemblyNameOrPath; - } - inline HRESULT GetBindingResult() - { - return m_hrBindingResult; - } - inline void SetBindingResult(HRESULT hrBindingResult) - { - m_hrBindingResult = hrBindingResult; - } - - protected: - SString m_assemblyNameOrPath; - HRESULT m_hrBindingResult; - }; - - class FailureCacheHashTraits : public DefaultSHashTraits - { - public: - typedef SString& key_t; - - // GetKey, Equals, and Hash can throw due to SString - static const bool s_NoThrow = false; - - static key_t GetKey(element_t pFailureCacheEntry) - { - return pFailureCacheEntry->GetAssemblyNameOrPath(); - } - static BOOL Equals(key_t pAssemblyNameOrPath1, key_t pAssemblyNameOrPath2) - { - return pAssemblyNameOrPath1.EqualsCaseInsensitive(pAssemblyNameOrPath2); - } - static count_t Hash(key_t pAssemblyNameOrPath) - { - return pAssemblyNameOrPath.HashCaseInsensitive(); - } - static element_t Null() - { - return NULL; - } - static bool IsNull(const element_t &propertyEntry) - { - return (propertyEntry == NULL); - } - - }; -}; - -#endif From 5cf324e1fdf4f928958cf44d403f4d68f48daaf6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 9 Nov 2023 01:09:22 +0800 Subject: [PATCH 110/136] Delete BINDER_SPACE::Assembly --- src/coreclr/binder/CMakeLists.txt | 4 - src/coreclr/binder/assembly.cpp | 77 --------------- src/coreclr/binder/assemblybindercommon.cpp | 1 - src/coreclr/binder/bindertracing.cpp | 1 + src/coreclr/binder/inc/assembly.hpp | 94 ------------------- src/coreclr/binder/inc/assembly.inl | 50 ---------- src/coreclr/binder/inc/assemblyhashtraits.hpp | 52 ---------- src/coreclr/binder/inc/bindertracing.h | 1 - src/coreclr/binder/inc/bindertypes.hpp | 1 - src/coreclr/inc/assemblybinderutil.h | 5 - src/coreclr/vm/assemblyspecbase.h | 3 +- src/coreclr/vm/coreassemblyspec.cpp | 1 - 12 files changed, 3 insertions(+), 287 deletions(-) delete mode 100644 src/coreclr/binder/assembly.cpp delete mode 100644 src/coreclr/binder/inc/assembly.hpp delete mode 100644 src/coreclr/binder/inc/assembly.inl delete mode 100644 src/coreclr/binder/inc/assemblyhashtraits.hpp diff --git a/src/coreclr/binder/CMakeLists.txt b/src/coreclr/binder/CMakeLists.txt index 9ac95bf5baf04c..0856a1b3985a04 100644 --- a/src/coreclr/binder/CMakeLists.txt +++ b/src/coreclr/binder/CMakeLists.txt @@ -4,7 +4,6 @@ include_directories(BEFORE "../vm") include_directories(BEFORE "inc") set(BINDER_COMMON_SOURCES - assembly.cpp assemblybindercommon.cpp assemblyname.cpp bindertracing.cpp @@ -13,10 +12,7 @@ set(BINDER_COMMON_SOURCES ) set(BINDER_COMMON_HEADERS - inc/assembly.hpp - inc/assembly.inl inc/assemblybindercommon.hpp - inc/assemblyhashtraits.hpp inc/assemblyidentity.hpp inc/assemblyname.hpp inc/assemblyname.inl diff --git a/src/coreclr/binder/assembly.cpp b/src/coreclr/binder/assembly.cpp deleted file mode 100644 index 9348c7b67e4e8c..00000000000000 --- a/src/coreclr/binder/assembly.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// Assembly.cpp -// - - -// -// Implements the Assembly class -// -// ============================================================ -#include "common.h" -#include "assembly.hpp" -#include "utils.hpp" -#include "assemblybindercommon.hpp" - -namespace BINDER_SPACE -{ - Assembly::Assembly() - { - m_cRef = 1; - m_pPEImage = NULL; - m_pAssemblyName = NULL; - m_isInTPA = false; - m_pBinder = NULL; - m_domainAssembly = NULL; - } - - Assembly::~Assembly() - { - SAFE_RELEASE(m_pPEImage); - SAFE_RELEASE(m_pAssemblyName); - } - - HRESULT Assembly::Init(PEImage *pPEImage, BOOL fIsInTPA) - { - HRESULT hr = S_OK; - - ReleaseHolder pAssemblyName; - SAFE_NEW(pAssemblyName, AssemblyName); - - // Get assembly name def from meta data import and store it for later refs access - IF_FAIL_GO(pAssemblyName->Init(pPEImage)); - pAssemblyName->SetIsDefinition(TRUE); - - // validate architecture - if (!AssemblyBinderCommon::IsValidArchitecture(pAssemblyName->GetArchitecture())) - { - // Assembly image can't be executed on this platform - IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); - } - - m_isInTPA = fIsInTPA; - - pPEImage->AddRef(); - m_pPEImage = pPEImage; - - // Now take ownership of assembly name - m_pAssemblyName = pAssemblyName.Extract(); - - Exit: - return hr; - } - - PEImage* Assembly::GetPEImage() - { - return m_pPEImage; - } - - LPCWSTR Assembly::GetSimpleName() - { - AssemblyName *pAsmName = GetAssemblyName(); - return (pAsmName == nullptr ? nullptr : (LPCWSTR)pAsmName->GetSimpleName()); - } -} - diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index b30f21a247ff1a..35d56c166dcdb3 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -15,7 +15,6 @@ #include "assemblybindercommon.hpp" #include "assemblyname.hpp" #include "assembly.hpp" -#include "assemblyhashtraits.hpp" #include "bindertracing.h" #include "utils.hpp" #include "stringarraylist.h" diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index d17348c202be08..6899ee8f3b5069 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -13,6 +13,7 @@ #include "common.h" #include "bindertracing.h" +#include "assemblybinder.h" #include "activitytracker.h" diff --git a/src/coreclr/binder/inc/assembly.hpp b/src/coreclr/binder/inc/assembly.hpp deleted file mode 100644 index 908e9387932650..00000000000000 --- a/src/coreclr/binder/inc/assembly.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// Assembly.hpp -// - - -// -// Defines the Assembly class -// -// ============================================================ - -#ifndef __BINDER__ASSEMBLY_HPP__ -#define __BINDER__ASSEMBLY_HPP__ - -#include "bindertypes.hpp" -#include "assemblyname.hpp" - -#include "corpriv.h" - -#include "defaultassemblybinder.h" - -#if !defined(DACCESS_COMPILE) -#include "customassemblybinder.h" -#endif // !defined(DACCESS_COMPILE) - -#include "bundle.h" -#include - -class DomainAssembly; - -namespace BINDER_SPACE -{ - // BINDER_SPACE::Assembly represents a result of binding to an actual assembly (PEImage) - // It is basically a tuple of 1) physical assembly and 2) binder which created/owns this binding - // We also store whether it was bound using TPA list - class Assembly - { - public: - ULONG AddRef(); - ULONG Release(); - - Assembly(); - virtual ~Assembly(); - - HRESULT Init(PEImage *pPEImage, BOOL fIsInTPA); - - LPCWSTR GetSimpleName(); - AssemblyName *GetAssemblyName(BOOL fAddRef = FALSE); - PEImage* GetPEImage(); - BOOL GetIsInTPA(); - - PTR_AssemblyBinder GetBinder() - { - return m_pBinder; - } - - DomainAssembly* GetDomainAssembly() - { - return m_domainAssembly; - } - - void SetDomainAssembly(DomainAssembly* value) - { - _ASSERTE(value == NULL || m_domainAssembly == NULL); - m_domainAssembly = value; - } - - private: - LONG m_cRef; - PEImage *m_pPEImage; - AssemblyName *m_pAssemblyName; - PTR_AssemblyBinder m_pBinder; - bool m_isInTPA; - DomainAssembly *m_domainAssembly; - -#if !defined(DACCESS_COMPILE) - inline void SetBinder(AssemblyBinder *pBinder) - { - _ASSERTE(m_pBinder == NULL || m_pBinder == pBinder); - m_pBinder = pBinder; - } - - friend class ::CustomAssemblyBinder; -#endif // !defined(DACCESS_COMPILE) - - friend class ::DefaultAssemblyBinder; - }; - -#include "assembly.inl" -}; - -#endif diff --git a/src/coreclr/binder/inc/assembly.inl b/src/coreclr/binder/inc/assembly.inl deleted file mode 100644 index a256be8ff5196b..00000000000000 --- a/src/coreclr/binder/inc/assembly.inl +++ /dev/null @@ -1,50 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// Assembly.inl -// - - -// -// Implements the inline methods of Assembly -// -// ============================================================ - -#ifndef __BINDER__ASSEMBLY_INL__ -#define __BINDER__ASSEMBLY_INL__ - -inline ULONG Assembly::AddRef() -{ - return InterlockedIncrement(&m_cRef); -} - -inline ULONG Assembly::Release() -{ - ULONG ulRef = InterlockedDecrement(&m_cRef); - - if (ulRef == 0) - { - delete this; - } - - return ulRef; -} - -inline AssemblyName *Assembly::GetAssemblyName(BOOL fAddRef /* = FALSE */) -{ - AssemblyName *pAssemblyName = m_pAssemblyName; - - if (fAddRef && (pAssemblyName != NULL)) - { - pAssemblyName->AddRef(); - } - return pAssemblyName; -} - -inline BOOL Assembly::GetIsInTPA() -{ - return m_isInTPA; -} - -#endif diff --git a/src/coreclr/binder/inc/assemblyhashtraits.hpp b/src/coreclr/binder/inc/assemblyhashtraits.hpp deleted file mode 100644 index c9d0cd2d7c71dd..00000000000000 --- a/src/coreclr/binder/inc/assemblyhashtraits.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ============================================================ -// -// AssemblyHashTraits.hpp -// - - -// -// Defines the AssemblyHashTraits template class -// -// ============================================================ - -#ifndef __BINDER__ASSEMBLY_HASH_TRAITS_HPP__ -#define __BINDER__ASSEMBLY_HASH_TRAITS_HPP__ - -#include "bindertypes.hpp" -#include "assembly.hpp" -#include "shash.h" - -namespace BINDER_SPACE -{ - class AssemblyHashTraits : public NoRemoveSHashTraits> - { - public: - typedef AssemblyName* key_t; - - // GetKey, Equals and Hash can throw due to SString - static const bool s_NoThrow = false; - - static key_t GetKey(const element_t& entry) - { - return entry->GetAssemblyName(); - } - static BOOL Equals(key_t pAssemblyName1, key_t pAssemblyName2) - { - return pAssemblyName1->Equals(pAssemblyName2, AssemblyName::INCLUDE_DEFAULT); - } - static count_t Hash(key_t pAssemblyName) - { - return pAssemblyName->Hash(AssemblyName::INCLUDE_DEFAULT); - } - - static const bool s_DestructPerEntryCleanupAction = true; - static void OnDestructPerEntryCleanupAction(element_t elem) - { - elem->Release(); - } - }; -}; - -#endif diff --git a/src/coreclr/binder/inc/bindertracing.h b/src/coreclr/binder/inc/bindertracing.h index d4442086ffcfc7..2e81d4dc0624bd 100644 --- a/src/coreclr/binder/inc/bindertracing.h +++ b/src/coreclr/binder/inc/bindertracing.h @@ -13,7 +13,6 @@ class PEAssembly; namespace BINDER_SPACE { - class Assembly; class AssemblyName; } diff --git a/src/coreclr/binder/inc/bindertypes.hpp b/src/coreclr/binder/inc/bindertypes.hpp index 1188d32a149a58..8592f41b7dbb69 100644 --- a/src/coreclr/binder/inc/bindertypes.hpp +++ b/src/coreclr/binder/inc/bindertypes.hpp @@ -21,7 +21,6 @@ namespace BINDER_SPACE { class AssemblyVersion; class AssemblyName; - class Assembly; }; typedef enum __AssemblyContentType diff --git a/src/coreclr/inc/assemblybinderutil.h b/src/coreclr/inc/assemblybinderutil.h index 4d6a6bcce71f78..841fa4cf346541 100644 --- a/src/coreclr/inc/assemblybinderutil.h +++ b/src/coreclr/inc/assemblybinderutil.h @@ -8,11 +8,6 @@ #ifndef __ASSEMBLY_BINDER_UTIL_H__ #define __ASSEMBLY_BINDER_UTIL_H__ -//===================================================================================================================== -// Forward declarations -typedef DPTR(BINDER_SPACE::Assembly) PTR_BINDER_SPACE_Assembly; -typedef DPTR(AssemblyBinder) PTR_AssemblyBinder; - //===================================================================================================================== #define VALIDATE_CONDITION(condition, fail_op) \ do { \ diff --git a/src/coreclr/vm/assemblyspecbase.h b/src/coreclr/vm/assemblyspecbase.h index c9db2e04b9f839..203990fb4ae71e 100644 --- a/src/coreclr/vm/assemblyspecbase.h +++ b/src/coreclr/vm/assemblyspecbase.h @@ -15,7 +15,8 @@ #ifndef __ASSEMBLY_SPEC_BASE_H__ #define __ASSEMBLY_SPEC_BASE_H__ -#include "../binder/inc/assembly.hpp" +#include "../binder/inc/assemblyname.hpp" +#include "assemblybinder.h" #include "baseassemblyspec.h" #include "baseassemblyspec.inl" diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 63bcea07490bca..0207f51c40d3a1 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -22,7 +22,6 @@ #include "strongnameholders.h" #include "../binder/inc/assemblyidentity.hpp" -#include "../binder/inc/assembly.hpp" #include "../binder/inc/assemblyname.hpp" #include "../binder/inc/assemblybindercommon.hpp" From 485ed02b0751a060a8d61ae3bfed872389948c9e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 03:44:45 +0800 Subject: [PATCH 111/136] Cleanup remaining tracing and assembly code --- src/coreclr/binder/assemblybindercommon.cpp | 112 +------------ src/coreclr/binder/bindertracing.cpp | 169 -------------------- src/coreclr/binder/inc/bindertracing.h | 66 -------- src/coreclr/vm/assemblyspecbase.h | 6 + 4 files changed, 7 insertions(+), 346 deletions(-) diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 35d56c166dcdb3..523844cf0c88cb 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -30,89 +30,6 @@ STDAPI BinderAcquirePEImage(LPCTSTR szAssemblyPath, namespace BINDER_SPACE { - namespace - { - // - // This defines the assembly equivalence relation - // - bool IsCompatibleAssemblyVersion(/* in */ AssemblyName *pRequestedName, - /* in */ AssemblyName *pFoundName) - { - AssemblyVersion *pRequestedVersion = pRequestedName->GetVersion(); - AssemblyVersion *pFoundVersion = pFoundName->GetVersion(); - - if (!pRequestedVersion->HasMajor()) - { - // An unspecified requested version component matches any value for the same component in the found version, - // regardless of lesser-order version components - return true; - } - if (!pFoundVersion->HasMajor() || pRequestedVersion->GetMajor() > pFoundVersion->GetMajor()) - { - // - A specific requested version component does not match an unspecified value for the same component in - // the found version, regardless of lesser-order version components - // - Or, the requested version is greater than the found version - return false; - } - if (pRequestedVersion->GetMajor() < pFoundVersion->GetMajor()) - { - // The requested version is less than the found version - return true; - } - - if (!pRequestedVersion->HasMinor()) - { - return true; - } - if (!pFoundVersion->HasMinor() || pRequestedVersion->GetMinor() > pFoundVersion->GetMinor()) - { - return false; - } - if (pRequestedVersion->GetMinor() < pFoundVersion->GetMinor()) - { - return true; - } - - if (!pRequestedVersion->HasBuild()) - { - return true; - } - if (!pFoundVersion->HasBuild() || pRequestedVersion->GetBuild() > pFoundVersion->GetBuild()) - { - return false; - } - if (pRequestedVersion->GetBuild() < pFoundVersion->GetBuild()) - { - return true; - } - - if (!pRequestedVersion->HasRevision()) - { - return true; - } - if (!pFoundVersion->HasRevision() || pRequestedVersion->GetRevision() > pFoundVersion->GetRevision()) - { - return false; - } - return true; - } - - HRESULT CreateImageAssembly(PEImage *pPEImage, - BindResult *pBindResult) - { - HRESULT hr = S_OK; - ReleaseHolder pAssembly; - - SAFE_NEW(pAssembly, Assembly); - IF_FAIL_GO(pAssembly->Init(pPEImage, /* fIsInTPA */ FALSE )); - - pBindResult->SetResult(pAssembly); - - Exit: - return hr; - } - }; - HRESULT AssemblyBinderCommon::TranslatePEToArchitectureType(DWORD *pdwPAFlags, PEKIND *PeKind) { HRESULT hr = S_OK; @@ -177,7 +94,7 @@ namespace BINDER_SPACE Exit: return hr; } - \ + /* static */ HRESULT AssemblyBinderCommon::BindToSystem(SString &systemDirectory, PEImage **ppPEImage) @@ -258,33 +175,6 @@ namespace BINDER_SPACE return hr; } - // - // Tests whether a candidate assembly's name matches the requested. - // This does not do a version check. The binder applies version policy - // further up the stack once it gets a successful bind. - // - BOOL TestCandidateRefMatchesDef(AssemblyName *pRequestedAssemblyName, - AssemblyName *pBoundAssemblyName, - BOOL tpaListAssembly) - { - DWORD dwIncludeFlags = AssemblyName::INCLUDE_DEFAULT; - - if (!tpaListAssembly) - { - if (pRequestedAssemblyName->IsNeutralCulture()) - { - dwIncludeFlags |= AssemblyName::EXCLUDE_CULTURE; - } - } - - if (pRequestedAssemblyName->GetArchitecture() != peNone) - { - dwIncludeFlags |= AssemblyName::INCLUDE_ARCHITECTURE; - } - - return pBoundAssemblyName->Equals(pRequestedAssemblyName, dwIncludeFlags); - } - #if !defined(DACCESS_COMPILE) HRESULT AssemblyBinderCommon::CreateDefaultBinder(DefaultAssemblyBinder** ppDefaultBinder) { diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index 6899ee8f3b5069..f7eb79c1c63d97 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -180,175 +180,6 @@ namespace BinderTracing namespace BinderTracing { - ResolutionAttemptedOperation::ResolutionAttemptedOperation(AssemblyName *assemblyName, AssemblyBinder* binder, INT_PTR managedALC, const HRESULT& hr) - : m_hr { hr } - , m_stage { Stage::NotYetStarted } - , m_tracingEnabled { BinderTracing::IsEnabled() } - , m_assemblyNameObject { assemblyName } - , m_pFoundAssembly { nullptr } - { - _ASSERTE(binder != nullptr || managedALC != 0); - - if (!m_tracingEnabled) - return; - - // When binding the main assembly (by code base instead of name), the assembly name will be null. In this special case, we just - // leave the assembly name empty. - if (m_assemblyNameObject != nullptr) - m_assemblyNameObject->GetDisplayName(m_assemblyName, AssemblyName::INCLUDE_VERSION | AssemblyName::INCLUDE_PUBLIC_KEY_TOKEN); - - if (managedALC != 0) - { - AssemblyBinder::GetNameForDiagnosticsFromManagedALC(managedALC, m_assemblyLoadContextName); - } - else - { - binder->GetNameForDiagnostics(m_assemblyLoadContextName); - } - } - - // This function simply traces out the two stages represented by the bind result. - // It does not change the stage/assembly of the ResolutionAttemptedOperation class instance. - void ResolutionAttemptedOperation::TraceBindResult(const BindResult &bindResult, bool mvidMismatch) - { - if (!m_tracingEnabled) - return; - - // Use the error message that would be reported in the file load exception - StackSString errorMsg; - if (mvidMismatch) - { - StackSString format; - format.LoadResource(CCompRC::Error, IDS_EE_FILELOAD_ERROR_GENERIC); - StackSString details; - details.LoadResource(CCompRC::Error, IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT); - errorMsg.FormatMessage(FORMAT_MESSAGE_FROM_STRING, format.GetUnicode(), 0, 0, m_assemblyName, details); - } - - const BindResult::AttemptResult *inContextAttempt = bindResult.GetAttempt(true /*foundInContext*/); - const BindResult::AttemptResult *appAssembliesAttempt = bindResult.GetAttempt(false /*foundInContext*/); - - if (inContextAttempt != nullptr) - { - // If there the attempt HR represents a success, but the tracked HR represents a failure (e.g. from further validation), report the failed HR - bool isLastAttempt = appAssembliesAttempt == nullptr; - TraceStage(Stage::FindInLoadContext, - isLastAttempt && FAILED(m_hr) && SUCCEEDED(inContextAttempt->HResult) ? m_hr : inContextAttempt->HResult, - inContextAttempt->Assembly, - mvidMismatch && isLastAttempt ? errorMsg.GetUnicode() : nullptr); - } - - if (appAssembliesAttempt != nullptr) - TraceStage(Stage::ApplicationAssemblies, FAILED(m_hr) && SUCCEEDED(appAssembliesAttempt->HResult) ? m_hr : appAssembliesAttempt->HResult, appAssembliesAttempt->Assembly, mvidMismatch ? errorMsg.GetUnicode() : nullptr); - } - - void ResolutionAttemptedOperation::TraceStage(Stage stage, HRESULT hr, BINDER_SPACE::Assembly *resultAssembly, const WCHAR *customError) - { - if (!m_tracingEnabled || stage == Stage::NotYetStarted) - return; - - PathString resultAssemblyName; - StackSString resultAssemblyPath; - if (resultAssembly != nullptr) - { - resultAssembly->GetAssemblyName()->GetDisplayName(resultAssemblyName, AssemblyName::INCLUDE_VERSION | AssemblyName::INCLUDE_PUBLIC_KEY_TOKEN); - resultAssemblyPath = resultAssembly->GetPEImage()->GetPath(); - } - - Result result; - StackSString errorMsg; - if (customError != nullptr) - { - errorMsg.Set(customError); - result = Result::Failure; - } - else if (!m_exceptionMessage.IsEmpty()) - { - errorMsg = m_exceptionMessage; - result = Result::Exception; - } - else - { - switch (hr) - { - case S_FALSE: - case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND): - static_assert(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == COR_E_FILENOTFOUND, - "COR_E_FILENOTFOUND has sane value"); - - result = Result::AssemblyNotFound; - errorMsg.Set(s_assemblyNotFoundMessage); - break; - - case FUSION_E_APP_DOMAIN_LOCKED: - result = Result::IncompatibleVersion; - - { - SString errorMsgUtf8(SString::Utf8, "Requested version"); - if (m_assemblyNameObject != nullptr) - { - const auto &reqVersion = m_assemblyNameObject->GetVersion(); - errorMsgUtf8.AppendPrintf(" %d.%d.%d.%d", - reqVersion->GetMajor(), - reqVersion->GetMinor(), - reqVersion->GetBuild(), - reqVersion->GetRevision()); - } - - errorMsgUtf8.AppendUTF8(" is incompatible with found version"); - if (resultAssembly != nullptr) - { - const auto &foundVersion = resultAssembly->GetAssemblyName()->GetVersion(); - errorMsgUtf8.AppendPrintf(" %d.%d.%d.%d", - foundVersion->GetMajor(), - foundVersion->GetMinor(), - foundVersion->GetBuild(), - foundVersion->GetRevision()); - } - errorMsg.Set(errorMsgUtf8.GetUnicode()); - } - break; - - case FUSION_E_REF_DEF_MISMATCH: - result = Result::MismatchedAssemblyName; - errorMsg.Append(W("Requested assembly name '")); - errorMsg.Append(m_assemblyName.GetUnicode()); - errorMsg.Append(W("' does not match found assembly name")); - if (resultAssembly != nullptr) - { - errorMsg.Append(W(" '")); - errorMsg.Append(resultAssemblyName.GetUnicode()); - errorMsg.Append(W("'")); - } - - break; - - default: - if (SUCCEEDED(hr)) - { - result = Result::Success; - _ASSERTE(resultAssembly != nullptr); - // Leave errorMsg empty in this case. - } - else - { - result = Result::Failure; - errorMsg.Printf("Resolution failed with HRESULT (%08x)", m_hr); - } - } - } - - FireEtwResolutionAttempted( - GetClrInstanceId(), - m_assemblyName, - static_cast(stage), - m_assemblyLoadContextName, - static_cast(result), - resultAssemblyName, - resultAssemblyPath, - errorMsg); - } - // static void ResolutionAttemptedOperation::TraceAppDomainAssemblyResolve(AssemblySpec *spec, PEAssembly *resultAssembly, Exception *exception) { diff --git a/src/coreclr/binder/inc/bindertracing.h b/src/coreclr/binder/inc/bindertracing.h index 2e81d4dc0624bd..d6efc028b69afd 100644 --- a/src/coreclr/binder/inc/bindertracing.h +++ b/src/coreclr/binder/inc/bindertracing.h @@ -91,53 +91,6 @@ namespace BinderTracing public: // static static void TraceAppDomainAssemblyResolve(AssemblySpec *spec, PEAssembly *resultAssembly, Exception *exception = nullptr); - public: - // One of native bindContext or managedALC is expected to be non-zero. If the managed ALC is set, bindContext is ignored. - ResolutionAttemptedOperation(BINDER_SPACE::AssemblyName *assemblyName, AssemblyBinder* bindContext, INT_PTR managedALC, const HRESULT& hr); - - void TraceBindResult(const BINDER_SPACE::BindResult &bindResult, bool mvidMismatch = false); - - void SetFoundAssembly(BINDER_SPACE::Assembly *assembly) - { - m_pFoundAssembly = assembly; - } - - void GoToStage(Stage stage) - { - assert(m_stage != stage); - assert(stage != Stage::NotYetStarted); - - if (!m_tracingEnabled) - return; - - // Going to a different stage should only happen if the current - // stage failed (or if the binding process wasn't yet started). - // Firing the event at this point not only helps timing each binding - // stage, but avoids keeping track of which stages were reached to - // resolve the assembly. - TraceStage(m_stage, m_hr, m_pFoundAssembly); - m_stage = stage; - m_exceptionMessage.Clear(); - } - - void SetException(Exception *ex) - { - if (!m_tracingEnabled) - return; - - ex->GetMessage(m_exceptionMessage); - } - -#ifdef FEATURE_EVENT_TRACE - ~ResolutionAttemptedOperation() - { - if (!m_tracingEnabled) - return; - - TraceStage(m_stage, m_hr, m_pFoundAssembly); - } -#endif // FEATURE_EVENT_TRACE - private: // This must match the ResolutionAttemptedResult value map in ClrEtwAll.man @@ -150,25 +103,6 @@ namespace BinderTracing Failure = 4, Exception = 5, }; - - // A reference to an HRESULT stored in the same scope as this object lets - // us determine if the last requested stage was successful or not, regardless - // if it was set through a function call (e.g. BindAssemblyByNameWorker()), or - // if an exception was thrown and captured by the EX_CATCH_HRESULT() macro. - const HRESULT &m_hr; - - Stage m_stage; - - bool m_tracingEnabled; - - BINDER_SPACE::AssemblyName *m_assemblyNameObject; - PathString m_assemblyName; - SString m_assemblyLoadContextName; - - SString m_exceptionMessage; - BINDER_SPACE::Assembly *m_pFoundAssembly; - - void TraceStage(Stage stage, HRESULT hr, BINDER_SPACE::Assembly *resultAssembly, const WCHAR *errorMessage = nullptr); }; // This must match the BindingPathSource value map in ClrEtwAll.man diff --git a/src/coreclr/vm/assemblyspecbase.h b/src/coreclr/vm/assemblyspecbase.h index 203990fb4ae71e..113c3117c1c1c7 100644 --- a/src/coreclr/vm/assemblyspecbase.h +++ b/src/coreclr/vm/assemblyspecbase.h @@ -18,6 +18,12 @@ #include "../binder/inc/assemblyname.hpp" #include "assemblybinder.h" +#include "../binder/inc/defaultassemblybinder.h" + +#if !defined(DACCESS_COMPILE) +#include "../binder/inc/customassemblybinder.h" +#endif // !defined(DACCESS_COMPILE) + #include "baseassemblyspec.h" #include "baseassemblyspec.inl" From dc3f5fc80da16f33873a82e3d2a75d59c1274b65 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 12:14:34 +0800 Subject: [PATCH 112/136] Fill managed tracer --- .../Tracing/ResolutionAttemptedOperation.cs | 20 +++++++------------ src/coreclr/binder/bindertracing.cpp | 2 +- src/coreclr/vm/assemblynative.cpp | 13 ++++++++++++ src/coreclr/vm/assemblynative.hpp | 2 ++ src/coreclr/vm/qcallentrypoints.cpp | 1 + 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs index 7bb91dae84f4c1..fbad7536234099 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Runtime.Loader.Tracing { @@ -24,7 +25,7 @@ namespace System.Runtime.Loader.Tracing // which is used to determine the success or failure of a stage either at the moment this // class is destructed (e.g. last stage), or when moving from one stage to another. (This // is especially useful if the HRESULT is captured from an exception handler.) - internal ref struct ResolutionAttemptedOperation + internal ref partial struct ResolutionAttemptedOperation { // This must match the ResolutionAttemptedStage value map in ClrEtwAll.man public enum Stage : ushort @@ -59,17 +60,11 @@ private enum Result : ushort private string _assemblyLoadContextName = string.Empty; private string? _exceptionMessage; - internal static bool IsEnabled() - { - return true; - } - - // One of native bindContext or binder is expected to be non-zero. If the managed ALC is set, binder is ignored. public ResolutionAttemptedOperation(BinderAssemblyName? assemblyName, AssemblyLoadContext binder, ref int hResult) { _hr = ref hResult; _stage = Stage.NotYetStarted; - _tracingEnabled = IsEnabled(); + _tracingEnabled = AssemblyLoadContext.IsTracingEnabled(); _assemblyNameObject = assemblyName; if (!_tracingEnabled) @@ -155,11 +150,10 @@ public void Dispose() TraceStage(_stage, _hr, _foundAssembly); } - // Foo - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string PEImage_GetPath(IntPtr pPEImage); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetPath", StringMarshalling = StringMarshalling.Utf16)] + private static unsafe partial char* PEImage_GetPath(IntPtr pPEImage); - public void TraceStage(Stage stage, int hResult, BinderAssembly? resultAssembly, string? customError = null) + private unsafe void TraceStage(Stage stage, int hResult, BinderAssembly? resultAssembly, string? customError = null) { if (!_tracingEnabled || stage == Stage.NotYetStarted) return; @@ -170,7 +164,7 @@ public void TraceStage(Stage stage, int hResult, BinderAssembly? resultAssembly, if (resultAssembly != null) { resultAssemblyName = resultAssembly.AssemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); - resultAssemblyPath = PEImage_GetPath(resultAssembly.PEImage); + resultAssemblyPath = new string(PEImage_GetPath(resultAssembly.PEImage)); } Result result; diff --git a/src/coreclr/binder/bindertracing.cpp b/src/coreclr/binder/bindertracing.cpp index f7eb79c1c63d97..cbe083157d3d23 100644 --- a/src/coreclr/binder/bindertracing.cpp +++ b/src/coreclr/binder/bindertracing.cpp @@ -95,7 +95,7 @@ namespace _ASSERTE(pPEAssembly != nullptr); pPEAssembly->GetDisplayName(request.RequestingAssembly); - AssemblyBinder *binder = /*pPEAssembly->GetAssemblyBinder()*/ NULL; + AssemblyBinder *binder = pPEAssembly->GetAssemblyBinder(); binder->GetNameForDiagnostics(request.RequestingAssemblyLoadContext); } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index c3e8b006b80e53..cb2ae672e92b14 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1615,6 +1615,19 @@ extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID) END_QCALL; } +extern "C" LPCWSTR QCALLTYPE PEImage_GetPath(PEImage * pPEImage) +{ + QCALL_CONTRACT; + + LPCWSTR result = NULL; + + BEGIN_QCALL; + + result = pPEImage->GetPath().GetUnicode(); + + END_QCALL; +} + extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 007c7f23cdf12d..c7c0c69360d3ef 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -165,6 +165,8 @@ extern "C" void QCALLTYPE PEImage_Release(PEImage * pPEImage); extern "C" void QCALLTYPE PEImage_GetMVID(PEImage * pPEImage, GUID* pMVID); +extern "C" LPCWSTR QCALLTYPE PEImage_GetPath(PEImage * pPEImage); + extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly); extern "C" void QCALLTYPE DomainAssembly_EnsureReferenceBinder(DomainAssembly * pDomainAssembly, AssemblyBinder * pBinder); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 9360caed6d4723..1c4cb17fde7aab 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -201,6 +201,7 @@ static const Entry s_QCall[] = DllImportEntry(PEImage_BinderAcquirePEImage) DllImportEntry(PEImage_Release) DllImportEntry(PEImage_GetMVID) + DllImportEntry(PEImage_GetPath) DllImportEntry(DomainAssembly_GetPEAssembly) DllImportEntry(DomainAssembly_EnsureReferenceBinder) DllImportEntry(PEAssembly_GetHostAssembly) From fd58a108d3a6a5c204140cbc960bb9265aa7f8c3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 15:41:36 +0800 Subject: [PATCH 113/136] Cleanup indent changes --- src/coreclr/vm/appdomain.hpp | 6 +++--- src/coreclr/vm/assembly.hpp | 2 +- src/coreclr/vm/assemblynative.cpp | 1 + src/coreclr/vm/assemblynative.hpp | 2 +- src/coreclr/vm/object.h | 6 ------ src/coreclr/vm/peimage.h | 2 +- src/coreclr/vm/readytoruninfo.cpp | 1 - .../src/System/Runtime/Loader/AssemblyLoadContext.cs | 4 ++-- 8 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index 892e23edb81cb7..cc974b4a726707 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1073,7 +1073,7 @@ class BaseDomain } #endif // DACCESS_COMPILE - + DefaultAssemblyBinder *GetDefaultBinder() {LIMITED_METHOD_CONTRACT; return m_pDefaultBinder; } CrstExplicitInit * GetLoaderAllocatorReferencesLock() @@ -1122,7 +1122,7 @@ class BaseDomain JitListLock m_JITLock; ListLock m_ILStubGenLock; ListLock m_NativeTypeLoadLock; - + DefaultAssemblyBinder *m_pDefaultBinder; // Reference to the binding context that holds TPA list details IGCHandleStore* m_handleStore; @@ -1966,7 +1966,7 @@ class AppDomain : public BaseDomain public: RCWRefCache *GetRCWRefCache(); #endif // FEATURE_COMWRAPPERS - + DefaultAssemblyBinder *CreateDefaultBinder(); void SetIgnoreUnhandledExceptions() diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index 98d20bb3bbf182..19c98283ffe5c5 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -65,7 +65,7 @@ class Assembly static void Initialize(); BOOL IsSystem() { WRAPPER_NO_CONTRACT; return m_pPEAssembly->IsSystem(); } - + static Assembly* CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNameParts* pAssemblyNameParts, INT32 hashAlgorithm, INT32 access, LOADERALLOCATORREF* pKeepAlive); MethodDesc *GetEntryPoint(); diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index cb2ae672e92b14..58fa83c958ee12 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1200,6 +1200,7 @@ extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyH END_QCALL; } + /*static*/ extern "C" INT_PTR QCALLTYPE AssemblyNative_InitializeAssemblyLoadContext(INT_PTR ptrManagedAssemblyLoadContext, BOOL fRepresentsTPALoadContext, BOOL fIsCollectible) diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index c7c0c69360d3ef..793b9989eae7e0 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -24,7 +24,7 @@ class AssemblyNative friend class DomainAssembly; public: - + static Assembly* LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pImage, bool excludeAppPaths = false); // static FCALLs diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 61a2a71a7a2190..b6b97769f04322 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -2275,12 +2275,6 @@ class LoaderAllocatorObject : public Object m_pLoaderAllocatorScout->m_nativeLoaderAllocator = pLoaderAllocator; } - LoaderAllocator* GetNativeLoaderAllocator() - { - LIMITED_METHOD_CONTRACT; - return m_pLoaderAllocatorScout->m_nativeLoaderAllocator; - } - // README: // If you modify the order of these fields, make sure to update the definition in // BCL for this object. diff --git a/src/coreclr/vm/peimage.h b/src/coreclr/vm/peimage.h index 6101e163b993d7..e7bfc11d319f12 100644 --- a/src/coreclr/vm/peimage.h +++ b/src/coreclr/vm/peimage.h @@ -264,7 +264,7 @@ class PEImage final static IJWFixupData* GetIJWData(void* pBase); static PTR_LoaderHeap GetDllThunkHeap(void* pBase); static void UnloadIJWModule(void* pBase); - + private: // ------------------------------------------------------------ diff --git a/src/coreclr/vm/readytoruninfo.cpp b/src/coreclr/vm/readytoruninfo.cpp index e35c7738075870..c60bee2471ee2b 100644 --- a/src/coreclr/vm/readytoruninfo.cpp +++ b/src/coreclr/vm/readytoruninfo.cpp @@ -786,7 +786,6 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, LoaderAllocator* pLoaderAllocat GCPROTECT_BEGIN(alc); - // TODO: GC mode MethodDescCallSite methDeclareDependencyOnMvid(METHOD__ASSEMBLYLOADCONTEXT__DECLARE_DEPENDENCY_ON_MVID); ARG_SLOT args[5] = { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 2941d11bb36469..99e1ed8877509e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -39,14 +39,14 @@ private enum InternalState Interlocked.CompareExchange(ref s_allContexts, new Dictionary>(), null) ?? s_allContexts; - #region private data members +#region private data members // If you modify this field, you must also update the // AssemblyLoadContextBaseObject structure in object.h // and MonoManagedAssemblyLoadContext in object-internals.h // Contains the reference to VM's representation of the AssemblyLoadContext private readonly IntPtr _nativeAssemblyLoadContext; - #endregion +#endregion // synchronization primitive to protect against usage of this instance while unloading private readonly object _unloadLock; From 87a89e4cb12007a5a1b7a0e46cfa3d9bb0305730 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 16:00:31 +0800 Subject: [PATCH 114/136] Fix --- src/coreclr/vm/assemblynative.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 58fa83c958ee12..2ee4c9282d1dd5 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1627,6 +1627,8 @@ extern "C" LPCWSTR QCALLTYPE PEImage_GetPath(PEImage * pPEImage) result = pPEImage->GetPath().GetUnicode(); END_QCALL; + + return result; } extern "C" PEAssembly * QCALLTYPE DomainAssembly_GetPEAssembly(DomainAssembly * pDomainAssembly) From 258b857e7e685fb9d2a3c396049a158aa203dade Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 16:24:01 +0800 Subject: [PATCH 115/136] Align tracing with existing ALC tracing --- .../AssemblyLoadContext.BinderCommon.cs | 14 +++++----- .../Loader/AssemblyLoadContext.CoreCLR.cs | 27 ++++++++++++------- .../Tracing/ResolutionAttemptedOperation.cs | 20 +++++--------- src/coreclr/vm/assemblynative.cpp | 24 +++++++++++++++-- src/coreclr/vm/assemblynative.hpp | 3 ++- src/coreclr/vm/qcallentrypoints.cpp | 3 ++- 6 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index ba62ffee34e59b..3bec6f94a026ea 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -284,7 +284,7 @@ private static unsafe int BindToSystemSatellite(char* systemDirectory, char* sim assembly = null; } - NativeRuntimeEventSource.Log.KnownPathProbed(sCoreLibSatellite, (ushort)pathSource, hr); + AssemblyLoadContext.TracePathProbed(sCoreLibSatellite, pathSource, hr); return hr; } @@ -477,7 +477,7 @@ private static int BindSatelliteResourceFromBundle(BinderAssemblyName requestedA hr = GetAssembly(relativePath, isInTPA: false, out BinderAssembly? assembly, bundleFileLocation); - NativeRuntimeEventSource.Log.KnownPathProbed(relativePath, (ushort)PathSource.Bundle, hr); + AssemblyLoadContext.TracePathProbed(relativePath, PathSource.Bundle, hr); // Missing files are okay and expected when probing if (hr == HResults.E_FILENOTFOUND) @@ -516,7 +516,7 @@ private static int BindSatelliteResourceByProbingPaths( { string fileName = Path.Combine(relativePath, bindingPath); int hr = GetAssembly(fileName, isInTPA: false, out BinderAssembly? assembly); - NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); + AssemblyLoadContext.TracePathProbed(fileName, pathSource, hr); // Missing files are okay and expected when probing if (hr == HResults.E_FILENOTFOUND) @@ -591,13 +591,13 @@ private static int BindAssemblyByProbingPaths(List bindingPaths, BinderA string fileName = fileNameWithoutExtension + ".dll"; int hr = GetAssembly(fileName, isInTPA: false, out BinderAssembly? assembly); - NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); + AssemblyLoadContext.TracePathProbed(fileName, pathSource, hr); if (hr < 0) { fileName = fileNameWithoutExtension + ".exe"; hr = GetAssembly(fileName, isInTPA: false, out assembly); - NativeRuntimeEventSource.Log.KnownPathProbed(fileName, (ushort)pathSource, hr); + AssemblyLoadContext.TracePathProbed(fileName, pathSource, hr); } // Since we're probing, file not founds are ok and we should just try another @@ -689,7 +689,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, BinderAss { int hr = GetAssembly(assemblyFilePath, isInTPA: true, out tpaAssembly, bundleFileLocation); - NativeRuntimeEventSource.Log.KnownPathProbed(assemblyFilePath, (ushort)PathSource.Bundle, hr); + AssemblyLoadContext.TracePathProbed(assemblyFilePath, PathSource.Bundle, hr); if (hr != HResults.E_FILENOTFOUND) { @@ -717,7 +717,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, BinderAss Debug.Assert(tpaFileName != null); int hr = GetAssembly(tpaFileName, isInTPA: true, out tpaAssembly); - NativeRuntimeEventSource.Log.KnownPathProbed(tpaFileName, (ushort)PathSource.ApplicationAssemblies, hr); + AssemblyLoadContext.TracePathProbed(tpaFileName, PathSource.ApplicationAssemblies, hr); bindResult.SetAttemptResult(hr, tpaAssembly); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 509f4eefec4858..6e3e36d88e7c01 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -38,20 +38,18 @@ public partial class AssemblyLoadContext internal static extern bool IsTracingEnabled(); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceResolvingHandlerInvoked", StringMarshalling = StringMarshalling.Utf16)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool TraceResolvingHandlerInvoked(string assemblyName, string handlerName, string? alcName, string? resultAssemblyName, string? resultAssemblyPath); + internal static partial void TraceResolvingHandlerInvoked(string assemblyName, string handlerName, string? alcName, string? resultAssemblyName, string? resultAssemblyPath); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceAssemblyResolveHandlerInvoked", StringMarshalling = StringMarshalling.Utf16)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool TraceAssemblyResolveHandlerInvoked(string assemblyName, string handlerName, string? resultAssemblyName, string? resultAssemblyPath); + internal static partial void TraceAssemblyResolveHandlerInvoked(string assemblyName, string handlerName, string? resultAssemblyName, string? resultAssemblyPath); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceAssemblyLoadFromResolveHandlerInvoked", StringMarshalling = StringMarshalling.Utf16)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool TraceAssemblyLoadFromResolveHandlerInvoked(string assemblyName, [MarshalAs(UnmanagedType.Bool)] bool isTrackedAssembly, string requestingAssemblyPath, string? requestedAssemblyPath); + internal static partial void TraceAssemblyLoadFromResolveHandlerInvoked(string assemblyName, [MarshalAs(UnmanagedType.Bool)] bool isTrackedAssembly, string requestingAssemblyPath, string? requestedAssemblyPath); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceSatelliteSubdirectoryPathProbed", StringMarshalling = StringMarshalling.Utf16)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static partial bool TraceSatelliteSubdirectoryPathProbed(string filePath, int hResult); + internal static void TraceSatelliteSubdirectoryPathProbed(string filePath, int hResult) => TracePathProbed(filePath, PathSource.SatelliteSubdirectory, hResult); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TracePathProbed", StringMarshalling = StringMarshalling.Utf16)] + internal static partial void TracePathProbed(string filePath, PathSource source, int hResult); [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] private RuntimeAssembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) @@ -192,4 +190,15 @@ private static void StopAssemblyLoad(ref Guid activityId) ActivityTracker.Instance.OnStop(NativeRuntimeEventSource.Log.Name, AssemblyLoadName, 0, ref activityId, useTplSource: false); } } + + // This must match the BindingPathSource value map in ClrEtwAll.man + internal enum PathSource : ushort + { + ApplicationAssemblies, + Unused, + AppPaths, + PlatformResourceRoots, + SatelliteSubdirectory, + Bundle + }; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs index fbad7536234099..3e95660264f248 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs @@ -231,25 +231,17 @@ private unsafe void TraceStage(Stage stage, int hResult, BinderAssembly? resultA } } - NativeRuntimeEventSource.Log.ResolutionAttempted( + TraceResolutionAttempted( _assemblyName, - (ushort)stage, + stage, _assemblyLoadContextName, - (ushort)result, + result, resultAssemblyName, resultAssemblyPath, errorMsg); } - } - // This must match the BindingPathSource value map in ClrEtwAll.man - internal enum PathSource : ushort - { - ApplicationAssemblies, - Unused, - AppPaths, - PlatformResourceRoots, - SatelliteSubdirectory, - Bundle - }; + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceResolutionAttempted", StringMarshalling = StringMarshalling.Utf16)] + private static partial void TraceResolutionAttempted(string assemblyName, Stage stage, string assemblyLoadContextName, Result result, string resultAssemblyName, string resultAssemblyPath, string errorMsg); + } } diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index 2ee4c9282d1dd5..d205092fc89004 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1389,13 +1389,33 @@ extern "C" void QCALLTYPE AssemblyNative_TraceAssemblyLoadFromResolveHandlerInvo } // static -extern "C" void QCALLTYPE AssemblyNative_TraceSatelliteSubdirectoryPathProbed(LPCWSTR filePath, HRESULT hr) +extern "C" void QCALLTYPE AssemblyNative_TracePathProbed(LPCWSTR filePath, uint16_t source, HRESULT hr) { QCALL_CONTRACT; BEGIN_QCALL; - BinderTracing::PathProbed(filePath, BinderTracing::PathSource::SatelliteSubdirectory, hr); + BinderTracing::PathProbed(filePath, static_cast(source), hr); + + END_QCALL; +} + +// static +extern "C" void QCALLTYPE AssemblyNative_TraceResolutionAttempted(LPCWSTR assemblyName, uint16_t stage, LPCWSTR assemblyLoadContextName, uint16_t result, LPCWSTR resultAssemblyName, LPCWSTR resultAssemblyPath, LPCWSTR errorMsg) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + FireEtwResolutionAttempted( + GetClrInstanceId(), + assemblyName, + stage, + assemblyLoadContextName, + result, + resultAssemblyName, + resultAssemblyPath, + errorMsg); END_QCALL; } diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 793b9989eae7e0..160a488246a399 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -138,8 +138,9 @@ extern "C" void QCALLTYPE AssemblyNative_TraceAssemblyResolveHandlerInvoked(LPCW extern "C" void QCALLTYPE AssemblyNative_TraceAssemblyLoadFromResolveHandlerInvoked(LPCWSTR assemblyName, bool isTrackedAssembly, LPCWSTR requestingAssemblyPath, LPCWSTR requestedAssemblyPath); -extern "C" void QCALLTYPE AssemblyNative_TraceSatelliteSubdirectoryPathProbed(LPCWSTR filePath, HRESULT hr); +extern "C" void QCALLTYPE AssemblyNative_TracePathProbed(LPCWSTR filePath, uint16_t source, HRESULT hr); +extern "C" void QCALLTYPE AssemblyNative_TraceResolutionAttempted(LPCWSTR assemblyName, uint16_t stage, LPCWSTR assemblyLoadContextName, uint16_t result, LPCWSTR resultAssemblyName, LPCWSTR resultAssemblyPath, LPCWSTR errorMsg); extern "C" void QCALLTYPE AssemblyNative_ApplyUpdate(QCall::AssemblyHandle assembly, UINT8* metadataDelta, INT32 metadataDeltaLength, UINT8* ilDelta, INT32 ilDeltaLength, UINT8* pdbDelta, INT32 pdbDeltaLength); diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 1c4cb17fde7aab..fe020d2e5fbb4f 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -193,7 +193,8 @@ static const Entry s_QCall[] = DllImportEntry(AssemblyNative_TraceResolvingHandlerInvoked) DllImportEntry(AssemblyNative_TraceAssemblyResolveHandlerInvoked) DllImportEntry(AssemblyNative_TraceAssemblyLoadFromResolveHandlerInvoked) - DllImportEntry(AssemblyNative_TraceSatelliteSubdirectoryPathProbed) + DllImportEntry(AssemblyNative_TracePathProbed) + DllImportEntry(AssemblyNative_TraceResolutionAttempted) DllImportEntry(AssemblyNative_GetAssemblyCount) DllImportEntry(AssemblyNative_GetEntryAssembly) DllImportEntry(AssemblyNative_GetExecutingAssembly) From e83e47293108025c19ea2e1f4e5461bcc3974a04 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 16:36:10 +0800 Subject: [PATCH 116/136] Fix GC mode for an assert --- src/coreclr/vm/ceeload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index d19781c9a1db9d..610ef628133d0b 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -3046,7 +3046,7 @@ DomainAssembly * Module::LoadAssemblyImpl(mdAssemblyRef kAssemblyRef) _ASSERTE( pDomainAssembly->IsSystem() || // GetAssemblyIfLoaded will not find CoreLib (see AppDomain::FindCachedFile) !pDomainAssembly->IsLoaded() || // GetAssemblyIfLoaded will not find not-yet-loaded assemblies - GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, (AssemblyBinder*)((BINDERASSEMBLYREF)ObjectFromHandle(pDomainAssembly->GetPEAssembly()->GetHostAssembly()))->m_binder->GetNativeAssemblyBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases + GetAssemblyIfLoaded(kAssemblyRef, NULL, FALSE, pDomainAssembly->GetPEAssembly()->GetAssemblyBinder()) != NULL); // GetAssemblyIfLoaded should find all remaining cases if (pDomainAssembly->GetAssembly() != NULL) { From ce072411231cf045de58a6e495f93f7c5f73a564 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 17:00:00 +0800 Subject: [PATCH 117/136] Cleanup --- .../System.Private.CoreLib.csproj | 1 - ...eEventSource.Binder.NativeSinks.CoreCLR.cs | 98 ------------------- src/coreclr/scripts/genRuntimeEventSources.py | 6 -- src/coreclr/vm/appdomain.cpp | 6 +- src/coreclr/vm/eventpipeinternal.cpp | 13 --- src/coreclr/vm/eventpipeinternal.h | 2 - src/coreclr/vm/nativeeventsource.cpp | 20 ---- src/coreclr/vm/nativeeventsource.h | 2 - src/coreclr/vm/qcallentrypoints.cpp | 3 - 9 files changed, 3 insertions(+), 148 deletions(-) delete mode 100644 src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 29fdbf194a73bd..9fd1af56f116b4 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -138,7 +138,6 @@ - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs deleted file mode 100644 index 4dcdf1eb680f6d..00000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.Binder.NativeSinks.CoreCLR.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace System.Diagnostics.Tracing -{ - // This is part of the NativeRuntimeEventsource, which is the managed version of the Microsoft-Windows-DotNETRuntime provider. - // It contains the runtime specific interop to native event sinks. - // - // Currently the Binder events are only used by managed binder of CoreCLR. - internal sealed unsafe partial class NativeRuntimeEventSource : EventSource - { - [NonEvent] - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_GetClrInstanceId")] - private static partial ushort GetClrInstanceId(); - - [NonEvent] - [MethodImpl(MethodImplOptions.NoInlining)] - public void ResolutionAttempted( - string AssemblyName, - ushort Stage, - string AssemblyLoadContext, - ushort Result, - string ResultAssemblyName, - string ResultAssemblyPath, - string ErrorMessage) - { - if (IsEnabled(EventLevel.Informational, Keywords.AssemblyLoaderKeyword)) - { - ResolutionAttempted(GetClrInstanceId(), AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, null, null); - } - } - - [Event(292, Level = EventLevel.Informational, Message = "", Task = default, Opcode = default, Version = 0, Keywords = Keywords.AssemblyLoaderKeyword)] - private unsafe void ResolutionAttempted( - ushort ClrInstanceId, - string AssemblyName, - ushort Stage, - string AssemblyLoadContext, - ushort Result, - string ResultAssemblyName, - string ResultAssemblyPath, - string ErrorMessage, - Guid* ActivityId = null, - Guid* RelatedActivityId = null) - { - LogResolutionAttempted(ClrInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, ActivityId, RelatedActivityId); - } - - [NonEvent] - [LibraryImport(RuntimeHelpers.QCall, StringMarshalling = StringMarshalling.Utf16)] - private static partial void LogResolutionAttempted( - ushort ClrInstanceId, - string AssemblyName, - ushort Stage, - string AssemblyLoadContext, - ushort Result, - string ResultAssemblyName, - string ResultAssemblyPath, - string ErrorMessage, - Guid* ActivityId, - Guid* RelatedActivityId); - - [NonEvent] - [MethodImpl(MethodImplOptions.NoInlining)] - public void KnownPathProbed(string FilePath, ushort Source, int Result) - { - if (IsEnabled(EventLevel.Informational, Keywords.AssemblyLoaderKeyword)) - { - KnownPathProbed(GetClrInstanceId(), FilePath, Source, Result); - } - } - - [Event(296, Level = EventLevel.Informational, Message = "", Task = default, Opcode = default, Version = 0, Keywords = Keywords.AssemblyLoaderKeyword)] - private unsafe void KnownPathProbed( - ushort ClrInstanceID, - string FilePath, - ushort Source, - int Result, - Guid* ActivityId = null, - Guid* RelatedActivityId = null) - { - LogKnownPathProbed(ClrInstanceID, FilePath, Source, Result, ActivityId, RelatedActivityId); - } - - [NonEvent] - [LibraryImport(RuntimeHelpers.QCall, StringMarshalling = StringMarshalling.Utf16)] - private static partial void LogKnownPathProbed( - ushort ClrInstanceId, - string FilePath, - ushort Source, - int Result, - Guid* ActivityId, - Guid* RelatedActivityId); - } -} diff --git a/src/coreclr/scripts/genRuntimeEventSources.py b/src/coreclr/scripts/genRuntimeEventSources.py index 4ebcee8c7caed5..f47a30f284519f 100644 --- a/src/coreclr/scripts/genRuntimeEventSources.py +++ b/src/coreclr/scripts/genRuntimeEventSources.py @@ -92,12 +92,6 @@ def generateEvent(eventNode, providerNode, outputFile, stringTable): if "Contention" in symbol: return - # Fired by managed binder - if "ResolutionAttempted" in symbol: - return - if "KnownPathProbed" in symbol: - return - evtLevel = eventNode.getAttribute("level")[4:] evtKeywords = "" # Write the event attribute. diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 045e700abcc667..53e1dcbdcd6087 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -571,7 +571,7 @@ BaseDomain::BaseDomain() FORBID_FAULT; } CONTRACTL_END; - + m_pDefaultBinder = NULL; // Make sure the container is set to NULL so that it gets loaded when it is used. @@ -682,7 +682,7 @@ void BaseDomain::ClearBinderContext() MODE_PREEMPTIVE; } CONTRACTL_END; - + if (m_pDefaultBinder) { delete m_pDefaultBinder; @@ -3596,7 +3596,7 @@ PEAssembly * AppDomain::BindAssemblySpec( // IsSystem on the PEAssembly should be false, even for CoreLib satellites result = PEAssembly::Open(boundAssembly); } - + // Setup the reference to the binder, which performed the bind, into the AssemblySpec AssemblyBinder* pBinder = result->GetAssemblyBinder(); _ASSERTE(pBinder != NULL); diff --git a/src/coreclr/vm/eventpipeinternal.cpp b/src/coreclr/vm/eventpipeinternal.cpp index 8e7ac182078077..57cf10ff30a11f 100644 --- a/src/coreclr/vm/eventpipeinternal.cpp +++ b/src/coreclr/vm/eventpipeinternal.cpp @@ -282,17 +282,4 @@ extern "C" BOOL QCALLTYPE EventPipeInternal_WaitForSessionSignal(UINT64 sessionI return result; } -extern "C" uint16_t QCALLTYPE EventPipeInternal_GetClrInstanceId() -{ - QCALL_CONTRACT; - - uint16_t result = 0; - BEGIN_QCALL; - - result = GetClrInstanceId(); - - END_QCALL; - return result; -} - #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/vm/eventpipeinternal.h b/src/coreclr/vm/eventpipeinternal.h index 362b55c996c22b..1ecbb79162e84b 100644 --- a/src/coreclr/vm/eventpipeinternal.h +++ b/src/coreclr/vm/eventpipeinternal.h @@ -94,8 +94,6 @@ extern "C" BOOL QCALLTYPE EventPipeInternal_WaitForSessionSignal( UINT64 sessionID, INT32 timeoutMs); -extern "C" uint16_t QCALLTYPE EventPipeInternal_GetClrInstanceId(); - #endif // FEATURE_PERFTRACING #endif // __EVENTPIPEINTERNAL_H__ diff --git a/src/coreclr/vm/nativeeventsource.cpp b/src/coreclr/vm/nativeeventsource.cpp index c1dba3ef156de3..b4bca0355e6c7a 100644 --- a/src/coreclr/vm/nativeeventsource.cpp +++ b/src/coreclr/vm/nativeeventsource.cpp @@ -189,24 +189,4 @@ extern "C" void QCALLTYPE LogContentionStop(uint8_t ContentionFlags, uint16_t Cl END_QCALL; } -extern "C" void QCALLTYPE LogResolutionAttempted(uint16_t CLRInstanceId, LPCWSTR AssemblyName, uint16_t Stage, LPCWSTR AssemblyLoadContext, uint16_t Result, LPCWSTR ResultAssemblyName, LPCWSTR ResultAssemblyPath, LPCWSTR ErrorMessage, LPCGUID ActivityId, LPCGUID RelatedActivityId) -{ - QCALL_CONTRACT; - BEGIN_QCALL; - - FireEtwResolutionAttempted(CLRInstanceId, AssemblyName, Stage, AssemblyLoadContext, Result, ResultAssemblyName, ResultAssemblyPath, ErrorMessage, ActivityId, RelatedActivityId); - - END_QCALL; -} - -extern "C" void QCALLTYPE LogKnownPathProbed(uint16_t CLRInstanceId, LPCWSTR FilePath, uint16_t Source, int32_t Result, LPCGUID ActivityId, LPCGUID RelatedActivityId) -{ - QCALL_CONTRACT; - BEGIN_QCALL; - - FireEtwKnownPathProbed(CLRInstanceId, FilePath, Source, Result, ActivityId, RelatedActivityId); - - END_QCALL; -} - #endif // FEATURE_PERFTRACING diff --git a/src/coreclr/vm/nativeeventsource.h b/src/coreclr/vm/nativeeventsource.h index d4bc30040c7d81..a407c4b5ebb10b 100644 --- a/src/coreclr/vm/nativeeventsource.h +++ b/src/coreclr/vm/nativeeventsource.h @@ -31,8 +31,6 @@ extern "C" void QCALLTYPE LogThreadPoolIOPack(_In_z_ void* nativeOverlapped, _In extern "C" void QCALLTYPE LogContentionLockCreated(void* LockID, void* AssociatedObjectID, uint16_t ClrInstanceID); extern "C" void QCALLTYPE LogContentionStart(uint8_t ContentionFlags, uint16_t ClrInstanceID, void* LockID, void* AssociatedObjectID, uint64_t LockOwnerThreadID); extern "C" void QCALLTYPE LogContentionStop(uint8_t ContentionFlags, uint16_t ClrInstanceID, double DurationNs); -extern "C" void QCALLTYPE LogResolutionAttempted(uint16_t CLRInstanceId, LPCWSTR AssemblyName, uint16_t Stage, LPCWSTR AssemblyLoadContext, uint16_t Result, LPCWSTR ResultAssemblyName, LPCWSTR ResultAssemblyPath, LPCWSTR ErrorMessage, LPCGUID ActivityId, LPCGUID RelatedActivityId); -extern "C" void QCALLTYPE LogKnownPathProbed(uint16_t CLRInstanceId, LPCWSTR FilePath, uint16_t Source, int32_t Result, LPCGUID ActivityId, LPCGUID RelatedActivityId); #endif // defined(FEATURE_PERFTRACING) #endif //_NATIVEEVENTSOURCE_H_ diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index fe020d2e5fbb4f..5e61f7ef3ce0b3 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -299,8 +299,6 @@ static const Entry s_QCall[] = DllImportEntry(LogContentionLockCreated) DllImportEntry(LogContentionStart) DllImportEntry(LogContentionStop) - DllImportEntry(LogResolutionAttempted) - DllImportEntry(LogKnownPathProbed) DllImportEntry(EventPipeInternal_Enable) DllImportEntry(EventPipeInternal_Disable) DllImportEntry(EventPipeInternal_GetSessionInfo) @@ -313,7 +311,6 @@ static const Entry s_QCall[] = DllImportEntry(EventPipeInternal_GetNextEvent) DllImportEntry(EventPipeInternal_SignalSession) DllImportEntry(EventPipeInternal_WaitForSessionSignal) - DllImportEntry(EventPipeInternal_GetClrInstanceId) #endif #if defined(TARGET_UNIX) DllImportEntry(CloseHandle) From 354c3590b7ace5559b720be2b513045492dc0fb7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 18:40:15 +0800 Subject: [PATCH 118/136] SourceGen can't generate for ref struct --- .../AssemblyLoadContext.BinderCommon.cs | 14 +++-- .../Loader/AssemblyLoadContext.CoreCLR.cs | 3 + .../Tracing/ResolutionAttemptedOperation.cs | 63 ++++++++----------- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 3bec6f94a026ea..a0970230047da0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.Tracing; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; @@ -34,7 +33,7 @@ internal struct BundleFileLocation internal static partial class AssemblyBinderCommon { [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquireImport")] - public static unsafe partial IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); + internal static unsafe partial IntPtr BinderAcquireImport(IntPtr pPEImage, int* pdwPAFlags); [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_BinderAcquirePEImage", StringMarshalling = StringMarshalling.Utf16)] private static unsafe partial int BinderAcquirePEImage(string szAssemblyPath, out IntPtr ppPEImage, BundleFileLocation bundleFileLocation); @@ -45,6 +44,9 @@ internal static partial class AssemblyBinderCommon [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetMVID")] internal static partial void PEImage_GetMVID(IntPtr pPEImage, out Guid mvid); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetPath", StringMarshalling = StringMarshalling.Utf16)] + internal static unsafe partial char* PEImage_GetPath(IntPtr pPEImage); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Bundle_AppIsBundle")] [return: MarshalAs(UnmanagedType.Bool)] private static partial bool AppIsBundle(); @@ -1143,7 +1145,7 @@ internal static int BindUsingHostAssemblyResolver( { // Step 2 (of CustomAssemblyBinder::BindAssemblyByName) - Invoke Load method // This is not invoked for TPA Binder since it always returns NULL. - tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextLoad); + tracer.GoToStage(Stage.AssemblyLoadContextLoad); refLoadedAssembly = binder.ResolveUsingLoad(refAssemblyName); if (refLoadedAssembly != null) @@ -1156,7 +1158,7 @@ internal static int BindUsingHostAssemblyResolver( // Step 3 (of CustomAssemblyBinder::BindAssemblyByName) if (!fResolvedAssembly && !isSatelliteAssemblyRequest) { - tracer.GoToStage(ResolutionAttemptedOperation.Stage.DefaultAssemblyLoadContextFallback); + tracer.GoToStage(Stage.DefaultAssemblyLoadContextFallback); // If we could not resolve the assembly using Load method, then attempt fallback with TPA Binder. // Since TPA binder cannot fallback to itself, this fallback does not happen for binds within TPA binder. @@ -1176,7 +1178,7 @@ internal static int BindUsingHostAssemblyResolver( // Step 4 (of CustomAssemblyBinder::BindAssemblyByName) // Attempt to resolve it using the ResolveSatelliteAssembly method. - tracer.GoToStage(ResolutionAttemptedOperation.Stage.ResolveSatelliteAssembly); + tracer.GoToStage(Stage.ResolveSatelliteAssembly); refLoadedAssembly = binder.ResolveSatelliteAssembly(refAssemblyName); if (refLoadedAssembly != null) @@ -1194,7 +1196,7 @@ internal static int BindUsingHostAssemblyResolver( // If we couldn't resolve the assembly using TPA LoadContext as well, then // attempt to resolve it using the Resolving event. - tracer.GoToStage(ResolutionAttemptedOperation.Stage.AssemblyLoadContextResolvingEvent); + tracer.GoToStage(Stage.AssemblyLoadContextResolvingEvent); refLoadedAssembly = binder.ResolveUsingEvent(refAssemblyName); if (refLoadedAssembly != null) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 6e3e36d88e7c01..962b4a3b307805 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -51,6 +51,9 @@ public partial class AssemblyLoadContext [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TracePathProbed", StringMarshalling = StringMarshalling.Utf16)] internal static partial void TracePathProbed(string filePath, PathSource source, int hResult); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceResolutionAttempted", StringMarshalling = StringMarshalling.Utf16)] + internal static partial void TraceResolutionAttempted(string assemblyName, Tracing.Stage stage, string assemblyLoadContextName, Tracing.Result result, string resultAssemblyName, string resultAssemblyPath, string errorMsg); + [RequiresUnreferencedCode("Types and members the loaded assembly depends on might be removed")] private RuntimeAssembly InternalLoadFromPath(string? assemblyPath, string? nativeImagePath) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs index 3e95660264f248..a2be06f4145368 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs @@ -2,12 +2,33 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Diagnostics.Tracing; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace System.Runtime.Loader.Tracing { + // This must match the ResolutionAttemptedStage value map in ClrEtwAll.man + internal enum Stage : ushort + { + FindInLoadContext = 0, + AssemblyLoadContextLoad = 1, + ApplicationAssemblies = 2, + DefaultAssemblyLoadContextFallback = 3, + ResolveSatelliteAssembly = 4, + AssemblyLoadContextResolvingEvent = 5, + AppDomainAssemblyResolveEvent = 6, + NotYetStarted = 0xffff, // Used as flag to not fire event; not present in value map + }; + + // This must match the ResolutionAttemptedResult value map in ClrEtwAll.man + internal enum Result : ushort + { + Success = 0, + AssemblyNotFound = 1, + IncompatibleVersion = 2, + MismatchedAssemblyName = 3, + Failure = 4, + Exception = 5, + }; + // An object of this class manages firing events for all the stages during a binder resolving // attempt operation. It has minimal cost if tracing for this event is disabled. // @@ -25,32 +46,8 @@ namespace System.Runtime.Loader.Tracing // which is used to determine the success or failure of a stage either at the moment this // class is destructed (e.g. last stage), or when moving from one stage to another. (This // is especially useful if the HRESULT is captured from an exception handler.) - internal ref partial struct ResolutionAttemptedOperation + internal ref struct ResolutionAttemptedOperation { - // This must match the ResolutionAttemptedStage value map in ClrEtwAll.man - public enum Stage : ushort - { - FindInLoadContext = 0, - AssemblyLoadContextLoad = 1, - ApplicationAssemblies = 2, - DefaultAssemblyLoadContextFallback = 3, - ResolveSatelliteAssembly = 4, - AssemblyLoadContextResolvingEvent = 5, - AppDomainAssemblyResolveEvent = 6, - NotYetStarted = 0xffff, // Used as flag to not fire event; not present in value map - }; - - // This must match the ResolutionAttemptedResult value map in ClrEtwAll.man - private enum Result : ushort - { - Success = 0, - AssemblyNotFound = 1, - IncompatibleVersion = 2, - MismatchedAssemblyName = 3, - Failure = 4, - Exception = 5, - }; - private ref readonly int _hr; private Stage _stage; private bool _tracingEnabled; @@ -150,9 +147,6 @@ public void Dispose() TraceStage(_stage, _hr, _foundAssembly); } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "PEImage_GetPath", StringMarshalling = StringMarshalling.Utf16)] - private static unsafe partial char* PEImage_GetPath(IntPtr pPEImage); - private unsafe void TraceStage(Stage stage, int hResult, BinderAssembly? resultAssembly, string? customError = null) { if (!_tracingEnabled || stage == Stage.NotYetStarted) @@ -164,7 +158,7 @@ private unsafe void TraceStage(Stage stage, int hResult, BinderAssembly? resultA if (resultAssembly != null) { resultAssemblyName = resultAssembly.AssemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); - resultAssemblyPath = new string(PEImage_GetPath(resultAssembly.PEImage)); + resultAssemblyPath = new string(AssemblyBinderCommon.PEImage_GetPath(resultAssembly.PEImage)); } Result result; @@ -231,7 +225,7 @@ private unsafe void TraceStage(Stage stage, int hResult, BinderAssembly? resultA } } - TraceResolutionAttempted( + AssemblyLoadContext.TraceResolutionAttempted( _assemblyName, stage, _assemblyLoadContextName, @@ -240,8 +234,5 @@ private unsafe void TraceStage(Stage stage, int hResult, BinderAssembly? resultA resultAssemblyPath, errorMsg); } - - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_TraceResolutionAttempted", StringMarshalling = StringMarshalling.Utf16)] - private static partial void TraceResolutionAttempted(string assemblyName, Stage stage, string assemblyLoadContextName, Result result, string resultAssemblyName, string resultAssemblyPath, string errorMsg); } } From e5487b3f513e91e567d9533a84d36def390a3dc9 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 19:57:15 +0800 Subject: [PATCH 119/136] Remove usage of record struct --- .../src/System/Runtime/Loader/ApplicationContext.cs | 9 ++------- .../Loader/AssemblyLoadContext.BinderCommon.cs | 6 +++--- .../src/System/Runtime/Loader/AssemblyName.cs | 2 +- .../src/System/Runtime/Loader/AssemblyVersion.cs | 13 ++++++++++++- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs index 3f34ca0c687787..235ec15015cbf9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs @@ -14,11 +14,6 @@ internal struct TPAEntry public string? NIFileName; } - internal record struct FailureCacheKey(string SimpleName, AssemblyVersion Version) - { - public FailureCacheKey(BinderAssemblyName assemblyName) : this(assemblyName.SimpleName, assemblyName.Version) { } - } - internal sealed class ApplicationContext { private volatile int _version; @@ -27,7 +22,7 @@ internal sealed class ApplicationContext public Dictionary ExecutionContext { get; } = new Dictionary(); - public Dictionary FailureCache { get; } = new Dictionary(); + public Dictionary<(string SimpleName, AssemblyVersion Version), int> FailureCache { get; } = new Dictionary<(string SimpleName, AssemblyVersion Version), int>(); public object ContextCriticalSection { get; } = new object(); @@ -281,7 +276,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string public void AddToFailureCache(BinderAssemblyName assemblyName, int hresult) { - FailureCache.Add(new FailureCacheKey(assemblyName), hresult); + FailureCache.Add((assemblyName.SimpleName, assemblyName.Version), hresult); IncrementVersion(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index a0970230047da0..21e31c6060de8d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -301,14 +301,14 @@ private static int BindByName( { // Look for already cached binding failure (ignore PA, every PA will lock the context) - if (applicationContext.FailureCache.TryGetValue(new FailureCacheKey(assemblyName), out int hr)) + if (applicationContext.FailureCache.TryGetValue((assemblyName.SimpleName, assemblyName.Version), out int hr)) { if (hr < 0) // FAILED(hr) { if (hr == HResults.E_FILENOTFOUND && skipFailureChecking) { // Ignore pre-existing transient bind error (re-bind will succeed) - applicationContext.FailureCache.Remove(new FailureCacheKey(assemblyName)); + applicationContext.FailureCache.Remove((assemblyName.SimpleName, assemblyName.Version)); } return hr; // goto LogExit @@ -929,7 +929,7 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi Debug.Assert(bindResult.Assembly.AssemblyName != null); // Look for already cached binding failure (ignore PA, every PA will lock the context) - if (!applicationContext.FailureCache.ContainsKey(new FailureCacheKey(bindResult.Assembly.AssemblyName))) // hr == S_OK + if (!applicationContext.FailureCache.ContainsKey((bindResult.Assembly.AssemblyName.SimpleName, bindResult.Assembly.AssemblyName.Version))) // hr == S_OK { int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out BinderAssembly? assembly); if (hr >= 0 && assembly != null) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index 33bee27511c72d..f6de8f2cbdfd6e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -349,7 +349,7 @@ public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFl if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_VERSION) != 0)) { - fEquals = Version == other.Version; + fEquals = Version.Equals(other.Version); } if (fEquals && ((dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_RETARGETABLE) != 0)) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs index 55398e832dc5c4..94fb43c299055f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyVersion.cs @@ -3,7 +3,7 @@ namespace System.Runtime.Loader { - internal record struct AssemblyVersion + internal struct AssemblyVersion : IEquatable { public int Major; public int Minor; @@ -27,5 +27,16 @@ public AssemblyVersion() public bool HasBuild => Build != Unspecified; public bool HasRevision => Revision != Unspecified; + + public bool Equals(AssemblyVersion other) => + Major == other.Major && + Minor == other.Minor && + Build == other.Build && + Revision == other.Revision; + + public override bool Equals(object? obj) + => obj is AssemblyVersion other && Equals(other); + + public override int GetHashCode() => HashCode.Combine(Major, Minor, Build, Revision); } } From e35aa059a1a6bc98b23b064f00a253542a0478e2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 20:12:22 +0800 Subject: [PATCH 120/136] Load lock cleanup --- .../Loader/AssemblyLoadContext.Binder.cs | 20 +++++-------------- src/coreclr/vm/appdomain.cpp | 3 +++ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index 689377637ae791..abcdab6c49c2ae 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -36,25 +36,17 @@ private protected unsafe int BindAssemblyByName(void* pAssemblyNameData, out Bin internal ApplicationContext AppContext { get; } = new ApplicationContext(); - // NativeImage* LoadNativeImage(Module* componentModule, LPCUTF8 nativeImageName); - // called by vm + // ensure to call with BaseDomain::LoadLockHolder in native (from native binder) private void AddLoadedAssembly(IntPtr loadedAssembly) { - // BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); - // TODO: is the lock shared outside this type? - lock (_loadLock) - { - _loadedAssemblies.Add(loadedAssembly); + _loadedAssemblies.Add(loadedAssembly); - // #ifdef FEATURE_READYTORUN - DeclareLoadedAssembly(loadedAssembly); - // #endif // FEATURE_READYTORUN - } + // #ifdef FEATURE_READYTORUN + DeclareLoadedAssembly(loadedAssembly); + // #endif // FEATURE_READYTORUN } - // static void GetNameForDiagnosticsFromSpec(AssemblySpec* spec, /*out*/ SString& alcName); - //# ifdef FEATURE_READYTORUN private static void MvidMismatchFatalError(Guid mvidActual, Guid mvidExpected, string simpleName, bool compositeComponent, string assemblyRequirementName) @@ -191,8 +183,6 @@ private struct SimpleNameToExpectedMVIDAndRequiringAssembly private readonly Dictionary _assemblySimpleNameMvidCheckHash = new Dictionary(); private readonly List _loadedAssemblies = new List(); - private static readonly object _loadLock = new object(); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AssemblyNative_GetMDImport")] private static partial IntPtr Assembly_GetMDImport(IntPtr pAssembly); diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 53e1dcbdcd6087..281aed7d902b1d 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -2819,6 +2819,9 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity, if (registerNewAssembly && !pDomainAssembly->GetAssembly()->IsSystem()) // CoreLib bootstrap { + // Ensure to call AddLoadedAssembly under load lock + BaseDomain::LoadLockHolder lock(AppDomain::GetCurrentDomain()); + GCX_COOP(); ASSEMBLYLOADCONTEXTREF managedALC = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)(pPEAssembly->GetAssemblyBinder()->GetManagedAssemblyLoadContext())); From 5af68d7fd893b747e6aa234db463868a899048cc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 20:31:35 +0800 Subject: [PATCH 121/136] Cleanup exception --- .../AssemblyLoadContext.BinderCommon.cs | 2 +- .../src/System/Runtime/Loader/AssemblyName.cs | 19 +++++++++++++------ .../src/Resources/Strings.resx | 5 ++++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 21e31c6060de8d..e231e1b4fff55c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -1242,7 +1242,7 @@ internal static int BindUsingHostAssemblyResolver( if (fFailLoad) { // string name = assemblyName.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_ALL); - throw new InvalidOperationException("Dynamically emitted assemblies are unsupported during host-based resolution."); // IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED + throw new InvalidOperationException(SR.Host_AssemblyResolver_DynamicallyEmittedAssemblies_Unsupported); } // For collectible assemblies, ensure that the parent loader allocator keeps the assembly's loader allocator diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index f6de8f2cbdfd6e..675af7a4389a5f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.IO; using System.Numerics; using System.Reflection; @@ -84,10 +85,10 @@ public BinderAssemblyName(IntPtr pPEImage) // Get name and metadata scope.GetAssemblyProps( mda, - out var pvPublicKeyToken, - out var dwPublicKeyToken, - out var dwHashAlgId, - out var assemblyName, + out byte* pvPublicKeyToken, + out uint dwPublicKeyToken, + out uint dwHashAlgId, + out string? assemblyName, &amd, out uint flags); @@ -109,7 +110,10 @@ public BinderAssemblyName(IntPtr pPEImage) const int MAX_PATH_FNAME = 260; if (assemblyName.Length >= MAX_PATH_FNAME) { - throw new Exception("FUSION_E_INVALID_NAME"); + throw new FileLoadException + { + HResult = HResults.FUSION_E_INVALID_NAME + }; } SimpleName = assemblyName; @@ -130,7 +134,10 @@ public BinderAssemblyName(IntPtr pPEImage) else { // We no longer support WindowsRuntime assembly. - throw new Exception("FUSION_E_INVALID_NAME"); + throw new FileLoadException + { + HResult = HResults.FUSION_E_INVALID_NAME + }; } // Set the assembly version diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 996cd81753de7d..87bdd89505432f 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -4289,4 +4289,7 @@ Assembly with same name is already loaded. - + + Dynamically emitted assemblies are unsupported during host-based resolution. + + \ No newline at end of file From 1f53d77838b3a269109460ac318d175bb78f223b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 16 Nov 2023 21:09:43 +0800 Subject: [PATCH 122/136] Fix callsite compiling --- src/coreclr/vm/assemblynative.cpp | 4 ++-- src/coreclr/vm/coreassemblyspec.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index d205092fc89004..a854c9f47d6173 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -152,11 +152,11 @@ Assembly* AssemblyNative::LoadFromPEImage(AssemblyBinder* pBinder, PEImage *pIma GCX_COOP(); struct { - ASSEMBLYLOADCONTEXTREF pBinder; + OBJECTREF pBinder; BINDERASSEMBLYREF pAssembly; } gc; - gc.pBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)(pBinder->GetManagedAssemblyLoadContext())); + gc.pBinder = ObjectFromHandle((OBJECTHANDLE)(pBinder->GetManagedAssemblyLoadContext())); gc.pAssembly = NULL; GCPROTECT_BEGIN(gc); diff --git a/src/coreclr/vm/coreassemblyspec.cpp b/src/coreclr/vm/coreassemblyspec.cpp index 0207f51c40d3a1..6a77760820fb6b 100644 --- a/src/coreclr/vm/coreassemblyspec.cpp +++ b/src/coreclr/vm/coreassemblyspec.cpp @@ -46,12 +46,12 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly struct { - ASSEMBLYLOADCONTEXTREF pBinder; + OBJECTREF pBinder; BINDERASSEMBLYREF pPrivAsm; } gc; // Have a default binding context setup - gc.pBinder = (ASSEMBLYLOADCONTEXTREF)ObjectFromHandle((OBJECTHANDLE)GetBinderFromParentAssembly(pAppDomain)->GetManagedAssemblyLoadContext()); + gc.pBinder = ObjectFromHandle((OBJECTHANDLE)GetBinderFromParentAssembly(pAppDomain)->GetManagedAssemblyLoadContext()); gc.pPrivAsm = NULL; _ASSERTE(gc.pBinder != NULL); @@ -84,7 +84,7 @@ HRESULT AssemblySpec::Bind(AppDomain *pAppDomain, BINDERASSEMBLYREF* ppAssembly AssemblyNameData assemblyNameData = { 0 }; PopulateAssemblyNameData(assemblyNameData); - MethodDescCallSite methBindAssemblyByName(METHOD__ASSEMBLYLOADCONTEXT__BIND_ASSEMBLY_BY_NAME); + MethodDescCallSite methBindAssemblyByName(METHOD__ASSEMBLYLOADCONTEXT__BIND_ASSEMBLY_BY_NAME, &gc.pBinder); ARG_SLOT args[3] = { ObjToArgSlot(gc.pBinder), From 65b2198b7ecfffda9958722b2a5ea370d067b288 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 17 Nov 2023 03:25:42 +0800 Subject: [PATCH 123/136] Fix GC mode in CreateDynamic --- src/coreclr/vm/peassembly.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/peassembly.cpp b/src/coreclr/vm/peassembly.cpp index 715e610764f257..6272b993a12a67 100644 --- a/src/coreclr/vm/peassembly.cpp +++ b/src/coreclr/vm/peassembly.cpp @@ -875,7 +875,11 @@ PEAssembly *PEAssembly::Create(IMetaDataAssemblyEmit *pAssemblyEmit) // we have.) SafeComHolder pEmit; pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void **)&pEmit); - RETURN new PEAssembly(NULL, pEmit, FALSE); + + { + GCX_COOP(); + RETURN new PEAssembly(NULL, pEmit, FALSE); + } } #endif // #ifndef DACCESS_COMPILE From 8098ff4622e19e8d2f748169ef15866b7be2f461 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 17 Nov 2023 03:56:44 +0800 Subject: [PATCH 124/136] Move CoreLib binder setup after g_fEEStarted --- src/coreclr/vm/appdomain.cpp | 61 ++++++++++++++++++++++-------------- src/coreclr/vm/appdomain.hpp | 1 + src/coreclr/vm/ceemain.cpp | 2 ++ 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 281aed7d902b1d..5a400b2f5c1291 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1161,30 +1161,6 @@ void SystemDomain::Init() // Finish loading CoreLib now. m_pSystemAssembly->GetDomainAssembly()->EnsureActive(); - - // AdHoc setting logic for CoreLib, since managed code isn't available during CoreLib bootstrap - { - // Initialize managed default binder and set binder assembly for CoreLib - MethodDescCallSite initializeDefault(METHOD__ASSEMBLYLOADCONTEXT__INITIALIZE_DEFAULT); - ARG_SLOT arg = PtrToArgSlot(m_pSystemAssembly); - OBJECTREF coreLibHostAssembly = initializeDefault.Call_RetOBJECTREF(&arg); - - // Default binder should be initialized - _ASSERTE(GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext() != NULL); - - m_pSystemPEAssembly->SetHostAssemblyAdHoc(CreateHandle(coreLibHostAssembly)); - - m_pSystemAssembly->GetDomainAssembly()->RegisterWithHostAssembly(); - - // Managed and unmanaged representations of CoreLib should be correctly linked - _ASSERTE(((BINDERASSEMBLYREF)coreLibHostAssembly)->m_pDomainAssembly == m_pSystemAssembly->GetDomainAssembly()); - _ASSERTE(ObjectFromHandle(m_pSystemPEAssembly->GetHostAssembly()) == coreLibHostAssembly); - - // Add CoreLib to AssemblyBindingCache - AssemblySpec spec; - spec.InitializeSpec(m_pSystemPEAssembly); - GetAppDomain()->AddAssemblyToCache(&spec, m_pSystemAssembly->GetDomainAssembly()); - } } #ifdef _DEBUG @@ -1197,6 +1173,43 @@ void SystemDomain::Init() #endif // _DEBUG } +void SystemDomain::PostStartInit() +{ + CONTRACTL + { + THROWS; + GC_TRIGGERS; + MODE_ANY; + INJECT_FAULT(COMPlusThrowOM();); + } + CONTRACTL_END; + + GCX_COOP(); + + // AdHoc setting logic for CoreLib, since managed code isn't available during CoreLib bootstrap + + // Initialize managed default binder and set binder assembly for CoreLib + MethodDescCallSite initializeDefault(METHOD__ASSEMBLYLOADCONTEXT__INITIALIZE_DEFAULT); + ARG_SLOT arg = PtrToArgSlot(m_pSystemAssembly); + OBJECTREF coreLibHostAssembly = initializeDefault.Call_RetOBJECTREF(&arg); + + // Default binder should be initialized + _ASSERTE(GetAppDomain()->GetDefaultBinder()->GetManagedAssemblyLoadContext() != NULL); + + m_pSystemPEAssembly->SetHostAssemblyAdHoc(CreateHandle(coreLibHostAssembly)); + + m_pSystemAssembly->GetDomainAssembly()->RegisterWithHostAssembly(); + + // Managed and unmanaged representations of CoreLib should be correctly linked + _ASSERTE(((BINDERASSEMBLYREF)coreLibHostAssembly)->m_pDomainAssembly == m_pSystemAssembly->GetDomainAssembly()); + _ASSERTE(ObjectFromHandle(m_pSystemPEAssembly->GetHostAssembly()) == coreLibHostAssembly); + + // Add CoreLib to AssemblyBindingCache + AssemblySpec spec; + spec.InitializeSpec(m_pSystemPEAssembly); + GetAppDomain()->AddAssemblyToCache(&spec, m_pSystemAssembly->GetDomainAssembly()); +} + void SystemDomain::LazyInitGlobalStringLiteralMap() { CONTRACTL diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index cc974b4a726707..b0b0ec24a8de44 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -2368,6 +2368,7 @@ class SystemDomain : public BaseDomain void operator delete(void *pMem); #endif void Init(); + void PostStartInit(); void Stop(); static void LazyInitGlobalStringLiteralMap(); static void LazyInitFrozenObjectsHeap(); diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index c5eaacd0c168ee..8ee52a9a05c7c3 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -962,6 +962,8 @@ void EEStartupHelper() } #endif // _DEBUG + // Initialize managed binder. Ensure g_fEEStarted and COM initialized before executing managed code. + SystemDomain::System()->PostStartInit(); ErrExit: ; } From 5363aecdc2acef73194ca6b60b5a68b29f5042f3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 22 Nov 2023 15:08:02 +0800 Subject: [PATCH 125/136] Fix AssemblyName equality --- .../src/System/Runtime/Loader/AssemblyIdentity.cs | 2 +- .../src/System/Runtime/Loader/AssemblyName.cs | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs index 458948e9ad300a..b344db93d25a78 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyIdentity.cs @@ -40,7 +40,7 @@ internal class AssemblyIdentity public byte[] PublicKeyOrTokenBLOB = Array.Empty(); public PEKind ProcessorArchitecture; public AssemblyContentType ContentType; - public AssemblyIdentityFlags IdentityFlags; + public AssemblyIdentityFlags IdentityFlags = AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE | AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY_TOKEN_NULL; // See https://docs.microsoft.com/dotnet/framework/reflection-and-codedom/specifying-fully-qualified-type-names#specifying-assembly-names public const string NeutralCulture = "neutral"; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index 675af7a4389a5f..60fa22c205949f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -68,9 +68,6 @@ internal sealed unsafe class BinderAssemblyName : AssemblyIdentity, IEquatableProcessorArchitecture; ContentType = data->ContentType; - IdentityFlags = flags; + IdentityFlags |= flags; } // TODO: Is this simple comparison enough? @@ -208,7 +205,7 @@ public unsafe BinderAssemblyName(AssemblyNameData* data) public bool IsNeutralCulture => string.IsNullOrEmpty(CultureOrLanguage) || string.EqualsOrdinalIgnoreCase(CultureOrLanguage, NeutralCulture); - public override int GetHashCode() => GetHashCode(AssemblyNameIncludeFlags.INCLUDE_ALL); + public override int GetHashCode() => GetHashCode(AssemblyNameIncludeFlags.INCLUDE_DEFAULT); public int GetHashCode(AssemblyNameIncludeFlags dwIncludeFlags) { @@ -320,7 +317,7 @@ static uint HashBytes(ReadOnlySpan bytes) public override bool Equals(object? obj) => obj is BinderAssemblyName other && Equals(other); - public bool Equals(BinderAssemblyName? other) => Equals(other, AssemblyNameIncludeFlags.INCLUDE_ALL); + public bool Equals(BinderAssemblyName? other) => Equals(other, AssemblyNameIncludeFlags.INCLUDE_DEFAULT); public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFlags) { From f50c271ff0f850f84174bd7b067d822dc29898d7 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 22 Nov 2023 17:56:59 +0800 Subject: [PATCH 126/136] Fix binder tracing --- .../AssemblyLoadContext.BinderCommon.cs | 132 ++++++++++-------- .../Runtime/Loader/TextualIdentityParser.cs | 1 + .../Tracing/ResolutionAttemptedOperation.cs | 8 +- .../src/Resources/Strings.resx | 6 +- 4 files changed, 79 insertions(+), 68 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index e231e1b4fff55c..9da4d5c7193834 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -220,12 +220,13 @@ public static int BindAssembly(AssemblyLoadContext binder, BinderAssemblyName as { hr = BindByName(applicationContext, assemblyName, false, false, excludeAppPaths, ref bindResult); - if (hr < 0) return hr; + if (hr < 0) goto Exit; // Remember the post-bind version kContextVersion = applicationContext.Version; } + Exit: tracer.TraceBindResult(bindResult); if (bindResult.Assembly != null) @@ -408,7 +409,7 @@ private static int BindLocked( { bool isCompatible = IsCompatibleAssemblyVersion(assemblyName, bindResult.Assembly.AssemblyName); hr = isCompatible ? HResults.S_OK : FUSION_E_APP_DOMAIN_LOCKED; - bindResult.SetAttemptResult(hr, assembly, isInContext: false); + bindResult.SetAttemptResult(hr, bindResult.Assembly); // TPA binder returns FUSION_E_REF_DEF_MISMATCH for incompatible version if (hr == FUSION_E_APP_DOMAIN_LOCKED && isTpaListProvided) // hr == FUSION_E_APP_DOMAIN_LOCKED @@ -957,89 +958,98 @@ public static int BindUsingPEImage(AssemblyLoadContext binder, BinderAssemblyNam // Tracing happens outside the binder lock to avoid calling into managed code within the lock using var tracer = new ResolutionAttemptedOperation(assemblyName, binder, ref hr); - Retry: bool mvidMismatch = false; - // Lock the application context - lock (applicationContext.ContextCriticalSection) + try { - // Attempt uncached bind and register stream if possible - // We skip version compatibility check - so assemblies with same simple name will be reported - // as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check). - hr = BindByName(applicationContext, assemblyName, true, true, excludeAppPaths, ref bindResult); + Retry: + mvidMismatch = false; - if (hr == HResults.E_FILENOTFOUND) - { - // IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); - try - { - bindResult.SetResult(new BinderAssembly(pPEImage, false)); - } - catch (Exception ex) - { - return ex.HResult; - } - } - else if (hr == HResults.S_OK) + // Lock the application context + lock (applicationContext.ContextCriticalSection) { - if (bindResult.Assembly != null) - { - // Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name - // does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being - // requested. - - Guid incomingMVID; - Guid boundMVID; + // Attempt uncached bind and register stream if possible + // We skip version compatibility check - so assemblies with same simple name will be reported + // as a successful bind. Below we compare MVIDs in that case instead (which is a more precise equality check). + hr = BindByName(applicationContext, assemblyName, true, true, excludeAppPaths, ref bindResult); + if (hr == HResults.E_FILENOTFOUND) + { + // IF_FAIL_GO(CreateImageAssembly(pPEImage, &bindResult)); try { - PEImage_GetMVID(pPEImage, out incomingMVID); - PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); + bindResult.SetResult(new BinderAssembly(pPEImage, false)); } catch (Exception ex) { return ex.HResult; } - - mvidMismatch = incomingMVID != boundMVID; - if (mvidMismatch) + } + else if (hr == HResults.S_OK) + { + if (bindResult.Assembly != null) { - // MVIDs do not match, so fail the load. - return HResults.COR_E_FILELOAD; - } + // Attempt was made to load an assembly that has the same name as a previously loaded one. Since same name + // does not imply the same assembly, we will need to check the MVID to confirm it is the same assembly as being + // requested. - // MVIDs match - request came in for the same assembly that was previously loaded. - // Let it through... - } - } + Guid incomingMVID; + Guid boundMVID; - // Remember the post-bind version of the context - kContextVersion = applicationContext.Version; - } + // GetMVID can throw exception + try + { + PEImage_GetMVID(pPEImage, out incomingMVID); + PEImage_GetMVID(bindResult.Assembly.PEImage, out boundMVID); + } + catch (Exception ex) + { + return ex.HResult; + } - if (bindResult.Assembly != null) - { - // This has to happen outside the binder lock as it can cause new binds - hr = RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult); - if (hr < 0) return hr; + mvidMismatch = incomingMVID != boundMVID; + if (mvidMismatch) + { + // MVIDs do not match, so fail the load. + return HResults.COR_E_FILELOAD; + } - if (hr == HResults.S_FALSE) - { - // tracer.TraceBindResult(bindResult); + // MVIDs match - request came in for the same assembly that was previously loaded. + // Let it through... + } + } - // Another bind interfered. We need to retry entire bind. - // This by design loops as long as needed because by construction we eventually - // will succeed or fail the bind. - bindResult = default; - goto Retry; + // Remember the post-bind version of the context + kContextVersion = applicationContext.Version; } - else if (hr == HResults.S_OK) + + if (bindResult.Assembly != null) { - assembly = hostBindResult.Assembly; + // This has to happen outside the binder lock as it can cause new binds + hr = RegisterAndGetHostChosen(applicationContext, kContextVersion, bindResult, out BindResult hostBindResult); + if (hr < 0) return hr; + + if (hr == HResults.S_FALSE) + { + // tracer.TraceBindResult(bindResult); + + // Another bind interfered. We need to retry entire bind. + // This by design loops as long as needed because by construction we eventually + // will succeed or fail the bind. + bindResult = default; + goto Retry; + } + else if (hr == HResults.S_OK) + { + assembly = hostBindResult.Assembly; + } } } + finally + { + tracer.TraceBindResult(bindResult, mvidMismatch); + } - tracer.TraceBindResult(bindResult, mvidMismatch); return hr; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs index f821d631b702b9..4903bfd48e9928 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/TextualIdentityParser.cs @@ -158,6 +158,7 @@ private static void AppendBinary(ref ValueStringBuilder vsb, ReadOnlySpan { vsb.EnsureCapacity(vsb.Length + data.Length * 2); HexConverter.EncodeToUtf16(data, vsb.RawChars[vsb.Length..], HexConverter.Casing.Lower); + vsb.Length += data.Length * 2; } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs index a2be06f4145368..7384b219f62420 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs @@ -72,12 +72,12 @@ public ResolutionAttemptedOperation(BinderAssemblyName? assemblyName, AssemblyLo if (_assemblyNameObject != null) _assemblyName = _assemblyNameObject.GetDisplayName(AssemblyNameIncludeFlags.INCLUDE_VERSION | AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN); - _assemblyLoadContextName = binder.ToString(); + _assemblyLoadContextName = (binder == AssemblyLoadContext.Default ? "Default" : binder.ToString()); } public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) { - if (_tracingEnabled) + if (!_tracingEnabled) return; string? errorMsg = null; @@ -85,7 +85,7 @@ public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) // Use the error message that would be reported in the file load exception if (mvidMismatch) { - errorMsg = SR.Format(SR.Host_AssemblyResolver_AssemblyAlreadyLoadedInContext, _assemblyName, SR.Host_AssemblyResolver_AssemblyAlreadyLoadedInContext); + errorMsg = SR.Format(SR.EE_FileLoad_Error_Generic, _assemblyName, SR.Host_AssemblyResolver_AssemblyAlreadyLoadedInContext); } BindResult.AttemptResult? inContextAttempt = bindResult.GetAttemptResult(isInContext: true); @@ -101,7 +101,7 @@ public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) mvidMismatch && isLastAttempt ? errorMsg : null); } - if (appAssembliesAttempt is { } appAssembliesAttemptValue) + if (appAssembliesAttempt is { } appAssembliesAttemptValue) { TraceStage(Stage.ApplicationAssemblies, (_hr < 0) && (appAssembliesAttemptValue.HResult >= 0) ? _hr : appAssembliesAttemptValue.HResult, diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 87bdd89505432f..a60cebdd1390e0 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -4284,12 +4284,12 @@ This operation is not available because the reflection support was disabled at compile time. - Could not load file or assembly {0}. {1} + Could not load file or assembly '{0}'. {1} - Assembly with same name is already loaded. + Assembly with same name is already loaded Dynamically emitted assemblies are unsupported during host-based resolution. - \ No newline at end of file + From 55e2b6c33a110ac03eb061cc91a0c4242b994289 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 23 Nov 2023 20:09:39 +0800 Subject: [PATCH 127/136] Simplify AttemptResult tracing --- .../src/System/Runtime/Loader/BindResult.cs | 6 +----- .../Tracing/ResolutionAttemptedOperation.cs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs index f5737aa111c09b..f6618a4bb54bfe 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs @@ -26,11 +26,7 @@ public void SetAttemptResult(int hResult, BinderAssembly? assembly, bool isInCon result.Attempted = true; } - public AttemptResult? GetAttemptResult(bool isInContext = false) - { - AttemptResult result = isInContext ? _inContextAttempt : _applicationAssembliesResult; - return result.Attempted ? result : null; - } + public AttemptResult GetAttemptResult(bool isInContext = false) => isInContext ? _inContextAttempt : _applicationAssembliesResult; public void SetResult(BinderAssembly assembly, bool isInContext = false) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs index 7384b219f62420..bcecf1199aca20 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Tracing/ResolutionAttemptedOperation.cs @@ -88,24 +88,24 @@ public void TraceBindResult(in BindResult bindResult, bool mvidMismatch = false) errorMsg = SR.Format(SR.EE_FileLoad_Error_Generic, _assemblyName, SR.Host_AssemblyResolver_AssemblyAlreadyLoadedInContext); } - BindResult.AttemptResult? inContextAttempt = bindResult.GetAttemptResult(isInContext: true); - BindResult.AttemptResult? appAssembliesAttempt = bindResult.GetAttemptResult(isInContext: false); + BindResult.AttemptResult inContextAttempt = bindResult.GetAttemptResult(isInContext: true); + BindResult.AttemptResult appAssembliesAttempt = bindResult.GetAttemptResult(isInContext: false); - if (inContextAttempt is { } inContextAttemptValue) + if (inContextAttempt.Attempted) { // If there the attempt HR represents a success, but the tracked HR represents a failure (e.g. from further validation), report the failed HR - bool isLastAttempt = appAssembliesAttempt == null; + bool isLastAttempt = !appAssembliesAttempt.Attempted; TraceStage(Stage.FindInLoadContext, - isLastAttempt && (_hr < 0) && (inContextAttemptValue.HResult >= 0) ? _hr : inContextAttemptValue.HResult, - inContextAttemptValue.Assembly, + isLastAttempt && (_hr < 0) && (inContextAttempt.HResult >= 0) ? _hr : inContextAttempt.HResult, + inContextAttempt.Assembly, mvidMismatch && isLastAttempt ? errorMsg : null); } - if (appAssembliesAttempt is { } appAssembliesAttemptValue) + if (appAssembliesAttempt.Attempted) { TraceStage(Stage.ApplicationAssemblies, - (_hr < 0) && (appAssembliesAttemptValue.HResult >= 0) ? _hr : appAssembliesAttemptValue.HResult, - appAssembliesAttemptValue.Assembly, + (_hr < 0) && (appAssembliesAttempt.HResult >= 0) ? _hr : appAssembliesAttempt.HResult, + appAssembliesAttempt.Assembly, mvidMismatch ? errorMsg : null); } } From f74c57dbda0787069fa10b0f4f739945869d91fd Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 23 Nov 2023 22:06:23 +0800 Subject: [PATCH 128/136] Update Crst level --- src/coreclr/inc/CrstTypes.def | 1 + src/coreclr/inc/crsttypes_generated.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/coreclr/inc/CrstTypes.def b/src/coreclr/inc/CrstTypes.def index 3bccb73e03a599..f8c5181d6a367b 100644 --- a/src/coreclr/inc/CrstTypes.def +++ b/src/coreclr/inc/CrstTypes.def @@ -87,6 +87,7 @@ End Crst AssemblyLoader AcquiredBefore DeadlockDetection UniqueStack DebuggerMutex + ThreadStore GlobalStrLiteralMap LoaderAllocatorReferences End Crst AvailableClass diff --git a/src/coreclr/inc/crsttypes_generated.h b/src/coreclr/inc/crsttypes_generated.h index 70847a5b367fcd..85bbd4883d0e72 100644 --- a/src/coreclr/inc/crsttypes_generated.h +++ b/src/coreclr/inc/crsttypes_generated.h @@ -148,7 +148,7 @@ int g_rgCrstLevelMap[] = 10, // CrstAppDomainCache 3, // CrstArgBasedStubCache 3, // CrstAssemblyList - 14, // CrstAssemblyLoader + 19, // CrstAssemblyLoader 4, // CrstAvailableClass 5, // CrstAvailableParamTypes 7, // CrstBaseDomain @@ -242,7 +242,7 @@ int g_rgCrstLevelMap[] = 5, // CrstSingleUseLock 0, // CrstSpecialStatics 0, // CrstStackSampler - 15, // CrstStaticBoxInit + 20, // CrstStaticBoxInit -1, // CrstStressLog 5, // CrstStubCache 0, // CrstStubDispatchCache From ab91f1769865a5dbd9eb43fd692131edaf578f00 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 24 Nov 2023 18:34:41 +0800 Subject: [PATCH 129/136] Fix --- .../src/System/Runtime/Loader/ApplicationContext.cs | 8 +++----- .../src/System/Runtime/Loader/BindResult.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs index 235ec15015cbf9..b13318f698075f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs @@ -34,14 +34,12 @@ internal sealed class ApplicationContext public void IncrementVersion() => Interlocked.Increment(ref _version); - private const char PATH_SEPARATOR_CHAR = ';'; - private static bool GetNextPath(string paths, ref int startPos, out string outPath) { bool wrappedWithQuotes = false; // Skip any leading spaces or path separators - while (startPos < paths.Length && paths[startPos] is ' ' or PATH_SEPARATOR_CHAR) + while (startPos < paths.Length && paths[startPos] is ' ' or PathInternal.PathSeparator) startPos++; if (startPos == paths.Length) @@ -73,7 +71,7 @@ static int IndexOfInRange(ReadOnlySpan str, int start, char ch) if (iEnd != -1) { // Find where the next path starts - there should be a path separator right after the closing quotation mark - iNext = IndexOfInRange(paths, iEnd, PATH_SEPARATOR_CHAR); + iNext = IndexOfInRange(paths, iEnd, PathInternal.PathSeparator); if (iNext != -1) { iNext++; @@ -89,7 +87,7 @@ static int IndexOfInRange(ReadOnlySpan str, int start, char ch) throw new ArgumentException(nameof(paths)); } } - else if ((iEnd = IndexOfInRange(paths, iEnd, PATH_SEPARATOR_CHAR)) != -1) + else if ((iEnd = IndexOfInRange(paths, iEnd, PathInternal.PathSeparator)) != -1) { iNext = iEnd + 1; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs index f6618a4bb54bfe..27dffcffd617f3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/BindResult.cs @@ -26,7 +26,7 @@ public void SetAttemptResult(int hResult, BinderAssembly? assembly, bool isInCon result.Attempted = true; } - public AttemptResult GetAttemptResult(bool isInContext = false) => isInContext ? _inContextAttempt : _applicationAssembliesResult; + public readonly AttemptResult GetAttemptResult(bool isInContext = false) => isInContext ? _inContextAttempt : _applicationAssembliesResult; public void SetResult(BinderAssembly assembly, bool isInContext = false) { From 5b1b5e165a83dfd3533ce730f93ccc29fbde6fb1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 25 Nov 2023 00:20:37 +0800 Subject: [PATCH 130/136] Unloadability --- .../src/System/Runtime/Loader/Assembly.cs | 7 +++++-- .../Loader/AssemblyLoadContext.CustomBinder.cs | 7 ++++--- .../Loader/AssemblyLoadContext.DefaultBinder.cs | 11 +++++++---- src/coreclr/vm/object.h | 4 ++-- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs index 9f9dac97419d1f..87036f58150f7c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/Assembly.cs @@ -10,15 +10,18 @@ internal sealed class BinderAssembly { // fields used by VM #pragma warning disable CA1823, 414, 169 - private AssemblyLoadContext? m_binder; private BinderAssemblyName m_assemblyName; + + // The assembly object is rooted by native object. + // Reference native ALC to allow managed ALC object to be collected. + private IntPtr m_binder; private IntPtr m_peImage; private IntPtr m_pDomainAssembly; private bool m_isInTPA; private bool m_isCoreLib; #pragma warning restore CA1823, 414, 169 - public AssemblyLoadContext? Binder + public IntPtr Binder { get => m_binder; set => m_binder = value; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs index 9af11d075bad3a..96db193288ee48 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CustomBinder.cs @@ -17,7 +17,7 @@ private int BindAssemblyByNameWorker(BinderAssemblyName assemblyName, out Binder if (hr >= 0) { Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder = this; + coreCLRFoundAssembly.Binder = _nativeAssemblyLoadContext; } return hr; @@ -63,7 +63,8 @@ internal virtual int BindUsingAssemblyName(BinderAssemblyName assemblyName, out // In such a case, we will not overwrite the binder (which would be wrong since the assembly would not // be present in the cache of the current binding context). Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder ??= this; + if (coreCLRFoundAssembly.Binder == IntPtr.Zero) + coreCLRFoundAssembly.Binder = _nativeAssemblyLoadContext; } } } @@ -96,7 +97,7 @@ internal virtual int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out B if (hr == HResults.S_OK) { Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder = this; + coreCLRFoundAssembly.Binder = _nativeAssemblyLoadContext; assembly = coreCLRFoundAssembly; } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs index bb360abf6c1f58..e1c737c70b3962 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.DefaultBinder.cs @@ -12,7 +12,7 @@ private static BinderAssembly InitializeDefault(IntPtr pCoreLibAssembly) { // ensure to touch Default to make it initialized Default.AddLoadedAssembly(pCoreLibAssembly); - return new BinderAssembly(Assembly_GetPEImage(pCoreLibAssembly), true) { Binder = Default }; + return new BinderAssembly(Assembly_GetPEImage(pCoreLibAssembly), true) { Binder = Default._nativeAssemblyLoadContext }; } // called by VM @@ -20,6 +20,8 @@ private static unsafe void SetupBindingPaths(char* trustedPlatformAssemblies, ch { Default.AppContext.SetupBindingPaths(new string(trustedPlatformAssemblies), new string(platformResourceRoots), new string(appPaths), acquireLock: true); } + + private protected IntPtr GetNativeAssemblyLoadContext() => _nativeAssemblyLoadContext; } internal partial class DefaultAssemblyLoadContext @@ -35,7 +37,7 @@ private int BindAssemblyByNameWorker(BinderAssemblyName assemblyName, out Binder if (hr >= 0) { Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder = this; + coreCLRFoundAssembly.Binder = GetNativeAssemblyLoadContext(); } return hr; @@ -73,7 +75,8 @@ internal override int BindUsingAssemblyName(BinderAssemblyName assemblyName, out // In such a case, we will not overwrite the binding context (which would be wrong since it would not // be present in the cache of the current binding context). Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder ??= this; + if (coreCLRFoundAssembly.Binder == IntPtr.Zero) + coreCLRFoundAssembly.Binder = GetNativeAssemblyLoadContext(); } } @@ -127,7 +130,7 @@ internal override int BindUsingPEImage(nint pPEImage, bool excludeAppPaths, out if (hr == HResults.S_OK) { Debug.Assert(coreCLRFoundAssembly != null); - coreCLRFoundAssembly.Binder = this; + coreCLRFoundAssembly.Binder = GetNativeAssemblyLoadContext(); assembly = coreCLRFoundAssembly; } } diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index b6b97769f04322..a74a4dc6bd2a63 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -1596,8 +1596,8 @@ class PEImage; class BinderAssemblyObject : public Object { public: - ASSEMBLYLOADCONTEXTREF m_binder; OBJECTREF m_assemblyName; + AssemblyBinder* m_binder; PEImage* m_peImage; DomainAssembly* m_pDomainAssembly; CLR_BOOL m_isInTPA; @@ -1605,7 +1605,7 @@ class BinderAssemblyObject : public Object PTR_AssemblyBinder GetBinder() { - return (PTR_AssemblyBinder)m_binder->GetNativeAssemblyBinder(); + return PTR_AssemblyBinder(m_binder); } }; #include From 106333afa0016765572b4656be5a5274cbb70107 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 25 Nov 2023 13:04:03 +0800 Subject: [PATCH 131/136] Fix BindSatelliteResourceByProbingPaths --- .../Runtime/Loader/AssemblyLoadContext.BinderCommon.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 9da4d5c7193834..3064f2d3cd82c4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -517,16 +517,20 @@ private static int BindSatelliteResourceByProbingPaths( { foreach (string bindingPath in resourceRoots) { - string fileName = Path.Combine(relativePath, bindingPath); + string fileName = Path.Combine(bindingPath, relativePath); int hr = GetAssembly(fileName, isInTPA: false, out BinderAssembly? assembly); AssemblyLoadContext.TracePathProbed(fileName, pathSource, hr); // Missing files are okay and expected when probing if (hr == HResults.E_FILENOTFOUND) { - return HResults.S_OK; + continue; } + bindResult.SetAttemptResult(hr, assembly); + if (hr < 0) + return hr; + Debug.Assert(assembly != null); BinderAssemblyName boundAssemblyName = assembly.AssemblyName; if (TestCandidateRefMatchesDef(requestedAssemblyName, boundAssemblyName, tpaListAssembly: false)) From 146c0f7f862d63a2122f217d0751b849ecc0e599 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 10 Mar 2024 21:14:00 +0800 Subject: [PATCH 132/136] Use separated helper to handle nullable array --- .../src/System/Runtime/Loader/AssemblyName.cs | 3 +-- .../Reflection/AssemblyNameHelpers.StrongName.cs | 11 ++++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index 60fa22c205949f..6c05ecefd23eb7 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -155,8 +155,7 @@ public BinderAssemblyName(IntPtr pPEImage) { if ((dwRefOrDefFlags & CorAssemblyFlags.afPublicKey) != 0) { - byte[]? publicKeyToken = AssemblyNameHelpers.ComputePublicKeyToken(new ReadOnlySpan(pvPublicKeyToken, (int)dwPublicKeyToken)); - Debug.Assert(publicKeyToken != null); + byte[] publicKeyToken = AssemblyNameHelpers.ComputePublicKeyToken(new ReadOnlySpan(pvPublicKeyToken, (int)dwPublicKeyToken)); PublicKeyOrTokenBLOB = publicKeyToken; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs index f11367ec66c4da..562acc8a68611c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyNameHelpers.StrongName.cs @@ -8,13 +8,18 @@ namespace System.Reflection { internal static partial class AssemblyNameHelpers { - public static byte[]? ComputePublicKeyToken(ReadOnlySpan publicKey) + public static byte[]? ComputePublicKeyToken(byte[]? publicKey) { - if (publicKey == default) + if (publicKey is null) return null; + return ComputePublicKeyToken(publicKey.AsSpan()); + } + + public static byte[] ComputePublicKeyToken(ReadOnlySpan publicKey) + { if (publicKey.Length == 0) - return Array.Empty(); + return []; if (!IsValidPublicKey(publicKey)) throw new SecurityException(SR.Security_InvalidAssemblyPublicKey); From 8afeb7da8d31ce78d12e50e741c0b324ff4dd0b5 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 13 Mar 2024 17:15:11 +0800 Subject: [PATCH 133/136] Don't use InvariantCulture --- .../Runtime/Loader/ApplicationContext.cs | 2 +- .../src/System/Runtime/Loader/AssemblyName.cs | 21 ++++--------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs index b13318f698075f..d428cd38a78a8d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs @@ -196,7 +196,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string // Parse TrustedPlatformAssemblies // - TrustedPlatformAssemblyMap = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + TrustedPlatformAssemblyMap = new Dictionary(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < trustedPlatformAssemblies.Length;) { if (!GetNextTPAPath(trustedPlatformAssemblies, ref i, dllOnly: false, out string fileName, out string simpleName, out bool isNativeImage)) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index 6c05ecefd23eb7..b9dfce15bc06ca 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -238,19 +238,6 @@ public int GetHashCode(AssemblyNameIncludeFlags dwIncludeFlags) dwUseIdentityFlags &= ~AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE; } - static uint HashCaseInsensitive(string str) - { - // ported from SString::HashCaseInsensitive - uint hash = 5381; - - foreach (char ch in str) - { - hash = ((hash << 5) + hash) ^ char.ToUpperInvariant(ch); - } - - return hash; - } - static uint HashBytes(ReadOnlySpan bytes) { // ported from coreclr/inc/utilcode.h @@ -264,7 +251,7 @@ static uint HashBytes(ReadOnlySpan bytes) return hash; } - dwHash ^= HashCaseInsensitive(SimpleName); + dwHash ^= (uint)SimpleName.GetNonRandomizedHashCodeOrdinalIgnoreCase(); dwHash = BitOperations.RotateLeft(dwHash, 4); if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_PUBLIC_KEY) != 0 || @@ -289,7 +276,7 @@ static uint HashBytes(ReadOnlySpan bytes) if ((dwUseIdentityFlags & AssemblyIdentityFlags.IDENTITY_FLAG_CULTURE) != 0) { - dwHash ^= HashCaseInsensitive(NormalizedCulture); + dwHash ^= (uint)NormalizedCulture.GetNonRandomizedHashCodeOrdinalIgnoreCase(); dwHash = BitOperations.RotateLeft(dwHash, 4); } @@ -330,14 +317,14 @@ public bool Equals(AssemblyIdentity? other, AssemblyNameIncludeFlags dwIncludeFl return ContentType == other.ContentType; } - if (string.Equals(SimpleName, other.SimpleName, StringComparison.InvariantCultureIgnoreCase) && + if (string.Equals(SimpleName, other.SimpleName, StringComparison.OrdinalIgnoreCase) && ContentType == other.ContentType) { fEquals = true; if ((dwIncludeFlags & AssemblyNameIncludeFlags.EXCLUDE_CULTURE) == 0) { - fEquals = string.Equals(NormalizedCulture, other.NormalizedCulture, StringComparison.InvariantCultureIgnoreCase); + fEquals = string.Equals(NormalizedCulture, other.NormalizedCulture, StringComparison.OrdinalIgnoreCase); } if (fEquals && (dwIncludeFlags & AssemblyNameIncludeFlags.INCLUDE_PUBLIC_KEY_TOKEN) != 0) From dfeaf1b9978f7b9ed7187f909bd2d5734ac0ab7b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 13 May 2024 17:42:36 +0800 Subject: [PATCH 134/136] Update MDImport to latest pattern --- .../src/System/Reflection/MdImport.cs | 14 +++++++++---- .../Loader/AssemblyLoadContext.Binder.cs | 2 +- .../src/System/Runtime/Loader/AssemblyName.cs | 2 +- src/coreclr/vm/ecalllist.h | 4 ++-- src/coreclr/vm/managedmdimport.cpp | 20 ++++++------------- src/coreclr/vm/managedmdimport.hpp | 8 +++----- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index 25e95ecf12a6b9..939b0fe26afacd 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -312,6 +312,12 @@ internal MetadataImport(RuntimeModule module) // since the instance can be replaced during HotReload and EnC scenarios. m_metadataImport2 = GetMetadataImport(module); } + + internal MetadataImport(IntPtr pIMetaDataAssemblyImport2) + { + ArgumentNullException.ThrowIfNull(pIMetaDataAssemblyImport2); + m_metadataImport2 = pIMetaDataAssemblyImport2; + } #endregion [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MetadataImport_Enum")] @@ -612,15 +618,15 @@ public bool IsValidToken(int token) } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _GetAssemblyFromScope(IntPtr scope, out uint tkAssembly); + private static extern int GetAssemblyFromScope(IntPtr scope, out uint tkAssembly); public uint GetAssemblyFromScope() { - _GetAssemblyFromScope(m_metadataImport2, out uint tkAssembly); + ThrowBadImageExceptionForHR(GetAssemblyFromScope(m_metadataImport2, out uint tkAssembly)); return tkAssembly; } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _GetAssemblyProps( + private static extern unsafe int GetAssemblyProps( IntPtr scope, uint mda, out byte* ppbPublicKey, @@ -639,7 +645,7 @@ public unsafe void GetAssemblyProps( out uint asselblyFlags) { void* _name; - _GetAssemblyProps(m_metadataImport2, assemblyToken, out publicKey, out publicKeyLength, out hashAlgId, &_name, pMetadata, out asselblyFlags); + ThrowBadImageExceptionForHR(GetAssemblyProps(m_metadataImport2, assemblyToken, out publicKey, out publicKeyLength, out hashAlgId, &_name, pMetadata, out asselblyFlags)); assemblyName = new MdUtf8String(_name).ToString(); } #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index abcdab6c49c2ae..13f52ec60f2c02 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -126,7 +126,7 @@ private unsafe void DeclareLoadedAssembly(IntPtr loadedAssembly) return; } - var mdImport = new MetadataImport(Assembly_GetMDImport(loadedAssembly), null); + var mdImport = new MetadataImport(Assembly_GetMDImport(loadedAssembly)); mdImport.GetScopeProps(out Guid mvid); string simpleName = new MdUtf8String(Assembly_GetSimpleName(loadedAssembly)).ToString(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs index b9dfce15bc06ca..c04c1e5733f88b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyName.cs @@ -70,7 +70,7 @@ public BinderAssemblyName(IntPtr pPEImage) { int* dwPAFlags = stackalloc int[2]; IntPtr pIMetaDataAssemblyImport = AssemblyBinderCommon.BinderAcquireImport(pPEImage, dwPAFlags); - var scope = new MetadataImport(pIMetaDataAssemblyImport, null); + var scope = new MetadataImport(pIMetaDataAssemblyImport); ProcessorArchitecture = AssemblyBinderCommon.TranslatePEToArchitectureType(dwPAFlags); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 696bb6f8c1dbdf..ac988be2c101af 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -181,8 +181,8 @@ FCFuncStart(gMetaDataImport) FCFuncElement("IsValidToken", MetaDataImport::IsValidToken) FCFuncElement("GetMarshalAs", MetaDataImport::GetMarshalAs) - FCFuncElement("_GetAssemblyFromScope", MetaDataImport::GetAssemblyFromScope) - FCFuncElement("_GetAssemblyProps", MetaDataImport::GetAssemblyProps) + FCFuncElement("GetAssemblyFromScope", MetaDataImport::GetAssemblyFromScope) + FCFuncElement("GetAssemblyProps", MetaDataImport::GetAssemblyProps) FCFuncEnd() FCFuncStart(gSignatureNative) diff --git a/src/coreclr/vm/managedmdimport.cpp b/src/coreclr/vm/managedmdimport.cpp index 5b219817ec934a..4e8d922726773d 100644 --- a/src/coreclr/vm/managedmdimport.cpp +++ b/src/coreclr/vm/managedmdimport.cpp @@ -440,23 +440,18 @@ FCIMPL3(HRESULT, MetaDataImport::GetMemberRefProps, } FCIMPLEND -MDImpl1(void, MetaDataImport::GetAssemblyFromScope, +FCIMPL2(HRESULT, MetaDataImport::GetAssemblyFromScope, + IMDInternalImport* pScope, mdAssembly* ptkAssembly) { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetAssemblyFromScope(ptkAssembly); - if (FAILED(hr)) - { - FCThrowVoid(kBadImageFormatException); - } + return pScope->GetAssemblyFromScope(ptkAssembly); } FCIMPLEND -MDImpl7(void, MetaDataImport::GetAssemblyProps, +FCIMPL8(HRESULT, MetaDataImport::GetAssemblyProps, + IMDInternalImport* pScope, mdAssembly mda, const void** ppbPublicKey, ULONG* pcbPublicKey, @@ -467,10 +462,7 @@ MDImpl7(void, MetaDataImport::GetAssemblyProps, { FCALL_CONTRACT; - HRESULT hr; - IMDInternalImport *_pScope = pScope; - - hr = _pScope->GetAssemblyProps(mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, pszName, pMetaData, pdwAsselblyFlags); + return pScope->GetAssemblyProps(mda, ppbPublicKey, pcbPublicKey, pulHashAlgId, pszName, pMetaData, pdwAsselblyFlags); } FCIMPLEND diff --git a/src/coreclr/vm/managedmdimport.hpp b/src/coreclr/vm/managedmdimport.hpp index abd4ae0f5c11fd..1968bdd1c67754 100644 --- a/src/coreclr/vm/managedmdimport.hpp +++ b/src/coreclr/vm/managedmdimport.hpp @@ -68,11 +68,9 @@ class MetaDataImport LPUTF8* marshalCookie, INT32* iidParamIndex); - //// - //// Assembly - //// - MDDecl1(void, GetAssemblyFromScope, mdAssembly* ptkAssembly); - MDDecl7(void, GetAssemblyProps, + static FCDECL2(HRESULT, GetAssemblyFromScope, IMDInternalImport* pScope, mdAssembly* ptkAssembly); + static FCDECL8(HRESULT, GetAssemblyProps, + IMDInternalImport* pScope, mdAssembly mda, const void** ppbPublicKey, ULONG* pcbPublicKey, From 22a25ba52b7e045b30f67180c46203f983e16f70 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 13 May 2024 19:25:07 +0800 Subject: [PATCH 135/136] Use class to reduce a generic instantiation --- .../System/Runtime/Loader/AssemblyLoadContext.Binder.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs index 13f52ec60f2c02..b7cad3811e9525 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Binder.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -79,7 +80,7 @@ private void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool composit addAllLoadedModules = true; } - ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); + ref SimpleNameToExpectedMVIDAndRequiringAssembly? entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); if (!found) { entry = new SimpleNameToExpectedMVIDAndRequiringAssembly @@ -91,6 +92,7 @@ private void DeclareDependencyOnMvid(string simpleName, Guid mvid, bool composit } else { + Debug.Assert(entry != null); // Elem already exists. Determine if the existing elem is another one with the same mvid, in which case just record that a dependency is in play. // If the existing elem has a different mvid, fail. if (entry.Mvid == mvid) @@ -130,7 +132,7 @@ private unsafe void DeclareLoadedAssembly(IntPtr loadedAssembly) mdImport.GetScopeProps(out Guid mvid); string simpleName = new MdUtf8String(Assembly_GetSimpleName(loadedAssembly)).ToString(); - ref SimpleNameToExpectedMVIDAndRequiringAssembly entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); + ref SimpleNameToExpectedMVIDAndRequiringAssembly? entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_assemblySimpleNameMvidCheckHash, simpleName, out bool found); if (!found) { entry = new SimpleNameToExpectedMVIDAndRequiringAssembly @@ -142,6 +144,7 @@ private unsafe void DeclareLoadedAssembly(IntPtr loadedAssembly) } else { + Debug.Assert(entry != null); // Elem already exists. Determine if the existing elem is another one with the same mvid, in which case do nothing. Everything is fine here. // If the existing elem has a different mvid, but isn't a dependency on exact mvid elem, then set the mvid to all 0. // If the existing elem has a different mvid, and is a dependency on exact mvid elem, then we've hit a fatal error. @@ -162,7 +165,7 @@ private unsafe void DeclareLoadedAssembly(IntPtr loadedAssembly) } //#endif // FEATURE_READYTORUN - private struct SimpleNameToExpectedMVIDAndRequiringAssembly + private sealed class SimpleNameToExpectedMVIDAndRequiringAssembly { // When an assembly is loaded, this Mvid value will be set to the mvid of the assembly. If there are multiple assemblies // with different mvid's loaded with the same simple name, then the Mvid value will be set to all zeroes. From dbb3a20bba42b5407d829e062504b6c179ecb7b1 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 13 May 2024 23:50:53 +0800 Subject: [PATCH 136/136] Remove more generic instantiation on Dictionary --- .../Runtime/Loader/ApplicationContext.cs | 28 ++++++++++++++++--- .../AssemblyLoadContext.BinderCommon.cs | 8 +++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs index d428cd38a78a8d..ecb621eeeae726 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/ApplicationContext.cs @@ -8,12 +8,30 @@ namespace System.Runtime.Loader { - internal struct TPAEntry + internal sealed class TPAEntry { public string? ILFileName; public string? NIFileName; } + internal sealed class FailureCacheKey : IEquatable + { + public readonly string SimpleName; + public readonly AssemblyVersion AssemblyVersion; + + public FailureCacheKey(string simpleName, AssemblyVersion AssemblyVersion) + { + SimpleName = simpleName; + this.AssemblyVersion = AssemblyVersion; + } + + public override bool Equals(object? obj) => obj is FailureCacheKey other && Equals(other); + + public bool Equals(FailureCacheKey? other) => other != null && SimpleName == other.SimpleName && AssemblyVersion.Equals(other.AssemblyVersion); + + public override int GetHashCode() => HashCode.Combine(SimpleName, AssemblyVersion.Major, AssemblyVersion.Minor, AssemblyVersion.Build, AssemblyVersion.Revision); + } + internal sealed class ApplicationContext { private volatile int _version; @@ -22,7 +40,7 @@ internal sealed class ApplicationContext public Dictionary ExecutionContext { get; } = new Dictionary(); - public Dictionary<(string SimpleName, AssemblyVersion Version), int> FailureCache { get; } = new Dictionary<(string SimpleName, AssemblyVersion Version), int>(); + public Dictionary FailureCache { get; } = new Dictionary(); public object ContextCriticalSection { get; } = new object(); @@ -204,7 +222,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string break; } - if (TrustedPlatformAssemblyMap.TryGetValue(simpleName, out TPAEntry existingEntry)) + if (TrustedPlatformAssemblyMap.TryGetValue(simpleName, out TPAEntry? existingEntry)) { // // We want to store only the first entry matching a simple name we encounter. @@ -221,10 +239,12 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string if (isNativeImage) { + existingEntry ??= new TPAEntry(); existingEntry.NIFileName = fileName; } else { + existingEntry ??= new TPAEntry(); existingEntry.ILFileName = fileName; } @@ -274,7 +294,7 @@ void Core(string trustedPlatformAssemblies, string platformResourceRoots, string public void AddToFailureCache(BinderAssemblyName assemblyName, int hresult) { - FailureCache.Add((assemblyName.SimpleName, assemblyName.Version), hresult); + FailureCache.Add(new FailureCacheKey(assemblyName.SimpleName, assemblyName.Version), hresult); IncrementVersion(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs index 3064f2d3cd82c4..e7b34f4f0966e1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.BinderCommon.cs @@ -302,14 +302,14 @@ private static int BindByName( { // Look for already cached binding failure (ignore PA, every PA will lock the context) - if (applicationContext.FailureCache.TryGetValue((assemblyName.SimpleName, assemblyName.Version), out int hr)) + if (applicationContext.FailureCache.TryGetValue(new FailureCacheKey(assemblyName.SimpleName, assemblyName.Version), out int hr)) { if (hr < 0) // FAILED(hr) { if (hr == HResults.E_FILENOTFOUND && skipFailureChecking) { // Ignore pre-existing transient bind error (re-bind will succeed) - applicationContext.FailureCache.Remove((assemblyName.SimpleName, assemblyName.Version)); + applicationContext.FailureCache.Remove(new FailureCacheKey(assemblyName.SimpleName, assemblyName.Version)); } return hr; // goto LogExit @@ -718,7 +718,7 @@ public static int BindByTpaList(ApplicationContext applicationContext, BinderAss // Is assembly on TPA list? Debug.Assert(applicationContext.TrustedPlatformAssemblyMap != null); - if (applicationContext.TrustedPlatformAssemblyMap.TryGetValue(requestedAssemblyName.SimpleName, out TPAEntry tpaEntry)) + if (applicationContext.TrustedPlatformAssemblyMap.TryGetValue(requestedAssemblyName.SimpleName, out TPAEntry? tpaEntry)) { string? tpaFileName = tpaEntry.NIFileName ?? tpaEntry.ILFileName; Debug.Assert(tpaFileName != null); @@ -934,7 +934,7 @@ private static int OtherBindInterfered(ApplicationContext applicationContext, Bi Debug.Assert(bindResult.Assembly.AssemblyName != null); // Look for already cached binding failure (ignore PA, every PA will lock the context) - if (!applicationContext.FailureCache.ContainsKey((bindResult.Assembly.AssemblyName.SimpleName, bindResult.Assembly.AssemblyName.Version))) // hr == S_OK + if (!applicationContext.FailureCache.ContainsKey(new FailureCacheKey(bindResult.Assembly.AssemblyName.SimpleName, bindResult.Assembly.AssemblyName.Version))) // hr == S_OK { int hr = FindInExecutionContext(applicationContext, bindResult.Assembly.AssemblyName, out BinderAssembly? assembly); if (hr >= 0 && assembly != null)