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
10 changes: 9 additions & 1 deletion docs/design/datacontracts/Loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ TargetPointer GetStubHeap(TargetPointer loaderAllocatorPointer);
| `ModuleLookupMap` | `Count` | Number of TargetPointer sized entries in this section of the map |
| `ModuleLookupMap` | `Next` | Pointer to next ModuleLookupMap segment for this map |
| `Assembly` | `Module` | Pointer to the Assemblies module |
| `Assembly` | `IsCollectible` | Flag indicating if this is module may be collected |
| `Assembly` | `IsCollectible` | Flag indicating if this module may be collected |
| `Assembly` | `IsDynamic` | Flag indicating if this module is dynamic |
| `Assembly` | `Error` | Pointer to exception. No error if nullptr |
| `Assembly` | `NotifyFlags` | Flags relating to the debugger/profiler notification state of the assembly |
| `Assembly` | `Level` | File load level of the assembly |
Expand Down Expand Up @@ -481,6 +482,13 @@ bool IsCollectible(ModuleHandle handle)
return isCollectible != 0;
}

bool IsDynamic(ModuleHandle handle)
{
TargetPointer assembly = target.ReadPointer(handle.Address + /*Module::Assembly*/);
byte isDynamic = target.Read<byte>(assembly + /* Assembly::IsDynamic*/);
return isDynamic != 0;
}

bool IsAssemblyLoaded(ModuleHandle handle)
{
TargetPointer assembly = target.ReadPointer(handle.Address + /*Module::Assembly*/);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/assembly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ struct cdac_data<Assembly>
#ifdef FEATURE_COLLECTIBLE_TYPES
static constexpr size_t IsCollectible = offsetof(Assembly, m_isCollectible);
#endif
static constexpr size_t IsDynamic = offsetof(Assembly, m_isDynamic);
static constexpr size_t Module = offsetof(Assembly, m_pModule);
static constexpr size_t Error = offsetof(Assembly, m_pError);
static constexpr size_t NotifyFlags = offsetof(Assembly, m_notifyFlags);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ CDAC_TYPE_INDETERMINATE(Assembly)
#ifdef FEATURE_COLLECTIBLE_TYPES
CDAC_TYPE_FIELD(Assembly, /*uint8*/, IsCollectible, cdac_data<Assembly>::IsCollectible)
#endif
CDAC_TYPE_FIELD(Assembly, /*bool*/, IsDynamic, cdac_data<Assembly>::IsDynamic)
CDAC_TYPE_FIELD(Assembly, /*pointer*/, Module, cdac_data<Assembly>::Module)
CDAC_TYPE_FIELD(Assembly, /*pointer*/, Error, cdac_data<Assembly>::Error)
CDAC_TYPE_FIELD(Assembly, /*uint32*/, NotifyFlags, cdac_data<Assembly>::NotifyFlags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public interface ILoader : IContract
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();
bool IsDynamic(ModuleHandle handle) => throw new NotImplementedException();
bool IsAssemblyLoaded(ModuleHandle handle) => throw new NotImplementedException();

TargetPointer GetGlobalLoaderAllocator() => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,17 @@ TargetPointer ILoader.GetModuleLookupMapElement(TargetPointer table, uint token,
bool ILoader.IsCollectible(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
TargetPointer assembly = module.Assembly;
Data.Assembly la = _target.ProcessedData.GetOrAdd<Data.Assembly>(assembly);
Data.Assembly la = _target.ProcessedData.GetOrAdd<Data.Assembly>(module.Assembly);
return la.IsCollectible != 0;
}

bool ILoader.IsDynamic(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
Data.Assembly assembly = _target.ProcessedData.GetOrAdd<Data.Assembly>(module.Assembly);
return assembly.IsDynamic;
}

bool ILoader.IsAssemblyLoaded(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ public Assembly(Target target, TargetPointer address)

Module = target.ReadPointer(address + (ulong)type.Fields[nameof(Module)].Offset);
IsCollectible = target.Read<byte>(address + (ulong)type.Fields[nameof(IsCollectible)].Offset);
IsDynamic = target.Read<byte>(address + (ulong)type.Fields[nameof(IsDynamic)].Offset) != 0;
Error = target.ReadPointer(address + (ulong)type.Fields[nameof(Error)].Offset);
NotifyFlags = target.Read<uint>(address + (ulong)type.Fields[nameof(NotifyFlags)].Offset);
Level = target.Read<uint>(address + (ulong)type.Fields[nameof(Level)].Offset);
}

public TargetPointer Module { get; init; }
public byte IsCollectible { get; init; }
public bool IsDynamic { get; init; }
public TargetPointer Error { get; init; }
public uint NotifyFlags { get; init; }
public uint Level { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ internal struct DacpAppDomainStoreData
public ClrDataAddress systemDomain;
public int DomainCount;
};

internal struct DacpAssemblyData
{
public ClrDataAddress AssemblyPtr;
public ClrDataAddress ClassLoader;
public ClrDataAddress ParentDomain;
public ClrDataAddress DomainPtr;
public ClrDataAddress AssemblySecDesc;
public int isDynamic;
public uint ModuleCount;
public uint LoadContext;
public int isDomainNeutral; // Always false, preserved for backward compatibility
public uint dwLocationFlags;
}

internal struct DacpThreadData
{
public int corThreadId;
Expand Down Expand Up @@ -270,7 +285,7 @@ internal unsafe partial interface ISOSDacInterface
[PreserveSig]
int GetAssemblyList(ClrDataAddress appDomain, int count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ClrDataAddress[]? values, int* pNeeded);
[PreserveSig]
int GetAssemblyData(ClrDataAddress baseDomainPtr, ClrDataAddress assembly, /*struct DacpAssemblyData*/ void* data);
int GetAssemblyData(ClrDataAddress domain, ClrDataAddress assembly, DacpAssemblyData* data);
[PreserveSig]
int GetAssemblyName(ClrDataAddress assembly, uint count, char* name, uint* pNeeded);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,65 @@ int ISOSDacInterface.GetApplicationBase(ClrDataAddress appDomain, int count, cha

return hr;
}
int ISOSDacInterface.GetAssemblyData(ClrDataAddress baseDomainPtr, ClrDataAddress assembly, void* data)
=> _legacyImpl is not null ? _legacyImpl.GetAssemblyData(baseDomainPtr, assembly, data) : HResults.E_NOTIMPL;

int ISOSDacInterface.GetAssemblyData(ClrDataAddress domain, ClrDataAddress assembly, DacpAssemblyData* data)
{
int hr = HResults.S_OK;

try
{
if (assembly == 0 && domain == 0)
throw new ArgumentException();

// Zero out data structure
*data = default;

data->AssemblyPtr = assembly;
data->DomainPtr = domain;

TargetPointer ppAppDomain = _target.ReadGlobalPointer(Constants.Globals.AppDomain);
TargetPointer pAppDomain = _target.ReadPointer(ppAppDomain);
data->ParentDomain = pAppDomain.ToClrDataAddress(_target);

ILoader loader = _target.Contracts.Loader;
Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromAssemblyPtr(assembly.ToTargetPointer(_target));
data->isDynamic = loader.IsDynamic(moduleHandle) ? 1 : 0;

// The DAC increments ModuleCount to 1 if assembly->GetModule() is valid,
// the cDAC assumes that all assemblies will have a module and the above logic relies on that.
// Therefore we always set ModuleCount to 1.
data->ModuleCount = 1;
}
catch (System.Exception ex)
{
hr = ex.HResult;
}

#if DEBUG
if (_legacyImpl is not null)
{
DacpAssemblyData dataLocal = default;
int hrLocal = _legacyImpl.GetAssemblyData(domain, assembly, &dataLocal);
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
if (hr == HResults.S_OK)
{
Debug.Assert(data->AssemblyPtr == dataLocal.AssemblyPtr, $"cDAC: {data->AssemblyPtr:x}, DAC: {dataLocal.AssemblyPtr:x}");
Debug.Assert(data->ClassLoader == dataLocal.ClassLoader, $"cDAC: {data->ClassLoader:x}, DAC: {dataLocal.ClassLoader:x}");
Debug.Assert(data->ParentDomain == dataLocal.ParentDomain, $"cDAC: {data->ParentDomain:x}, DAC: {dataLocal.ParentDomain:x}");
Debug.Assert(data->DomainPtr == dataLocal.DomainPtr, $"cDAC: {data->DomainPtr:x}, DAC: {dataLocal.DomainPtr:x}");
Debug.Assert(data->AssemblySecDesc == dataLocal.AssemblySecDesc, $"cDAC: {data->AssemblySecDesc:x}, DAC: {dataLocal.AssemblySecDesc:x}");
Debug.Assert(data->isDynamic == dataLocal.isDynamic, $"cDAC: {data->isDynamic}, DAC: {dataLocal.isDynamic}");
Debug.Assert(data->ModuleCount == dataLocal.ModuleCount, $"cDAC: {data->ModuleCount}, DAC: {dataLocal.ModuleCount}");
Debug.Assert(data->LoadContext == dataLocal.LoadContext, $"cDAC: {data->LoadContext:x}, DAC: {dataLocal.LoadContext:x}");
Debug.Assert(data->isDomainNeutral == dataLocal.isDomainNeutral, $"cDAC: {data->isDomainNeutral}, DAC: {dataLocal.isDomainNeutral}");
Debug.Assert(data->dwLocationFlags == dataLocal.dwLocationFlags, $"cDAC: {data->dwLocationFlags:x}, DAC: {dataLocal.dwLocationFlags:x}");
}
}
#endif

return hr;
}

int ISOSDacInterface.GetAssemblyList(ClrDataAddress addr, int count, [In, MarshalUsing(CountElementName = "count"), Out] ClrDataAddress[]? values, int* pNeeded)
{
if (addr == 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ internal record TypeFields
[
new(nameof(Data.Assembly.Module), DataType.pointer),
new(nameof(Data.Assembly.IsCollectible), DataType.uint8),
new(nameof(Data.Assembly.IsDynamic), DataType.uint8),
new(nameof(Data.Assembly.Error), DataType.pointer),
new(nameof(Data.Assembly.NotifyFlags), DataType.uint32),
new(nameof(Data.Assembly.Level), DataType.uint32),
Expand Down
Loading