summaryrefslogtreecommitdiff
path: root/src/binder
diff options
context:
space:
mode:
authorGaurav Khanna <gkhanna@microsoft.com>2016-05-20 17:03:08 -0700
committerGaurav Khanna <gkhanna@microsoft.com>2016-05-20 17:04:26 -0700
commitefa0c0ee49e7a4d045adcbba2de0f38aa50ae2c5 (patch)
tree08c0bdd4b3874ee782480d0497707a0b59cae8d8 /src/binder
parentce3ff76234bf199b4498a5d31f05af6eb43073f6 (diff)
downloadcoreclr-efa0c0ee49e7a4d045adcbba2de0f38aa50ae2c5.tar.gz
coreclr-efa0c0ee49e7a4d045adcbba2de0f38aa50ae2c5.tar.bz2
coreclr-efa0c0ee49e7a4d045adcbba2de0f38aa50ae2c5.zip
Enable overriding of TPA assemblies
Diffstat (limited to 'src/binder')
-rw-r--r--src/binder/assemblybinder.cpp10
-rw-r--r--src/binder/clrprivbinderassemblyloadcontext.cpp58
-rw-r--r--src/binder/clrprivbindercoreclr.cpp3
-rw-r--r--src/binder/inc/assemblybinder.hpp1
4 files changed, 31 insertions, 41 deletions
diff --git a/src/binder/assemblybinder.cpp b/src/binder/assemblybinder.cpp
index a1982ebb37..517eac99d6 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,