summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mscorlib/src/System/Reflection/Assembly.cs35
-rw-r--r--src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs17
-rw-r--r--src/vm/appdomain.cpp61
-rw-r--r--src/vm/assemblynative.cpp18
-rw-r--r--src/vm/assemblynative.hpp5
-rw-r--r--src/vm/assemblyspec.cpp17
-rw-r--r--src/vm/assemblyspec.hpp24
7 files changed, 117 insertions, 60 deletions
diff --git a/src/mscorlib/src/System/Reflection/Assembly.cs b/src/mscorlib/src/System/Reflection/Assembly.cs
index b28f8681fc..62ae9b49f6 100644
--- a/src/mscorlib/src/System/Reflection/Assembly.cs
+++ b/src/mscorlib/src/System/Reflection/Assembly.cs
@@ -327,6 +327,22 @@ namespace System.Reflection
Contract.Ensures(Contract.Result<Assembly>() != null);
Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+ return Load(assemblyRef, IntPtr.Zero);
+ }
+
+ // Locate an assembly by its name. The name can be strong or
+ // weak. The assembly is loaded into the domain of the caller.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static Assembly Load(AssemblyName assemblyRef, IntPtr ptrLoadContextBinder)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
#if FEATURE_WINDOWSPHONE
if (assemblyRef != null && assemblyRef.CodeBase != null)
{
@@ -335,7 +351,7 @@ namespace System.Reflection
#endif
StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/);
+ return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/, ptrLoadContextBinder);
}
[System.Security.SecuritySafeCritical] // auto-generated
@@ -1663,9 +1679,10 @@ namespace System.Reflection
ref StackCrawlMark stackMark,
bool throwOnFileNotFound,
bool forIntrospection,
- bool suppressSecurityChecks)
+ bool suppressSecurityChecks,
+ IntPtr ptrLoadContextBinder = default(IntPtr))
{
- return InternalLoadAssemblyName(assemblyRef, assemblySecurity, reqAssembly, ref stackMark, IntPtr.Zero, true /*throwOnError*/, forIntrospection, suppressSecurityChecks);
+ return InternalLoadAssemblyName(assemblyRef, assemblySecurity, reqAssembly, ref stackMark, IntPtr.Zero, true /*throwOnError*/, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder);
}
[System.Security.SecurityCritical] // auto-generated
@@ -1677,7 +1694,8 @@ namespace System.Reflection
IntPtr pPrivHostBinder,
bool throwOnFileNotFound,
bool forIntrospection,
- bool suppressSecurityChecks)
+ bool suppressSecurityChecks,
+ IntPtr ptrLoadContextBinder = default(IntPtr))
{
if (assemblyRef == null)
@@ -1735,7 +1753,7 @@ namespace System.Reflection
return nLoad(assemblyRef, codeBase, assemblySecurity, reqAssembly, ref stackMark,
pPrivHostBinder,
- throwOnFileNotFound, forIntrospection, suppressSecurityChecks);
+ throwOnFileNotFound, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder);
}
// These are the framework assemblies that does reflection invocation
@@ -1785,7 +1803,8 @@ namespace System.Reflection
IntPtr pPrivHostBinder,
bool throwOnFileNotFound,
bool forIntrospection,
- bool suppressSecurityChecks);
+ bool suppressSecurityChecks,
+ IntPtr ptrLoadContextBinder);
#if !FEATURE_CORECLR
// The NGEN task uses this method, so please do not modify its signature
@@ -1807,11 +1826,11 @@ namespace System.Reflection
IntPtr pPrivHostBinder,
bool throwOnFileNotFound,
bool forIntrospection,
- bool suppressSecurityChecks)
+ bool suppressSecurityChecks, IntPtr ptrLoadContextBinder = default(IntPtr))
{
return _nLoad(fileName, codeBase, assemblySecurity, locationHint, ref stackMark,
pPrivHostBinder,
- throwOnFileNotFound, forIntrospection, suppressSecurityChecks);
+ throwOnFileNotFound, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder);
}
#if FEATURE_FUSION
diff --git a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
index c4872e363b..75529868bd 100644
--- a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
+++ b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
@@ -31,6 +31,10 @@ namespace System.Runtime.Loader
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
private static extern IntPtr InitializeAssemblyLoadContext(IntPtr ptrAssemblyLoadContext, bool fRepresentsTPALoadContext);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr LoadFromAssemblyName(IntPtr ptrNativeAssemblyLoadContext, bool fRepresentsTPALoadContext);
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
[SuppressUnmanagedCodeSecurity]
@@ -271,17 +275,10 @@ namespace System.Runtime.Loader
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);
- }
+ // Attempt to load the assembly, using the same ordering as static load, in the current load context.
+ Assembly loadedAssembly = Assembly.Load(assemblyName, m_pNativeAssemblyLoadContext);
- return assembly;
+ return loadedAssembly;
}
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp
index 4580c5aff5..0ec2c5f2fc 100644
--- a/src/vm/appdomain.cpp
+++ b/src/vm/appdomain.cpp
@@ -14241,6 +14241,8 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB
GCPROTECT_BEGIN(_gcRefs);
ICLRPrivAssembly *pAssemblyBindingContext = NULL;
+
+ bool fInvokedForTPABinder = (pTPABinder == NULL)?true:false;
// Prepare to invoke System.Runtime.Loader.AssemblyLoadContext.Resolve method.
//
@@ -14250,47 +14252,48 @@ HRESULT RuntimeInvokeHostAssemblyResolver(INT_PTR pManagedAssemblyLoadContextToB
hr = spec.Init(pIAssemblyName);
if (SUCCEEDED(hr))
{
- // Step 2 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName) - Invoke Load method
- //
+ bool fResolvedAssembly = false;
+ bool fResolvedAssemblyViaTPALoadContext = false;
+
// Allocate an AssemblyName managed object
_gcRefs.oRefAssemblyName = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME));
// Initialize the AssemblyName object from the AssemblySpec
spec.AssemblyNameInit(&_gcRefs.oRefAssemblyName, NULL);
-
- // Finally, setup arguments for invocation
- BinderMethodID idHAR_Resolve = METHOD__ASSEMBLYLOADCONTEXT__RESOLVE;
- MethodDescCallSite methLoadAssembly(idHAR_Resolve);
-
- // Setup the arguments for the call
- ARG_SLOT args[2] =
+
+ if (!fInvokedForTPABinder)
{
- PtrToArgSlot(pManagedAssemblyLoadContextToBindWithin), // IntPtr for managed assembly load context instance
- ObjToArgSlot(_gcRefs.oRefAssemblyName), // AssemblyName instance
- };
+ // Step 2 (of CLRPrivBinderAssemblyLoadContext::BindUsingAssemblyName) - Invoke Load method
+ // This is not invoked for TPA Binder since it always returns NULL.
- bool fResolvedAssembly = true;
- bool fResolvedAssemblyViaTPALoadContext = false;
-
- // Make the call
- _gcRefs.oRefLoadedAssembly = (ASSEMBLYREF) methLoadAssembly.Call_RetOBJECTREF(args);
- if (_gcRefs.oRefLoadedAssembly == NULL)
- {
- fResolvedAssembly = false;
- }
+ // Finally, setup arguments for invocation
+ BinderMethodID idHAR_Resolve = METHOD__ASSEMBLYLOADCONTEXT__RESOLVE;
+ MethodDescCallSite methLoadAssembly(idHAR_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;
+ }
- 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)
+ if (!fResolvedAssembly)
{
+ // 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 = pTPABinder->BindAssemblyByNameWorker(pAssemblyName, &pCoreCLRFoundAssembly, true /* excludeAppPaths */);
+ ICLRPrivAssembly *pCoreCLRFoundAssembly = NULL;
+ hr = pTPABinder->BindAssemblyByName(pIAssemblyName, &pCoreCLRFoundAssembly);
if (SUCCEEDED(hr))
{
pAssemblyBindingContext = pCoreCLRFoundAssembly;
diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp
index 29e0a451f0..90c58fc59c 100644
--- a/src/vm/assemblynative.cpp
+++ b/src/vm/assemblynative.cpp
@@ -137,7 +137,7 @@ FCIMPL1(FC_BOOL_RET, AssemblyNative::IsNewPortableAssembly, AssemblyNameBaseObje
FCIMPLEND
#endif // FEATURE_FUSION
-FCIMPL9(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAFE,
+FCIMPL10(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAFE,
StringObject* codeBaseUNSAFE,
Object* securityUNSAFE,
AssemblyBaseObject* requestingAssemblyUNSAFE,
@@ -145,7 +145,8 @@ FCIMPL9(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAF
ICLRPrivBinder * pPrivHostBinder,
CLR_BOOL fThrowOnFileNotFound,
CLR_BOOL fForIntrospection,
- CLR_BOOL fSuppressSecurityChecks)
+ CLR_BOOL fSuppressSecurityChecks,
+ INT_PTR ptrLoadContextBinder)
{
FCALL_CONTRACT;
@@ -243,10 +244,17 @@ FCIMPL9(Object*, AssemblyNative::Load, AssemblyNameBaseObject* assemblyNameUNSAF
spec.SetParentAssembly(pParentAssembly);
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
- // If the requesting assembly has Fallback LoadContext binder available,
- // then set it up in the AssemblySpec.
- if (pRefAssembly != NULL)
+ // Have we been passed the reference to the binder against which this load should be triggered?
+ // If so, then use it to set the fallback load context binder.
+ if (ptrLoadContextBinder != NULL)
{
+ spec.SetFallbackLoadContextBinderForRequestingAssembly(reinterpret_cast<ICLRPrivBinder *>(ptrLoadContextBinder));
+ spec.SetPreferFallbackLoadContextBinder();
+ }
+ else if (pRefAssembly != NULL)
+ {
+ // If the requesting assembly has Fallback LoadContext binder available,
+ // then set it up in the AssemblySpec.
PEFile *pRefAssemblyManifestFile = pRefAssembly->GetManifestFile();
spec.SetFallbackLoadContextBinderForRequestingAssembly(pRefAssemblyManifestFile->GetFallbackLoadContextBinder());
}
diff --git a/src/vm/assemblynative.hpp b/src/vm/assemblynative.hpp
index 6309ffcf36..ca03239d3e 100644
--- a/src/vm/assemblynative.hpp
+++ b/src/vm/assemblynative.hpp
@@ -50,7 +50,7 @@ public:
Object* securityUNSAFE);
static FCDECL6(Object*, LoadImage, U1Array* PEByteArrayUNSAFE, U1Array* SymByteArrayUNSAFE, Object* securityUNSAFE, StackCrawlMark* stackMark, CLR_BOOL fForIntrospection, SecurityContextSource securityContextSource);
- static FCDECL9(Object*, Load, AssemblyNameBaseObject* assemblyNameUNSAFE,
+ static FCDECL10(Object*, Load, AssemblyNameBaseObject* assemblyNameUNSAFE,
StringObject* codeBaseUNSAFE,
Object* securityUNSAFE,
AssemblyBaseObject* requestingAssemblyUNSAFE,
@@ -58,7 +58,8 @@ public:
ICLRPrivBinder * pPrivHostBinder,
CLR_BOOL fThrowOnFileNotFound,
CLR_BOOL fForIntrospection,
- CLR_BOOL fSuppressSecurityChecks);
+ CLR_BOOL fSuppressSecurityChecks,
+ INT_PTR ptrLoadContextBinder);
static FCDECL1(FC_BOOL_RET, IsFrameworkAssembly, AssemblyNameBaseObject* refAssemblyNameUNSAFE);
static FCDECL1(FC_BOOL_RET, IsNewPortableAssembly, AssemblyNameBaseObject* refAssemblyNameUNSAFE);
diff --git a/src/vm/assemblyspec.cpp b/src/vm/assemblyspec.cpp
index 3bd6d38861..2b4b1fb480 100644
--- a/src/vm/assemblyspec.cpp
+++ b/src/vm/assemblyspec.cpp
@@ -1259,19 +1259,28 @@ ICLRPrivBinder* AssemblySpec::GetBindingContextFromParentAssembly(AppDomain *pDo
}
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
+ if (GetPreferFallbackLoadContextBinder())
+ {
+ // If we have been asked to use the fallback load context binder (currently only supported for AssemblyLoadContext.LoadFromAssemblyName),
+ // then pretend we do not have any binder yet available.
+ _ASSERTE(GetFallbackLoadContextBinderForRequestingAssembly() != NULL);
+ pParentAssemblyBinder = NULL;
+ }
+
if (pParentAssemblyBinder == NULL)
{
// If the parent assembly binder is not available, then we maybe dealing with one of the following
// assembly scenarios:
//
// 1) Domain Neutral assembly
- // 2) RefEmitted assembly
- // 3) Entrypoint assembly
+ // 2) Entrypoint assembly
+ // 3) RefEmitted assembly
+ // 4) AssemblyLoadContext.LoadFromAssemblyName
//
- // For (1) and (3), we will need to bind against the DefaultContext binder (aka TPA Binder). This happens
+ // For (1) and (2), we will need to bind against the DefaultContext binder (aka TPA Binder). This happens
// below if we do not find the parent assembly binder.
//
- // For (2), check if we have the fallback load context binder for the requesting dynamic assembly available.
+ // For (3) and (4), fetch the fallback load context binder reference.
pParentAssemblyBinder = GetFallbackLoadContextBinderForRequestingAssembly();
}
diff --git a/src/vm/assemblyspec.hpp b/src/vm/assemblyspec.hpp
index 84e67dfcc2..a7e9c0f203 100644
--- a/src/vm/assemblyspec.hpp
+++ b/src/vm/assemblyspec.hpp
@@ -45,6 +45,9 @@ class AssemblySpec : public BaseAssemblySpec
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
// Contains the reference to the fallback load context associated with RefEmitted assembly requesting the load of another assembly (static or dynamic)
ICLRPrivBinder *m_pFallbackLoadContextBinder;
+
+ // Flag to indicate if we should prefer the fallback load context binder for binding or not.
+ bool m_fPreferFallbackLoadContextBinder;
#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
BOOL IsValidAssemblyName();
@@ -74,7 +77,8 @@ class AssemblySpec : public BaseAssemblySpec
m_pParentAssembly = NULL;
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
- m_pFallbackLoadContextBinder = NULL;
+ m_pFallbackLoadContextBinder = NULL;
+ m_fPreferFallbackLoadContextBinder = false;
#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
}
@@ -86,7 +90,8 @@ class AssemblySpec : public BaseAssemblySpec
m_pParentAssembly = NULL;
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
- m_pFallbackLoadContextBinder = NULL;
+ m_pFallbackLoadContextBinder = NULL;
+ m_fPreferFallbackLoadContextBinder = false;
#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
}
@@ -187,6 +192,20 @@ class AssemblySpec : public BaseAssemblySpec
return m_pFallbackLoadContextBinder;
}
+
+ void SetPreferFallbackLoadContextBinder()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ m_fPreferFallbackLoadContextBinder = true;
+ }
+
+ bool GetPreferFallbackLoadContextBinder()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ return m_fPreferFallbackLoadContextBinder;
+ }
#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
// Note that this method does not clone the fields!
@@ -208,6 +227,7 @@ class AssemblySpec : public BaseAssemblySpec
#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
// Copy the details of the fallback load context binder
SetFallbackLoadContextBinderForRequestingAssembly(pSource->GetFallbackLoadContextBinderForRequestingAssembly());
+ m_fPreferFallbackLoadContextBinder = pSource->GetPreferFallbackLoadContextBinder();
#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
m_HashForControl = pSource->m_HashForControl;