Skip to content

Commit

Permalink
Introduce native AssemblyLoadContext base class (dotnet#32097)
Browse files Browse the repository at this point in the history
* Add assemblyloadcontext.*

* Make AssemblyContext base class

* Add method to return AssemblyLoadContext
  • Loading branch information
jkotas authored Feb 12, 2020
1 parent 75d8683 commit 0cf87c6
Show file tree
Hide file tree
Showing 17 changed files with 92 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,7 @@ internal Type LoadTypeForWinRTTypeNameInContext(string typeName)
if (ptrAssemblyLoadContext == IntPtr.Zero)
{
// If the load context is returned null, then the assembly was bound using the TPA binder
// and we shall return reference to the active "Default" binder - which could be the TPA binder
// or an overridden CLRPrivBinderAssemblyLoadContext instance.
// and we shall return reference to the "Default" binder.
loadContextForAssembly = AssemblyLoadContext.Default;
}
else
Expand Down
7 changes: 0 additions & 7 deletions src/coreclr/src/binder/clrprivbinderassemblyloadcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,6 @@ Exit:;
return hr;
}

HRESULT CLRPrivBinderAssemblyLoadContext::GetBinderID(
UINT_PTR *pBinderId)
{
*pBinderId = reinterpret_cast<UINT_PTR>(this);
return S_OK;
}

HRESULT CLRPrivBinderAssemblyLoadContext::GetLoaderAllocator(LPVOID* pLoaderAllocator)
{
_ASSERTE(pLoaderAllocator != NULL);
Expand Down
7 changes: 0 additions & 7 deletions src/coreclr/src/binder/clrprivbindercoreclr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,6 @@ Exit:;
}
#endif // !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)

HRESULT CLRPrivBinderCoreCLR::GetBinderID(
UINT_PTR *pBinderId)
{
*pBinderId = reinterpret_cast<UINT_PTR>(this);
return S_OK;
}

HRESULT CLRPrivBinderCoreCLR::SetupBindingPaths(SString &sTrustedPlatformAssemblies,
SString &sPlatformResourceRoots,
SString &sAppPaths,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ class Object;
class Assembly;
class LoaderAllocator;

class CLRPrivBinderAssemblyLoadContext :
public IUnknownCommon<ICLRPrivBinder, IID_ICLRPrivBinder>
class CLRPrivBinderAssemblyLoadContext : public AssemblyLoadContext
{
public:

Expand All @@ -35,9 +34,6 @@ class CLRPrivBinderAssemblyLoadContext :
/* [in] */ IAssemblyName *pIAssemblyName,
/* [retval][out] */ ICLRPrivAssembly **ppAssembly);

STDMETHOD(GetBinderID)(
/* [retval][out] */ UINT_PTR *pBinderId);

STDMETHOD(GetLoaderAllocator)(
/* [retval][out] */ LPVOID *pLoaderAllocator);

Expand Down
6 changes: 2 additions & 4 deletions src/coreclr/src/binder/inc/clrprivbindercoreclr.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@

#include "coreclrbindercommon.h"
#include "applicationcontext.hpp"
#include "assemblyloadcontext.h"

namespace BINDER_SPACE
{
class AssemblyIdentityUTF8;
};

class CLRPrivBinderCoreCLR : public IUnknownCommon<ICLRPrivBinder, IID_ICLRPrivBinder>
class CLRPrivBinderCoreCLR : public AssemblyLoadContext
{
public:

Expand All @@ -25,9 +26,6 @@ class CLRPrivBinderCoreCLR : public IUnknownCommon<ICLRPrivBinder, IID_ICLRPrivB
/* [in] */ IAssemblyName *pIAssemblyName,
/* [retval][out] */ ICLRPrivAssembly **ppAssembly);

STDMETHOD(GetBinderID)(
/* [retval][out] */ UINT_PTR *pBinderId);

STDMETHOD(GetLoaderAllocator)(
/* [retval][out] */ LPVOID *pLoaderAllocator);

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/src/dlls/mscoree/coreclr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ set(CORECLR_LIBRARIES
debug-pal
${LIB_UNWINDER}
cee_wks
v3binder
${END_LIBRARY_GROUP} # End group of libraries that have circular references
mdcompiler_wks
mdruntime_wks
Expand All @@ -103,7 +104,6 @@ set(CORECLR_LIBRARIES
gcinfo # Condition="'$(TargetCpu)'=='amd64' or '$(TargetCpu)' == 'arm' or '$(TargetCpu)' == 'arm64'"
ildbsymlib
utilcode
v3binder
)

if(CLR_CMAKE_TARGET_WIN32)
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/src/dlls/mscorrc/mscorrc.rc
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,6 @@ BEGIN
IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT "Assembly with same name is already loaded"
IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED "Dynamically emitted assemblies are unsupported during host-based resolution."
IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT "Assembly is already bound to an incompatible binding context."
IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT "Default binding context is already attached to managed load context."
END

STRINGTABLE DISCARDABLE
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/src/dlls/mscorrc/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,6 @@
#define IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT 0x2636
#define IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED 0x2637
#define IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_BINDING_CONTEXT 0x2638
#define IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT 0x2639

#define IDS_NATIVE_IMAGE_CANNOT_BE_LOADED_MULTIPLE_TIMES 0x263a

Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/src/tools/crossgen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,28 @@ if(FEATURE_MERGE_JIT_AND_ENGINE)
set(CLRJIT_CROSSGEN clrjit_crossgen)
endif(FEATURE_MERGE_JIT_AND_ENGINE)

if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)
# The following linked options can be inserted into the linker libraries list to
# ensure proper resolving of circular references between a subset of the libraries.
set(START_LIBRARY_GROUP -Wl,--start-group)
set(END_LIBRARY_GROUP -Wl,--end-group)
endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD)

target_link_libraries(crossgen
${START_LIBRARY_GROUP} # Start group of libraries that have circular references
cee_crossgen
v3binder_crossgen
mdcompiler_crossgen
mdruntime_crossgen
mdruntimerw_crossgen
mdhotdata_crossgen
${END_LIBRARY_GROUP} # End group of libraries that have circular references
corguids
${CLRJIT_CROSSGEN}
gcinfo_crossgen
corzap_crossgen
mscorlib_crossgen
utilcode_crossgen
v3binder_crossgen
)

if(CLR_CMAKE_HOST_UNIX)
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/src/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ set(VM_SOURCES_DAC_AND_WKS_COMMON
appdomain.cpp
array.cpp
assembly.cpp
assemblyloadcontext.cpp
baseassemblyspec.cpp
binder.cpp
castcache.cpp
Expand Down Expand Up @@ -139,6 +140,7 @@ set(VM_HEADERS_DAC_AND_WKS_COMMON
appdomain.inl
array.h
assembly.hpp
assemblyloadcontext.h
baseassemblyspec.h
baseassemblyspec.inl
binder.h
Expand Down
16 changes: 16 additions & 0 deletions src/coreclr/src/vm/assemblyloadcontext.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "common.h"

AssemblyLoadContext::AssemblyLoadContext()
{
}

HRESULT AssemblyLoadContext::GetBinderID(
UINT_PTR* pBinderId)
{
*pBinderId = reinterpret_cast<UINT_PTR>(this);
return S_OK;
}
20 changes: 20 additions & 0 deletions src/coreclr/src/vm/assemblyloadcontext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#ifndef _ASSEMBLYLOADCONTEXT_H
#define _ASSEMBLYLOADCONTEXT_H

//
// Unmanaged counter-part of System.Runtime.Loader.AssemblyLoadContext
//
class AssemblyLoadContext : public IUnknownCommon<ICLRPrivBinder, IID_ICLRPrivBinder>
{
public:
AssemblyLoadContext();

STDMETHOD(GetBinderID)(
/* [retval][out] */ UINT_PTR* pBinderId);
};

#endif
4 changes: 0 additions & 4 deletions src/coreclr/src/vm/assemblyname.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@
#include "strongnameinternal.h"
#include "eeconfig.h"

#ifndef URL_ESCAPE_AS_UTF8
#define URL_ESCAPE_AS_UTF8 0x00040000 // Percent-encode all non-ASCII characters as their UTF-8 equivalents.
#endif

FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE)
{
FCALL_CONTRACT;
Expand Down
54 changes: 4 additions & 50 deletions src/coreclr/src/vm/assemblynative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1280,11 +1280,7 @@ INT_PTR QCALLTYPE AssemblyNative::InitializeAssemblyLoadContext(INT_PTR ptrManag
{
// 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.
INT_PTR ptrTPAAssemblyLoadContext = pTPABinderContext->GetManagedAssemblyLoadContext();
if ((ptrTPAAssemblyLoadContext != NULL) && (ptrTPAAssemblyLoadContext != ptrManagedAssemblyLoadContext))
{
COMPlusThrow(kInvalidOperationException, IDS_HOST_ASSEMBLY_RESOLVER_INCOMPATIBLE_TPA_BINDING_CONTEXT);
}
_ASSERTE(pTPABinderContext->GetManagedAssemblyLoadContext() == NULL);

// Attach the managed TPA binding context with the native one.
pTPABinderContext->SetManagedAssemblyLoadContext(ptrManagedAssemblyLoadContext);
Expand Down Expand Up @@ -1325,55 +1321,13 @@ INT_PTR QCALLTYPE AssemblyNative::GetLoadContextForAssembly(QCall::AssemblyHandl

_ASSERTE(pAssembly != NULL);

// Get the PEAssembly for the RuntimeAssembly
PEFile *pPEFile = pAssembly->GetFile();
PTR_PEAssembly pPEAssembly = pPEFile ? pPEFile->AsAssembly() : NULL;

// Platform assemblies are semantically bound against the "Default" binder.
// The reference to the same will be returned when this QCall returns.

// Get the binding context for the assembly.
//
ICLRPrivBinder *pOpaqueBinder = nullptr;
AppDomain *pCurDomain = AppDomain::GetCurrentDomain();
CLRPrivBinderCoreCLR *pTPABinder = pCurDomain->GetTPABinderContext();

// GetBindingContext returns a ICLRPrivAssembly which can be used to get access to the
// actual ICLRPrivBinder instance in which the assembly was loaded.
PTR_ICLRPrivBinder pBindingContext = pPEAssembly->GetBindingContext();
UINT_PTR assemblyBinderID = 0;

if (pBindingContext)
{
IfFailThrow(pBindingContext->GetBinderID(&assemblyBinderID));

// If the assembly was bound using the TPA binder,
// then we will return the reference to "Default" binder from the managed implementation when this QCall returns.
//
// See earlier comment about "Default" binder for additional context.
pOpaqueBinder = reinterpret_cast<ICLRPrivBinder *>(assemblyBinderID);
}
else
{
// GetBindingContext() returns NULL for System.Private.CoreLib
pOpaqueBinder = pTPABinder;
}
AssemblyLoadContext* pAssemblyLoadContext = pAssembly->GetFile()->GetAssemblyLoadContext();

// We should have a load context binder at this point.
_ASSERTE(pOpaqueBinder != nullptr);

// the TPA binder uses the default ALC
// WinRT assemblies (bound using the WinRT binder) don't actually have an ALC,
// so treat them the same as if they were loaded into the TPA ALC in this case.
#ifdef FEATURE_COMINTEROP
if (!AreSameBinderInstance(pTPABinder, pOpaqueBinder) && !AreSameBinderInstance(pCurDomain->GetWinRtBinder(), pOpaqueBinder))
#else
if (!AreSameBinderInstance(pTPABinder, pOpaqueBinder))
#endif // FEATURE_COMINTEROP
if (pAssemblyLoadContext != AppDomain::GetCurrentDomain()->GetTPABinderContext())
{
// Only CLRPrivBinderAssemblyLoadContext instance contains the reference to its
// corresponding managed instance.
CLRPrivBinderAssemblyLoadContext *pBinder = (CLRPrivBinderAssemblyLoadContext *)(pOpaqueBinder);
CLRPrivBinderAssemblyLoadContext* pBinder = (CLRPrivBinderAssemblyLoadContext*)(pAssemblyLoadContext);

// Fetch the managed binder reference from the native binder instance
ptrManagedAssemblyLoadContext = pBinder->GetManagedAssemblyLoadContext();
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/src/vm/crossgen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(VM_CROSSGEN_SOURCES
../appdomain.cpp
../array.cpp
../assembly.cpp
../assemblyloadcontext.cpp
../assemblyspec.cpp
../baseassemblyspec.cpp
../binder.cpp
Expand Down Expand Up @@ -91,6 +92,7 @@ set(VM_CROSSGEN_HEADERS
../appdomain.inl
../array.h
../assembly.hpp
../assemblyloadcontext.h
../assemblyspec.hpp
../assemblyspecbase.h
../baseassemblyspec.h
Expand Down
29 changes: 28 additions & 1 deletion src/coreclr/src/vm/pefile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2448,7 +2448,6 @@ PTR_ICLRPrivBinder PEFile::GetBindingContext()

// CoreLibrary is always bound in context of the TPA Binder. However, since it gets loaded and published
// during EEStartup *before* DefaultContext Binder (aka TPAbinder) is initialized, we dont have a binding context to publish against.
// Thus, we will always return NULL for its binding context.
if (!IsSystem())
{
pBindingContext = dac_cast<PTR_ICLRPrivBinder>(GetHostAssembly());
Expand All @@ -2466,3 +2465,31 @@ PTR_ICLRPrivBinder PEFile::GetBindingContext()

return pBindingContext;
}

#ifndef DACCESS_COMPILE
AssemblyLoadContext* PEFile::GetAssemblyLoadContext()
{
LIMITED_METHOD_CONTRACT;

PTR_ICLRPrivBinder pBindingContext = GetBindingContext();
ICLRPrivBinder* pOpaqueBinder = NULL;

if (pBindingContext != NULL)
{
UINT_PTR assemblyBinderID = 0;
IfFailThrow(pBindingContext->GetBinderID(&assemblyBinderID));

pOpaqueBinder = reinterpret_cast<ICLRPrivBinder*>(assemblyBinderID);

#ifdef FEATURE_COMINTEROP
// Treat WinRT assemblies (bound using the WinRT binder) as if they were loaded into the TPA ALC
if (AreSameBinderInstance(AppDomain::GetCurrentDomain()->GetWinRtBinder(), pOpaqueBinder))
{
pOpaqueBinder = NULL;
}
#endif
}

return (pOpaqueBinder != NULL) ? (AssemblyLoadContext*)pOpaqueBinder : AppDomain::GetCurrentDomain()->GetTPABinderContext();
}
#endif
7 changes: 5 additions & 2 deletions src/coreclr/src/vm/pefile.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class PEFile;
class PEModule;
class PEAssembly;
class SimpleRWLock;
class AssemblyLoadContext;

typedef VPTR(PEModule) PTR_PEModule;
typedef VPTR(PEAssembly) PTR_PEAssembly;
Expand Down Expand Up @@ -568,6 +569,8 @@ class PEFile
// Returns the ICLRPrivBinder* instance associated with the PEFile
PTR_ICLRPrivBinder GetBindingContext();

AssemblyLoadContext* GetAssemblyLoadContext();

bool HasHostAssembly()
{ STATIC_CONTRACT_WRAPPER; return GetHostAssembly() != nullptr; }

Expand Down Expand Up @@ -729,8 +732,8 @@ class PEAssembly : public PEFile
// Indicates if the assembly can be cached in a binding cache such as AssemblySpecBindingCache.
inline bool CanUseWithBindingCache()
{
STATIC_CONTRACT_WRAPPER;
return (HasBindableIdentity());
STATIC_CONTRACT_WRAPPER;
return (HasBindableIdentity());
}
};

Expand Down

0 comments on commit 0cf87c6

Please sign in to comment.