Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/design/datacontracts/Loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ string GetPath(ModuleHandle handle);
string GetFileName(ModuleHandle handle);
TargetPointer GetLoaderAllocator(ModuleHandle handle);
TargetPointer GetILBase(ModuleHandle handle);
TargetPointer GetAssemblyLoadContext(ModuleHandle handle);
ModuleLookupTables GetLookupTables(ModuleHandle handle);
TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out TargetNUInt flags);
bool IsCollectible(ModuleHandle handle);
Expand Down Expand Up @@ -106,6 +107,8 @@ TargetPointer GetStubHeap(TargetPointer loaderAllocatorPointer);
| `Assembly` | `NotifyFlags` | Flags relating to the debugger/profiler notification state of the assembly |
| `Assembly` | `Level` | File load level of the assembly |
| `PEAssembly` | `PEImage` | Pointer to the PEAssembly's PEImage |
| `PEAssembly` | `AssemblyBinder` | Pointer to the PEAssembly's binder |
| `AssemblyBinder` | `ManagedAssemblyLoadContext` | Pointer to the AssemblyBinder's ManagedAssemblyLoadContext |
| `PEImage` | `LoadedImageLayout` | Pointer to the PEImage's loaded PEImageLayout |
| `PEImage` | `ProbeExtensionResult` | PEImage's ProbeExtensionResult |
| `ProbeExtensionResult` | `Type` | Type of ProbeExtensionResult |
Expand Down Expand Up @@ -373,6 +376,14 @@ TargetPointer GetILBase(ModuleHandle handle)
return target.ReadPointer(handle.Address + /* Module::Base offset */);
}

TargetPointer ILoader.GetAssemblyLoadContext(ModuleHandle handle)
{
PEAssembly peAssembly = target.ReadPointer(handle.Address + /* Module::PEAssembly offset */);
AssemblyBinder binder = target.ReadPointer(peAssembly + /* PEAssembly::AssemblyBinder offset */);
ObjectHandle objectHandle = new ObjectHandle(binder);
return objectHandle.Object;
}

ModuleLookupTables GetLookupTables(ModuleHandle handle)
{
return new ModuleLookupTables(
Expand Down
7 changes: 0 additions & 7 deletions docs/design/datacontracts/Thread.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ record struct ThreadData (
ThreadStoreData GetThreadStoreData();
ThreadStoreCounts GetThreadCounts();
ThreadData GetThreadData(TargetPointer threadPointer);
TargetPointer GetManagedThreadObject(TargetPointer threadPointer);
```

## Version 1
Expand Down Expand Up @@ -128,10 +127,4 @@ ThreadData GetThreadData(TargetPointer address)
NextThread: target.ReadPointer(address + /* Thread::LinkNext offset */) - threadLinkOffset;
);
}

TargetPointer GetManagedThreadObject(TargetPointer threadPointer)
{
var runtimeThread = new Thread(Target, threadPointer);
return Contracts.GCHandle.GetObject(new DacGCHandle(runtimeThread.m_ExposedObject));
}
```
6 changes: 6 additions & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,14 @@ CDAC_TYPE_END(LoaderAllocator)
CDAC_TYPE_BEGIN(PEAssembly)
CDAC_TYPE_INDETERMINATE(PEAssembly)
CDAC_TYPE_FIELD(PEAssembly, /*pointer*/, PEImage, cdac_data<PEAssembly>::PEImage)
CDAC_TYPE_FIELD(PEAssembly, /*pointer*/, AssemblyBinder, cdac_data<PEAssembly>::AssemblyBinder)
CDAC_TYPE_END(PEAssembly)

CDAC_TYPE_BEGIN(AssemblyBinder)
CDAC_TYPE_INDETERMINATE(AssemblyBinder)
CDAC_TYPE_FIELD(AssemblyBinder, /*pointer*/, ManagedAssemblyLoadContext, cdac_data<AssemblyBinder>::ManagedAssemblyLoadContext)
CDAC_TYPE_END(AssemblyBinder)

CDAC_TYPE_BEGIN(PEImage)
CDAC_TYPE_INDETERMINATE(PEImage)
CDAC_TYPE_FIELD(PEImage, /*pointer*/, LoadedImageLayout, cdac_data<PEImage>::LoadedImageLayout)
Expand Down
5 changes: 1 addition & 4 deletions src/coreclr/vm/assembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,7 @@ Assembly *Assembly::CreateDynamic(AssemblyBinder* pBinder, NativeAssemblyNamePar
IfFailThrow(pAssemblyEmit->DefineAssembly(pAssemblyNameParts->_pPublicKeyOrToken, pAssemblyNameParts->_cbPublicKeyOrToken, hashAlgorithm,
pAssemblyNameParts->_pName, &assemData, pAssemblyNameParts->_flags,
&ma));
pPEAssembly = PEAssembly::Create(pAssemblyEmit);

// Set it as the fallback load context binder for the dynamic assembly being created
pPEAssembly->SetFallbackBinder(pBinder);
pPEAssembly = PEAssembly::Create(pAssemblyEmit, pBinder);
}

AppDomain* pDomain = ::GetAppDomain();
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/vm/assemblybinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,12 @@ class AssemblyBinder
INT_PTR m_ptrManagedAssemblyLoadContext;

SArray<Assembly*> m_loadedAssemblies;
friend struct cdac_data<AssemblyBinder>;
};

template<>
struct cdac_data<AssemblyBinder>
{
static constexpr size_t ManagedAssemblyLoadContext = offsetof(AssemblyBinder, m_ptrManagedAssemblyLoadContext);
};
#endif
39 changes: 15 additions & 24 deletions src/coreclr/vm/peassembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ PEAssembly::PEAssembly(
BINDER_SPACE::Assembly* pBindResultInfo,
IMetaDataEmit* pEmit,
BOOL isSystem,
AssemblyBinder* pFallbackBinder /*= NULL*/,
PEImage * pPEImage /*= NULL*/,
BINDER_SPACE::Assembly * pHostAssembly /*= NULL*/)
{
Expand All @@ -670,7 +671,7 @@ PEAssembly::PEAssembly(
m_refCount = 1;
m_isSystem = isSystem;
m_pHostAssembly = nullptr;
m_pFallbackBinder = nullptr;
m_pAssemblyBinder = nullptr;

pPEImage = pBindResultInfo ? pBindResultInfo->GetPEImage() : pPEImage;
if (pPEImage)
Expand Down Expand Up @@ -722,6 +723,15 @@ PEAssembly::PEAssembly(
m_pHostAssembly = pBindResultInfo;
}

if (m_pHostAssembly != nullptr)
{
m_pAssemblyBinder = m_pHostAssembly->GetBinder();
}
else
{
m_pAssemblyBinder = pFallbackBinder;
}

#ifdef LOGGING
GetPathOrCodeBase(m_debugName);
m_pDebugName = m_debugName.GetUTF8();
Expand All @@ -740,6 +750,7 @@ PEAssembly *PEAssembly::Open(
nullptr, // BindResult
nullptr, // IMetaDataEmit
FALSE, // isSystem
nullptr, // FallbackBinder
pPEImageIL,
pHostAssembly);

Expand Down Expand Up @@ -833,7 +844,7 @@ PEAssembly* PEAssembly::Open(BINDER_SPACE::Assembly* pBindResult)
};

/* static */
PEAssembly *PEAssembly::Create(IMetaDataAssemblyEmit *pAssemblyEmit)
PEAssembly *PEAssembly::Create(IMetaDataAssemblyEmit *pAssemblyEmit, AssemblyBinder *pFallbackBinder)
{
CONTRACT(PEAssembly *)
{
Expand All @@ -847,7 +858,7 @@ PEAssembly *PEAssembly::Create(IMetaDataAssemblyEmit *pAssemblyEmit)
// we have.)
SafeComHolder<IMetaDataEmit> pEmit;
pAssemblyEmit->QueryInterface(IID_IMetaDataEmit, (void **)&pEmit);
RETURN new PEAssembly(NULL, pEmit, FALSE);
RETURN new PEAssembly(NULL, pEmit, FALSE, pFallbackBinder);
}

#endif // #ifndef DACCESS_COMPILE
Expand Down Expand Up @@ -1083,25 +1094,5 @@ TADDR PEAssembly::GetMDInternalRWAddress()
// Returns the AssemblyBinder* instance associated with the PEAssembly
PTR_AssemblyBinder PEAssembly::GetAssemblyBinder()
{
LIMITED_METHOD_CONTRACT;

PTR_AssemblyBinder pBinder = NULL;

PTR_BINDER_SPACE_Assembly pHostAssembly = GetHostAssembly();
if (pHostAssembly)
{
pBinder = pHostAssembly->GetBinder();
}
else
{
// If we do not have a host assembly, check if we are dealing with
// a dynamically emitted assembly and if so, use its fallback load context
// binder reference.
if (IsReflectionEmit())
{
pBinder = GetFallbackBinder();
}
}

return pBinder;
return m_pAssemblyBinder;
}
32 changes: 12 additions & 20 deletions src/coreclr/vm/peassembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,20 +312,18 @@ class PEAssembly final
// For Dynamic assemblies this is the fallback binder.
PTR_AssemblyBinder GetAssemblyBinder();

#ifndef DACCESS_COMPILE
void SetFallbackBinder(PTR_AssemblyBinder pFallbackBinder)
{
LIMITED_METHOD_CONTRACT;
m_pFallbackBinder = pFallbackBinder;
}

#endif //!DACCESS_COMPILE

// 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,
// we need to ensure they are loaded in appropriate load context.
//
// 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 GetFallbackBinder()
{
LIMITED_METHOD_CONTRACT;

return m_pFallbackBinder;
return (m_pHostAssembly != NULL) ? NULL : m_pAssemblyBinder;
}

// ------------------------------------------------------------
Expand All @@ -341,7 +339,7 @@ class PEAssembly final

static PEAssembly* Open(BINDER_SPACE::Assembly* pBindResult);

static PEAssembly* Create(IMetaDataAssemblyEmit* pEmit);
static PEAssembly* Create(IMetaDataAssemblyEmit* pEmit, AssemblyBinder* pFallbackBinder);

// ------------------------------------------------------------
// Utility functions
Expand Down Expand Up @@ -372,6 +370,7 @@ class PEAssembly final
BINDER_SPACE::Assembly* pBindResultInfo,
IMetaDataEmit* pEmit,
BOOL isSystem,
AssemblyBinder* pFallbackBinder = NULL,
PEImage* pPEImageIL = NULL,
BINDER_SPACE::Assembly* pHostAssembly = NULL
);
Expand Down Expand Up @@ -425,15 +424,7 @@ class PEAssembly final
bool m_isSystem;

PTR_BINDER_SPACE_Assembly 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,
// we need to ensure they are loaded in appropriate load context.
//
// 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;
PTR_AssemblyBinder m_pAssemblyBinder;

friend struct cdac_data<PEAssembly>;
}; // class PEAssembly
Expand All @@ -442,6 +433,7 @@ template<>
struct cdac_data<PEAssembly>
{
static constexpr size_t PEImage = offsetof(PEAssembly, m_PEImage);
static constexpr size_t AssemblyBinder = offsetof(PEAssembly, m_pAssemblyBinder);
};

typedef ReleaseHolder<PEAssembly> PEAssemblyHolder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public interface ILoader : IContract
string GetFileName(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetLoaderAllocator(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetILBase(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetAssemblyLoadContext(ModuleHandle handle) => throw new NotImplementedException();
ModuleLookupTables GetLookupTables(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out TargetNUInt flags) => throw new NotImplementedException();
bool IsCollectible(ModuleHandle handle) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public enum DataType
Assembly,
LoaderAllocator,
PEAssembly,
AssemblyBinder,
PEImage,
PEImageLayout,
CGrowableSymbolStream,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,15 @@ TargetPointer ILoader.GetILBase(ModuleHandle handle)
return module.Base;
}

TargetPointer ILoader.GetAssemblyLoadContext(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
Data.PEAssembly peAssembly = _target.ProcessedData.GetOrAdd<Data.PEAssembly>(module.PEAssembly);
Data.AssemblyBinder binder = _target.ProcessedData.GetOrAdd<Data.AssemblyBinder>(peAssembly.AssemblyBinder);
Data.ObjectHandle objectHandle = _target.ProcessedData.GetOrAdd<Data.ObjectHandle>(binder.ManagedAssemblyLoadContext);
return objectHandle.Object;
}

ModuleLookupTables ILoader.GetLookupTables(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +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;

namespace Microsoft.Diagnostics.DataContractReader.Data;

internal sealed class AssemblyBinder : IData<AssemblyBinder>
{
static AssemblyBinder IData<AssemblyBinder>.Create(Target target, TargetPointer address) => new AssemblyBinder(target, address);
public AssemblyBinder(Target target, TargetPointer address)
{
Target.TypeInfo type = target.GetTypeInfo(DataType.AssemblyBinder);
ManagedAssemblyLoadContext = target.ReadPointer(address + (ulong)type.Fields[nameof(ManagedAssemblyLoadContext)].Offset);
}
public TargetPointer ManagedAssemblyLoadContext { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ public PEAssembly(Target target, TargetPointer address)
Target.TypeInfo type = target.GetTypeInfo(DataType.PEAssembly);

PEImage = target.ReadPointer(address + (ulong)type.Fields[nameof(PEImage)].Offset);
AssemblyBinder = target.ReadPointer(address + (ulong)type.Fields[nameof(AssemblyBinder)].Offset);
}

public TargetPointer PEImage { get; init; }
public TargetPointer AssemblyBinder { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2229,7 +2229,40 @@ int ISOSDacInterface8.GetFinalizationFillPointersSvr(ClrDataAddress heapAddr, ui
=> _legacyImpl8 is not null ? _legacyImpl8.GetFinalizationFillPointersSvr(heapAddr, cFillPointers, pFinalizationFillPointers, pNeeded) : HResults.E_NOTIMPL;

int ISOSDacInterface8.GetAssemblyLoadContext(ClrDataAddress methodTable, ClrDataAddress* assemblyLoadContext)
=> _legacyImpl8 is not null ? _legacyImpl8.GetAssemblyLoadContext(methodTable, assemblyLoadContext) : HResults.E_NOTIMPL;
{
int hr = HResults.S_OK;
try
{
if (methodTable == 0 || assemblyLoadContext == null)
hr = HResults.E_INVALIDARG;
else
{
Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem;
Contracts.ILoader loaderContract = _target.Contracts.Loader;
Contracts.TypeHandle methodTableHandle = rtsContract.GetTypeHandle(methodTable.ToTargetPointer(_target));
Contracts.ModuleHandle moduleHandle = loaderContract.GetModuleHandleFromModulePtr(rtsContract.GetModule(methodTableHandle));
TargetPointer alc = loaderContract.GetAssemblyLoadContext(moduleHandle);
*assemblyLoadContext = alc.ToClrDataAddress(_target);
}
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacyImpl8 is not null)
{
ClrDataAddress assemblyLoadContextLocal;
int hrLocal = _legacyImpl8.GetAssemblyLoadContext(methodTable, &assemblyLoadContextLocal);
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
if (hr == HResults.S_OK)
{
Debug.Assert(*assemblyLoadContext == assemblyLoadContextLocal);
}
}
#endif
return hr;
}
#endregion ISOSDacInterface8

#region ISOSDacInterface9
Expand Down
Loading