Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
31 changes: 21 additions & 10 deletions docs/design/datacontracts/Loader.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ ModuleHandle GetModuleHandleFromModulePtr(TargetPointer module);
ModuleHandle GetModuleHandleFromAssemblyPtr(TargetPointer assemblyPointer);
IEnumerable<ModuleHandle> GetModuleHandles(TargetPointer appDomain, AssemblyIterationFlags iterationFlags);
TargetPointer GetRootAssembly();
string GetAppDomainFriendlyName();
TargetPointer GetModule(ModuleHandle handle);
TargetPointer GetAssembly(ModuleHandle handle);
TargetPointer GetPEAssembly(ModuleHandle handle);
Expand Down Expand Up @@ -114,6 +115,7 @@ bool IsAssemblyLoaded(ModuleHandle handle);
| `CGrowableSymbolStream` | `Size` | Size of the raw symbol stream buffer |
| `AppDomain` | `RootAssembly` | Pointer to the root assembly |
| `AppDomain` | `DomainAssemblyList` | ArrayListBase of assemblies in the AppDomain |
| `AppDomain` | `FriendlyName` | Friendly name of the AppDomain |
| `LoaderAllocator` | `ReferenceCount` | Reference count of LoaderAllocator |
| `ArrayListBase` | `Count` | Total number of elements in the ArrayListBase |
| `ArrayListBase` | `FirstBlock` | First ArrayListBlock |
Expand Down Expand Up @@ -263,6 +265,15 @@ TargetPointer GetRootAssembly()
return appDomain.RootAssembly;
}

string ILoader.GetAppDomainFriendlyName()
{
TargetPointer appDomainPointer = target.ReadGlobalPointer(Constants.Globals.AppDomain);
TargetPointer appDomain = target.ReadPointer(appDomainPointer)
TargetPointer pathStart = appDomain + /* AppDomain::FriendlyName offset */;
char[] name = // Read<char> from target starting at pathStart until null terminator
return new string(name);
}

TargetPointer ILoader.GetModule(ModuleHandle handle)
{
return handle.Address;
Expand Down Expand Up @@ -393,20 +404,20 @@ TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out Tar
uint index = rid;
// have to read lookupMap an extra time upfront because only the first map
// has valid supportedFlagsMask
TargetNUInt supportedFlagsMask = _target.ReadNUInt(table + /* ModuleLookupMap::SupportedFlagsMask */);
TargetNUInt supportedFlagsMask = target.ReadNUInt(table + /* ModuleLookupMap::SupportedFlagsMask */);
do
{
if (index < _target.Read<uint>(table + /*ModuleLookupMap::Count*/))
if (index < target.Read<uint>(table + /*ModuleLookupMap::Count*/))
{
TargetPointer entryAddress = _target.ReadPointer(lookupMap + /*ModuleLookupMap::TableData*/) + (ulong)(index * _target.PointerSize);
TargetPointer rawValue = _target.ReadPointer(entryAddress);
TargetPointer entryAddress = target.ReadPointer(lookupMap + /*ModuleLookupMap::TableData*/) + (ulong)(index * target.PointerSize);
TargetPointer rawValue = target.ReadPointer(entryAddress);
flags = rawValue & supportedFlagsMask;
return rawValue & ~(supportedFlagsMask.Value);
}
else
{
table = _target.ReadPointer(lookupMap + /*ModuleLookupMap::Next*/);
index -= _target.Read<uint>(lookupMap + /*ModuleLookupMap::Count*/);
table = target.ReadPointer(lookupMap + /*ModuleLookupMap::Next*/);
index -= target.Read<uint>(lookupMap + /*ModuleLookupMap::Count*/);
}
} while (table != TargetPointer.Null);
return TargetPointer.Null;
Expand All @@ -416,15 +427,15 @@ TargetPointer GetModuleLookupMapElement(TargetPointer table, uint token, out Tar
```csharp
bool ILoader.IsCollectible(ModuleHandle handle)
{
TargetPointer assembly = _target.ReadPointer(handle.Address + /*Module::Assembly*/);
byte isCollectible = _target.Read<byte>(assembly + /* Assembly::IsCollectible*/);
TargetPointer assembly = target.ReadPointer(handle.Address + /*Module::Assembly*/);
byte isCollectible = target.Read<byte>(assembly + /* Assembly::IsCollectible*/);
return isCollectible != 0;
}

bool ILoader.IsAssemblyLoaded(ModuleHandle handle)
{
TargetPointer assembly = _target.ReadPointer(handle.Address + /*Module::Assembly*/);
uint loadLevel = _target.Read<uint>(assembly + /* Assembly::Level*/);
TargetPointer assembly = target.ReadPointer(handle.Address + /*Module::Assembly*/);
uint loadLevel = target.Read<uint>(assembly + /* Assembly::Level*/);
return assembly.Level >= ASSEMBLY_LEVEL_LOADED;
}
```
1 change: 1 addition & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ CDAC_TYPE_BEGIN(AppDomain)
CDAC_TYPE_INDETERMINATE(AppDomain)
CDAC_TYPE_FIELD(AppDomain, /*pointer*/, RootAssembly, cdac_data<AppDomain>::RootAssembly)
CDAC_TYPE_FIELD(AppDomain, /*DomainAssemblyList*/, DomainAssemblyList, cdac_data<AppDomain>::DomainAssemblyList)
CDAC_TYPE_FIELD(AppDomain, /*pointer*/, FriendlyName, cdac_data<AppDomain>::FriendlyName)
CDAC_TYPE_END(AppDomain)

CDAC_TYPE_BEGIN(ArrayListBase)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/appdomain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,7 @@ struct cdac_data<AppDomain>
{
static constexpr size_t RootAssembly = offsetof(AppDomain, m_pRootAssembly);
static constexpr size_t DomainAssemblyList = offsetof(AppDomain, m_Assemblies) + offsetof(AppDomain::DomainAssemblyList, m_array);
static constexpr size_t FriendlyName = offsetof(AppDomain, m_friendlyName);
};

typedef DPTR(class SystemDomain) PTR_SystemDomain;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public interface ILoader : IContract
ModuleHandle GetModuleHandleFromAssemblyPtr(TargetPointer assemblyPointer) => throw new NotImplementedException();
IEnumerable<ModuleHandle> GetModuleHandles(TargetPointer appDomain, AssemblyIterationFlags iterationFlags) => throw new NotImplementedException();
TargetPointer GetRootAssembly() => throw new NotImplementedException();
string GetAppDomainFriendlyName() => throw new NotImplementedException();
TargetPointer GetModule(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetAssembly(ModuleHandle handle) => throw new NotImplementedException();
TargetPointer GetPEAssembly(ModuleHandle handle) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,21 @@ TargetPointer ILoader.GetRootAssembly()
Data.AppDomain appDomain = _target.ProcessedData.GetOrAdd<Data.AppDomain>(_target.ReadPointer(appDomainPointer));
return appDomain.RootAssembly;
}

string ILoader.GetAppDomainFriendlyName()
{
TargetPointer appDomainPointer = _target.ReadGlobalPointer(Constants.Globals.AppDomain);
Data.AppDomain appDomain = _target.ProcessedData.GetOrAdd<Data.AppDomain>(_target.ReadPointer(appDomainPointer));
return appDomain.FriendlyName != TargetPointer.Null
? _target.ReadUtf16String(appDomain.FriendlyName)
: string.Empty;
}

TargetPointer ILoader.GetModule(ModuleHandle handle)
{
return handle.Address;
}

TargetPointer ILoader.GetAssembly(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,8 +14,10 @@ public AppDomain(Target target, TargetPointer address)

RootAssembly = target.ReadPointer(address + (ulong)type.Fields[nameof(RootAssembly)].Offset);
DomainAssemblyList = address + (ulong)type.Fields[nameof(DomainAssemblyList)].Offset;
FriendlyName = target.ReadPointer(address + (ulong)type.Fields[nameof(FriendlyName)].Offset);
}

public TargetPointer RootAssembly { get; init; }
public TargetPointer DomainAssemblyList { get; init; }
public TargetPointer FriendlyName { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,62 @@ int ISOSDacInterface.GetAppDomainData(ClrDataAddress addr, void* data)
int ISOSDacInterface.GetAppDomainList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ClrDataAddress[] values, uint* pNeeded)
=> _legacyImpl is not null ? _legacyImpl.GetAppDomainList(count, values, pNeeded) : HResults.E_NOTIMPL;
int ISOSDacInterface.GetAppDomainName(ClrDataAddress addr, uint count, char* name, uint* pNeeded)
=> _legacyImpl is not null ? _legacyImpl.GetAppDomainName(addr, count, name, pNeeded) : HResults.E_NOTIMPL;
{
int hr = HResults.S_OK;
try
{
ILoader loader = _target.Contracts.Loader;
string friendlyName = loader.GetAppDomainFriendlyName();
TargetPointer systemDomainPtr = _target.ReadGlobalPointer(Constants.Globals.SystemDomain);
ClrDataAddress systemDomain = _target.ReadPointer(systemDomainPtr).ToClrDataAddress(_target);
if (addr == systemDomain || friendlyName == string.Empty)
{
if (pNeeded is not null)
{
*pNeeded = 1;
}
if (name is not null && count > 0)
{
name[0] = '\0'; // Set the first character to null terminator
}
}
else
{
if (pNeeded is not null)
{
*pNeeded = (uint)(friendlyName.Length + 1); // +1 for null terminator
}

if (name is not null && count > 0)
{
OutputBufferHelpers.CopyStringToBuffer(name, count, pNeeded, friendlyName);
}
}
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacyImpl is not null)
{
uint neededLocal;
char[] nameLocal = new char[count];
int hrLocal;
fixed (char* ptr = nameLocal)
{
hrLocal = _legacyImpl.GetAppDomainName(addr, count, ptr, &neededLocal);
}
Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
if (hr == HResults.S_OK)
{
Debug.Assert(pNeeded == null || *pNeeded == neededLocal);
Debug.Assert(name == null || new ReadOnlySpan<char>(nameLocal, 0, (int)neededLocal - 1).SequenceEqual(new string(name)));
}
}
#endif
return hr;
}
int ISOSDacInterface.GetAppDomainStoreData(void* data)
=> _legacyImpl is not null ? _legacyImpl.GetAppDomainStoreData(data) : HResults.E_NOTIMPL;
int ISOSDacInterface.GetApplicationBase(ClrDataAddress appDomain, int count, char* appBase, uint* pNeeded)
Expand Down
Loading