diff options
author | Gaurav Khanna <gkhanna@microsoft.com> | 2016-05-15 20:55:02 -0700 |
---|---|---|
committer | Gaurav Khanna <gkhanna@microsoft.com> | 2016-05-15 20:55:02 -0700 |
commit | 71fe847d72f7b6a4d019c3bd2715ceba3bc1b33b (patch) | |
tree | 001332b1c9052e6b5c8d783c627872b6a6d503eb | |
parent | 06e38c02a88c6d0f290bacf7900eab1a523a0ccb (diff) | |
parent | dd9317c7958f4fb65f45420433c587ea5e122ab2 (diff) | |
download | coreclr-71fe847d72f7b6a4d019c3bd2715ceba3bc1b33b.tar.gz coreclr-71fe847d72f7b6a4d019c3bd2715ceba3bc1b33b.tar.bz2 coreclr-71fe847d72f7b6a4d019c3bd2715ceba3bc1b33b.zip |
Merge pull request #4969 from gkhanna79/RelaxALC
Enable overriding assemblies from TPA
-rw-r--r-- | src/binder/assemblybinder.cpp | 10 | ||||
-rw-r--r-- | src/binder/clrprivbinderassemblyloadcontext.cpp | 58 | ||||
-rw-r--r-- | src/binder/clrprivbindercoreclr.cpp | 3 | ||||
-rw-r--r-- | src/binder/inc/assemblybinder.hpp | 1 | ||||
-rw-r--r-- | src/mscorlib/model.CoreLib.xml | 1 | ||||
-rw-r--r-- | src/mscorlib/model.xml | 1 | ||||
-rw-r--r-- | src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs | 85 | ||||
-rw-r--r-- | src/vm/appdomain.cpp | 91 | ||||
-rw-r--r-- | src/vm/mscorlib.h | 1 |
9 files changed, 169 insertions, 82 deletions
diff --git a/src/binder/assemblybinder.cpp b/src/binder/assemblybinder.cpp index 55d0147b07..70f698f10f 100644 --- a/src/binder/assemblybinder.cpp +++ b/src/binder/assemblybinder.cpp @@ -50,7 +50,9 @@ BOOL IsCompilationProcess(); #include "clrprivbindercoreclr.h" #include "clrprivbinderassemblyloadcontext.h" // Helper function in the VM, invoked by the Binder, to invoke the host assembly resolver -extern HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, IAssemblyName *pIAssemblyName, ICLRPrivAssembly **ppLoadedAssembly); +extern HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, + IAssemblyName *pIAssemblyName, CLRPrivBinderCoreCLR *pTPABinder, + BINDER_SPACE::AssemblyName *pAssemblyName, ICLRPrivAssembly **ppLoadedAssembly); // Helper to check if we have a host assembly resolver set extern BOOL RuntimeCanUseAppPathAssemblyResolver(DWORD adid); @@ -1814,6 +1816,7 @@ namespace BINDER_SPACE HRESULT AssemblyBinder::BindUsingHostAssemblyResolver (/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin, /* in */ AssemblyName *pAssemblyName, /* in */ IAssemblyName *pIAssemblyName, + /* in */ CLRPrivBinderCoreCLR *pTPABinder, /* out */ Assembly **ppAssembly) { HRESULT hr = E_FAIL; @@ -1821,9 +1824,10 @@ HRESULT AssemblyBinder::BindUsingHostAssemblyResolver (/* in */ INT_PTR pManaged _ASSERTE(pManagedAssemblyLoadContextToBindWithin != NULL); - // Call into the VM to use the HostAssemblyResolver and load the assembly + // RuntimeInvokeHostAssemblyResolver will perform steps 2-4 of CLRPrivBinderAssemblyLoadContext::BindAssemblyByName. ICLRPrivAssembly *pLoadedAssembly = NULL; - hr = RuntimeInvokeHostAssemblyResolver(pManagedAssemblyLoadContextToBindWithin, pIAssemblyName, &pLoadedAssembly); + hr = RuntimeInvokeHostAssemblyResolver(pManagedAssemblyLoadContextToBindWithin, pIAssemblyName, + pTPABinder, pAssemblyName, &pLoadedAssembly); if (SUCCEEDED(hr)) { _ASSERTE(pLoadedAssembly != NULL); diff --git a/src/binder/clrprivbinderassemblyloadcontext.cpp b/src/binder/clrprivbinderassemblyloadcontext.cpp index 57f4ee72c4..8f3a3eef49 100644 --- a/src/binder/clrprivbinderassemblyloadcontext.cpp +++ b/src/binder/clrprivbinderassemblyloadcontext.cpp @@ -61,14 +61,19 @@ HRESULT CLRPrivBinderAssemblyLoadContext::BindAssemblyByName(IAssemblyName * SAFE_NEW(pAssemblyName, AssemblyName); IF_FAIL_GO(pAssemblyName->Init(pIAssemblyName)); - // Check if the assembly is in the TPA list or not. Don't search app paths when using the TPA binder because the actual - // binder is using a host assembly resolver. - hr = m_pTPABinder->BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */); - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + // 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 TPABinder. If assembly is found, use it. + // 4) Invoke the LoadContext's Resolving event. If assembly is found, use it. + // 5) 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. + { - // If we could not find the assembly in the TPA list, - // then bind to it in the context of the current binder. - // If we find it already loaded, we will return the reference. + // 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)) @@ -82,7 +87,8 @@ HRESULT CLRPrivBinderAssemblyLoadContext::BindAssemblyByName(IAssemblyName * // 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 = AssemblyBinder::BindUsingHostAssemblyResolver(GetManagedAssemblyLoadContext(), pAssemblyName, pIAssemblyName, &pCoreCLRFoundAssembly); + // + hr = AssemblyBinder::BindUsingHostAssemblyResolver(GetManagedAssemblyLoadContext(), pAssemblyName, pIAssemblyName, m_pTPABinder, &pCoreCLRFoundAssembly); if (SUCCEEDED(hr)) { // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. @@ -142,41 +148,19 @@ HRESULT CLRPrivBinderAssemblyLoadContext::BindUsingPEImage( /* in */ PEImage *pP IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); } - // Ensure we are not being asked to bind to a TPA assembly - // - // Easy out for mscorlib + // 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->IsMscorlib()) { IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); } + hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly); + if (hr == S_OK) { - SString& simpleName = pAssemblyName->GetSimpleName(); - ApplicationContext *pTPAApplicationContext = m_pTPABinder->GetAppContext(); - SimpleNameToFileNameMap * tpaMap = pTPAApplicationContext->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 or not. - // Don't search app paths when using the TPA binder because the actual binder is using a host assembly resolver. - hr = m_pTPABinder->BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */); - if (SUCCEEDED(hr)) - { - if (pCoreCLRFoundAssembly->GetIsInGAC()) - { - // If we were able to bind to a TPA assembly, then fail the load - IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); - } - } - } - - hr = AssemblyBinder::BindUsingPEImage(&m_appContext, pAssemblyName, pPEImage, PeKind, pIMetaDataAssemblyImport, &pCoreCLRFoundAssembly); - if (hr == S_OK) - { - _ASSERTE(pCoreCLRFoundAssembly != NULL); - pCoreCLRFoundAssembly->SetBinder(this); - *ppAssembly = pCoreCLRFoundAssembly.Extract(); - } + _ASSERTE(pCoreCLRFoundAssembly != NULL); + pCoreCLRFoundAssembly->SetBinder(this); + *ppAssembly = pCoreCLRFoundAssembly.Extract(); } Exit:; } diff --git a/src/binder/clrprivbindercoreclr.cpp b/src/binder/clrprivbindercoreclr.cpp index a2fb1c8237..d62af867ef 100644 --- a/src/binder/clrprivbindercoreclr.cpp +++ b/src/binder/clrprivbindercoreclr.cpp @@ -80,7 +80,8 @@ HRESULT CLRPrivBinderCoreCLR::BindAssemblyByName(IAssemblyName *pIAssemblyNa INT_PTR pManagedAssemblyLoadContext = GetManagedAssemblyLoadContext(); if (pManagedAssemblyLoadContext != NULL) { - hr = AssemblyBinder::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, pIAssemblyName, &pCoreCLRFoundAssembly); + hr = AssemblyBinder::BindUsingHostAssemblyResolver(pManagedAssemblyLoadContext, pAssemblyName, pIAssemblyName, + NULL, &pCoreCLRFoundAssembly); if (SUCCEEDED(hr)) { // We maybe returned an assembly that was bound to a different AssemblyLoadContext instance. diff --git a/src/binder/inc/assemblybinder.hpp b/src/binder/inc/assemblybinder.hpp index 87d6491a92..3a1f1e45fd 100644 --- a/src/binder/inc/assemblybinder.hpp +++ b/src/binder/inc/assemblybinder.hpp @@ -78,6 +78,7 @@ namespace BINDER_SPACE static HRESULT BindUsingHostAssemblyResolver (/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin, /* in */ AssemblyName *pAssemblyName, /* in */ IAssemblyName *pIAssemblyName, + /* in */ CLRPrivBinderCoreCLR *pTPABinder, /* out */ Assembly **ppAssembly); static HRESULT BindUsingPEImage(/* in */ ApplicationContext *pApplicationContext, diff --git a/src/mscorlib/model.CoreLib.xml b/src/mscorlib/model.CoreLib.xml index 1f1408d446..7b5214b2f8 100644 --- a/src/mscorlib/model.CoreLib.xml +++ b/src/mscorlib/model.CoreLib.xml @@ -951,6 +951,7 @@ <Member Name="LoadFromStream(System.IO.Stream)" /> <Member Name="LoadFromStream(System.IO.Stream,System.IO.Stream)" /> <Member Name="Resolve(System.IntPtr,System.Reflection.AssemblyName)" /> + <Member Name="ResolveUsingResolvingEvent(System.IntPtr,System.Reflection.AssemblyName)" /> <Member Name="ResolveUnmanagedDll(System.String,System.IntPtr)" /> <Member Name="LoadUnmanagedDll(System.String)" /> <Member Name="LoadUnmanagedDllFromPath(System.String)" /> diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml index 225249f83c..ef2774a9f3 100644 --- a/src/mscorlib/model.xml +++ b/src/mscorlib/model.xml @@ -951,6 +951,7 @@ <Member Name="LoadFromStream(System.IO.Stream)" /> <Member Name="LoadFromStream(System.IO.Stream,System.IO.Stream)" /> <Member Name="Resolve(System.IntPtr,System.Reflection.AssemblyName)" /> + <Member Name="ResolveUsingResolvingEvent(System.IntPtr,System.Reflection.AssemblyName)" /> <Member Name="ResolveUnmanagedDll(System.String,System.IntPtr)" /> <Member Name="LoadUnmanagedDll(System.String)" /> <Member Name="LoadUnmanagedDllFromPath(System.String)" /> diff --git a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs index 6b53ba3b64..527fbe4d6c 100644 --- a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs +++ b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs @@ -111,13 +111,6 @@ namespace System.Runtime.Loader throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), "nativeImagePath"); } - // Check if the nativeImagePath has ".ni.dll" or ".ni.exe" extension - if (!(nativeImagePath.EndsWith(".ni.dll", StringComparison.InvariantCultureIgnoreCase) || - nativeImagePath.EndsWith(".ni.exe", StringComparison.InvariantCultureIgnoreCase))) - { - throw new ArgumentException("nativeImagePath"); - } - if (assemblyPath != null && Path.IsRelative(assemblyPath)) { throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), "assemblyPath"); @@ -184,7 +177,17 @@ namespace System.Runtime.Loader { AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target); - return context.LoadFromAssemblyName(assemblyName); + return context.ResolveUsingLoad(assemblyName); + } + + // 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) + { + AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target); + + // Invoke the AssemblyResolve event callbacks if wired up + return context.ResolveUsingEvent(assemblyName); } private Assembly GetFirstResolvedAssembly(AssemblyName assemblyName) @@ -210,23 +213,8 @@ namespace System.Runtime.Loader return resolvedAssembly; } - public Assembly LoadFromAssemblyName(AssemblyName assemblyName) + private Assembly ValidateAssemblyNameWithSimpleName(Assembly assembly, string requestedSimpleName) { - // AssemblyName is mutable. Cache the expected name before anybody gets a chance to modify it. - string requestedSimpleName = assemblyName.Name; - - Assembly assembly = Load(assemblyName); - if (assembly == null) - { - // Invoke the AssemblyResolve event callbacks if wired up - assembly = GetFirstResolvedAssembly(assemblyName); - } - - if (assembly == null) - { - throw new FileNotFoundException(Environment.GetResourceString("IO.FileLoad"), requestedSimpleName); - } - // Get the name of the loaded assembly string loadedSimpleName = null; @@ -244,7 +232,56 @@ namespace System.Runtime.Loader throw new InvalidOperationException(Environment.GetResourceString("Argument_CustomAssemblyLoadContextRequestedNameMismatch")); return assembly; + + } + + private Assembly ResolveUsingLoad(AssemblyName assemblyName) + { + string simpleName = assemblyName.Name; + Assembly assembly = Load(assemblyName); + + if (assembly != null) + { + assembly = ValidateAssemblyNameWithSimpleName(assembly, simpleName); + } + + return assembly; + } + + private Assembly ResolveUsingEvent(AssemblyName assemblyName) + { + string simpleName = assemblyName.Name; + + // Invoke the AssemblyResolve event callbacks if wired up + Assembly assembly = GetFirstResolvedAssembly(assemblyName); + if (assembly != null) + { + assembly = ValidateAssemblyNameWithSimpleName(assembly, simpleName); + } + + // Since attempt to resolve the assembly via Resolving event is the last option, + // throw an exception if we do not find any assembly. + if (assembly == null) + { + throw new FileNotFoundException(Environment.GetResourceString("IO.FileLoad"), simpleName); + } + + return assembly; + } + + public Assembly LoadFromAssemblyName(AssemblyName assemblyName) + { + // AssemblyName is mutable. Cache the expected name before anybody gets a chance to modify it. + string requestedSimpleName = assemblyName.Name; + + Assembly assembly = ResolveUsingLoad(assemblyName); + if (assembly == null) + { + // Invoke the AssemblyResolve event callbacks if wired up + assembly = ResolveUsingEvent(assemblyName); + } + return assembly; } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 3827d9b0ac..53c68776d3 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -14214,7 +14214,7 @@ BOOL RuntimeCanUseAppPathAssemblyResolver(DWORD adid) } // Returns S_OK if the assembly was successfully loaded -HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, IAssemblyName *pIAssemblyName, ICLRPrivAssembly **ppLoadedAssembly) +HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToBindWithin, IAssemblyName *pIAssemblyName, CLRPrivBinderCoreCLR *pTPABinder, BINDER_SPACE::AssemblyName *pAssemblyName, ICLRPrivAssembly **ppLoadedAssembly) { CONTRACTL { @@ -14243,6 +14243,8 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB GCPROTECT_BEGIN(_gcRefs); + ICLRPrivAssembly *pAssemblyBindingContext = NULL; + // Prepare to invoke System.Runtime.Loader.AssemblyLoadContext.Resolve method. // // First, initialize an assembly spec for the requested assembly @@ -14251,7 +14253,9 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB hr = spec.Init(pIAssemblyName); if (SUCCEEDED(hr)) { - // Next, allocate an AssemblyName managed object + // Step 2 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName) - Invoke Load method + // + // Allocate an AssemblyName managed object _gcRefs.oRefAssemblyName = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME)); // Initialize the AssemblyName object from the AssemblySpec @@ -14268,10 +14272,63 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance }; + bool fResolvedAssembly = true; + bool fResolvedAssemblyViaTPALoadContext = false; + // Make the call _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methLoadAssembly.Call_RetOBJECTREF(args); - if (_gcRefs.oRefLoadedAssembly != NULL) + if (_gcRefs.oRefLoadedAssembly == NULL) + { + fResolvedAssembly = false; + } + + if (!fResolvedAssembly) + { + // Step 3 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName) + // + // If we could not resolve the assembly using Load method, then bind using TPA binder if present in its + // load context. + if (pTPABinder != NULL) + { + // Switch to pre-emp mode before calling into the binder + GCX_PREEMP(); + BINDER_SPACE::Assembly *pCoreCLRFoundAssembly = NULL; + hr = pTPABinder->BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */); + if (SUCCEEDED(hr)) + { + pAssemblyBindingContext = pCoreCLRFoundAssembly; + fResolvedAssembly = true; + fResolvedAssemblyViaTPALoadContext = true; + } + } + } + + if (!fResolvedAssembly) + { + // Step 4 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName) + // + // If we couldnt resolve the assembly using TPA LoadContext as well, then + // attempt to resolve it using the Resolving event. + // Finally, setup arguments for invocation + BinderMethodID idHAR_ResolveUsingEvent = METHOD__ASSEMBLYLOADCONTEXT__RESOLVEUSINGEVENT; + MethodDescCallSite methLoadAssembly(idHAR_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) methLoadAssembly.Call_RetOBJECTREF(args); + } + + if (fResolvedAssembly && !fResolvedAssemblyViaTPALoadContext) { + // 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(); @@ -14302,23 +14359,23 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB // Is the assembly already bound using a binding context that will be incompatible? // An example is attempting to consume an assembly bound to WinRT binder. - ICLRPrivAssembly *pAssemblyBindingContext = pLoadedPEAssembly->GetHostAssembly(); - + pAssemblyBindingContext = pLoadedPEAssembly->GetHostAssembly(); + } + #ifdef FEATURE_COMINTEROP - if (AreSameBinderInstance(pAssemblyBindingContext, GetAppDomain()->GetWinRtBinder())) - { - // It is invalid to return an assembly bound to an incompatible binder - *ppLoadedAssembly = NULL; - SString name; - spec.GetFileOrDisplayName(0, name); - COMPlusThrowHR(COR_E_INVALIDOPERATION, IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT, name); - } + if (AreSameBinderInstance(pAssemblyBindingContext, GetAppDomain()->GetWinRtBinder())) + { + // It is invalid to return an assembly bound to an incompatible binder + *ppLoadedAssembly = NULL; + SString name; + spec.GetFileOrDisplayName(0, name); + COMPlusThrowHR(COR_E_INVALIDOPERATION, IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT, name); + } #endif // FEATURE_COMINTEROP - // Get the ICLRPrivAssembly reference to return back to. - *ppLoadedAssembly = clr::SafeAddRef(pLoadedPEAssembly->GetHostAssembly()); - hr = S_OK; - } + // Get the ICLRPrivAssembly reference to return back to. + *ppLoadedAssembly = clr::SafeAddRef(pAssemblyBindingContext); + hr = S_OK; } GCPROTECT_END(); diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index 9620627bea..4c27965248 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -1674,6 +1674,7 @@ DEFINE_METHOD(FIRSTCHANCE_EVENTARGS, CTOR, .ctor, 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, RESOLVEUSINGEVENT, ResolveUsingResolvingEvent, SM_IntPtr_AssemblyName_RetAssemblyBase) #endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER) |