1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 18:11:04 +09:00

[cdac] Implement ISOSDacInterface::GetPEFileName in cDAC (#106358)

- Include Module path in data descriptor
- Implement `GetPath` in `Loader` contract
- Make cDAC implement ISOSDacInterface::GetPEFileName
This commit is contained in:
Elinor Fung 2024-08-13 18:04:18 -07:00 committed by GitHub
parent 605ff6f648
commit 527ab8fe46
Signed by: github
GPG key ID: B5690EEEBB952194
9 changed files with 109 additions and 7 deletions

View file

@ -102,6 +102,7 @@ internal enum AvailableMetadataType
ModuleHandle GetModuleHandle(TargetPointer);
TargetPointer GetAssembly(ModuleHandle handle);
ModuleFlags GetFlags(ModuleHandle handle);
string GetPath(ModuleHandle handle);
TargetPointer GetLoaderAllocator(ModuleHandle handle);
TargetPointer GetThunkHeap(ModuleHandle handle);
TargetPointer GetILBase(ModuleHandle handle);
@ -122,6 +123,7 @@ Data descriptors used:
| `Module` | `Flags` | Assembly of the Module |
| `Module` | `LoaderAllocator` | LoaderAllocator of the Module |
| `Module` | `ThunkHeap` | Pointer to the thunk heap |
| `Module` | `Path` | Path of the Module (UTF-16, null-terminated) |
| `Module` | `DynamicMetadata` | Pointer to saved metadata for reflection emit modules |
| `Module` | `FieldDefToDescMap` | Mapping table |
| `Module` | `ManifestModuleReferencesMap` | Mapping table |
@ -149,6 +151,13 @@ ModuleFlags GetFlags(ModuleHandle handle)
return target.Read<uint>(handle.Address + /* Module::Flags offset */);
}
string GetPath(ModuleHandle handle)
{
TargetPointer pathStart = target.ReadPointer(handle.Address + /* Module::Path offset */);
char[] path = // Read<char> from target starting at pathStart until null terminator
return new string(path);
}
TargetPointer GetLoaderAllocator(ModuleHandle handle)
{
return target.ReadPointer(handle.Address + /* Module::LoaderAllocator offset */);

View file

@ -1243,6 +1243,7 @@ public:
HRESULT GetObjectDataImpl(CLRDATA_ADDRESS addr, struct DacpObjectData *objectData);
HRESULT GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
HRESULT GetObjectStringDataImpl(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR *stringData, unsigned int *pNeeded);
HRESULT GetPEFileNameImpl(CLRDATA_ADDRESS moduleAddr, unsigned int count, _Inout_updates_z_(count) WCHAR *fileName, unsigned int *pNeeded);
HRESULT GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData);
HRESULT GetMethodDescDataImpl(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData);
HRESULT GetMethodDescNameImpl(CLRDATA_ADDRESS methodDesc, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded);

View file

@ -2542,6 +2542,41 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In
return E_INVALIDARG;
SOSDacEnter();
if (m_cdacSos != NULL)
{
hr = m_cdacSos->GetPEFileName(moduleAddr, count, fileName, pNeeded);
if (FAILED(hr))
{
hr = GetPEFileNameImpl(moduleAddr, count, fileName, pNeeded);
}
#ifdef _DEBUG
else
{
NewArrayHolder<WCHAR> fileNameLocal(new WCHAR[count]);
unsigned int neededLocal = 0;
HRESULT hrLocal = GetPEFileNameImpl(moduleAddr, count, fileNameLocal, &neededLocal);
DacAssertsEnabledHolder assertsEnabled;
_ASSERTE(hr == hrLocal);
_ASSERTE(pNeeded == NULL || *pNeeded == neededLocal);
_ASSERTE(fileName == NULL || u16_strncmp(fileName, fileNameLocal, count) == 0);
}
#endif
}
else
{
hr = GetPEFileNameImpl(moduleAddr, count, fileName, pNeeded);;
}
SOSDacLeave();
return hr;
}
HRESULT
ClrDataAccess::GetPEFileNameImpl(CLRDATA_ADDRESS moduleAddr, unsigned int count, _Inout_updates_z_(count) WCHAR *fileName, unsigned int *pNeeded)
{
PTR_Module pModule = PTR_Module(TO_TADDR(moduleAddr));
PEAssembly* pPEAssembly = pModule->GetPEAssembly();
@ -2549,11 +2584,11 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In
if (!pPEAssembly->GetPath().IsEmpty())
{
if (!pPEAssembly->GetPath().DacGetUnicode(count, fileName, pNeeded))
hr = E_FAIL;
return E_FAIL;
}
else if (!pPEAssembly->IsReflectionEmit())
{
hr = E_NOTIMPL;
return E_NOTIMPL;
}
else
{
@ -2564,8 +2599,7 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In
*pNeeded = 1;
}
SOSDacLeave();
return hr;
return S_OK;
}
HRESULT

View file

@ -220,6 +220,7 @@ CDAC_TYPE_FIELD(Module, /*pointer*/, Flags, cdac_data<Module>::Flags)
CDAC_TYPE_FIELD(Module, /*pointer*/, LoaderAllocator, cdac_data<Module>::LoaderAllocator)
CDAC_TYPE_FIELD(Module, /*pointer*/, ThunkHeap, cdac_data<Module>::ThunkHeap)
CDAC_TYPE_FIELD(Module, /*pointer*/, DynamicMetadata, cdac_data<Module>::DynamicMetadata)
CDAC_TYPE_FIELD(Module, /*pointer*/, Path, cdac_data<Module>::Path)
CDAC_TYPE_FIELD(Module, /*pointer*/, FieldDefToDescMap, cdac_data<Module>::FieldDefToDescMap)
CDAC_TYPE_FIELD(Module, /*pointer*/, ManifestModuleReferencesMap, cdac_data<Module>::ManifestModuleReferencesMap)

View file

@ -1639,6 +1639,7 @@ struct cdac_data<Module>
static constexpr size_t LoaderAllocator = offsetof(Module, m_loaderAllocator);
static constexpr size_t ThunkHeap = offsetof(Module, m_pThunkHeap);
static constexpr size_t DynamicMetadata = offsetof(Module, m_pDynamicMetadata);
static constexpr size_t Path = offsetof(Module, m_path);
// Lookup map pointers
static constexpr size_t FieldDefToDescMap = offsetof(Module, m_FieldDefToDescMap);

View file

@ -117,6 +117,8 @@ internal interface ILoader : IContract
public virtual TargetPointer GetAssembly(ModuleHandle handle) => throw new NotImplementedException();
public virtual ModuleFlags GetFlags(ModuleHandle handle) => throw new NotImplementedException();
public virtual string GetPath(ModuleHandle handle) => throw new NotImplementedException();
public virtual TargetPointer GetLoaderAllocator(ModuleHandle handle) => throw new NotImplementedException();
public virtual TargetPointer GetThunkHeap(ModuleHandle handle) => throw new NotImplementedException();
@ -131,8 +133,6 @@ internal interface ILoader : IContract
public virtual TargetEcmaMetadata GetReadWriteMetadata(ModuleHandle handle) => throw new NotImplementedException();
public virtual ModuleLookupTables GetLookupTables(ModuleHandle handle) => throw new NotImplementedException();
public virtual string GetPath(ModuleHandle handle) => throw new NotImplementedException();
}
internal readonly struct Loader : ILoader

View file

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Microsoft.Diagnostics.DataContractReader.Contracts;
@ -35,6 +36,31 @@ internal readonly struct Loader_1 : ILoader
return (ModuleFlags)module.Flags;
}
string ILoader.GetPath(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
// TODO: [cdac] Add/use APIs on Target for reading strings in target endianness
TargetPointer addr = module.Path;
while (true)
{
// Read characters until we find the null terminator
char nameChar = _target.Read<char>(addr);
if (nameChar == 0)
break;
addr += sizeof(char);
}
int length = (int)(addr.Value - module.Path.Value);
if (length == 0)
return string.Empty;
Span<byte> span = stackalloc byte[length];
_target.ReadBuffer(module.Path, span);
return new string(MemoryMarshal.Cast<byte, char>(span));
}
TargetPointer ILoader.GetLoaderAllocator(ModuleHandle handle)
{
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);

View file

@ -23,6 +23,7 @@ internal sealed class Module : IData<Module>
LoaderAllocator = target.ReadPointer(address + (ulong)type.Fields[nameof(LoaderAllocator)].Offset);
ThunkHeap = target.ReadPointer(address + (ulong)type.Fields[nameof(ThunkHeap)].Offset);
DynamicMetadata = target.ReadPointer(address + (ulong)type.Fields[nameof(DynamicMetadata)].Offset);
Path = target.ReadPointer(address + (ulong)type.Fields[nameof(Path)].Offset);
FieldDefToDescMap = target.ReadPointer(address + (ulong)type.Fields[nameof(FieldDefToDescMap)].Offset);
ManifestModuleReferencesMap = target.ReadPointer(address + (ulong)type.Fields[nameof(ManifestModuleReferencesMap)].Offset);
@ -39,6 +40,7 @@ internal sealed class Module : IData<Module>
public TargetPointer LoaderAllocator { get; init; }
public TargetPointer ThunkHeap { get; init; }
public TargetPointer DynamicMetadata { get; init; }
public TargetPointer Path { get; init; }
public TargetPointer FieldDefToDescMap { get; init; }
public TargetPointer ManifestModuleReferencesMap { get; init; }

View file

@ -507,7 +507,35 @@ internal sealed partial class SOSDacImpl : ISOSDacInterface, ISOSDacInterface2,
public unsafe int GetOOMData(ulong oomAddr, void* data) => HResults.E_NOTIMPL;
public unsafe int GetOOMStaticData(void* data) => HResults.E_NOTIMPL;
public unsafe int GetPEFileBase(ulong addr, ulong* peBase) => HResults.E_NOTIMPL;
public unsafe int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded) => HResults.E_NOTIMPL;
public unsafe int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded)
{
try
{
Contracts.ILoader contract = _target.Contracts.Loader;
Contracts.ModuleHandle handle = contract.GetModuleHandle(addr);
string path = contract.GetPath(handle);
// Return not implemented for empty paths for non-reflection emit assemblies (for example, loaded from memory)
if (string.IsNullOrEmpty(path))
{
Contracts.ModuleFlags flags = contract.GetFlags(handle);
if (!flags.HasFlag(Contracts.ModuleFlags.ReflectionEmit))
{
return HResults.E_NOTIMPL;
}
}
CopyStringToTargetBuffer(fileName, count, pNeeded, path);
}
catch (System.Exception ex)
{
return ex.HResult;
}
return HResults.S_OK;
}
public unsafe int GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded) => HResults.E_NOTIMPL;
public unsafe int GetRCWData(ulong addr, void* data) => HResults.E_NOTIMPL;
public unsafe int GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL;