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:
parent
605ff6f648
commit
527ab8fe46
9 changed files with 109 additions and 7 deletions
|
@ -102,6 +102,7 @@ internal enum AvailableMetadataType
|
||||||
ModuleHandle GetModuleHandle(TargetPointer);
|
ModuleHandle GetModuleHandle(TargetPointer);
|
||||||
TargetPointer GetAssembly(ModuleHandle handle);
|
TargetPointer GetAssembly(ModuleHandle handle);
|
||||||
ModuleFlags GetFlags(ModuleHandle handle);
|
ModuleFlags GetFlags(ModuleHandle handle);
|
||||||
|
string GetPath(ModuleHandle handle);
|
||||||
TargetPointer GetLoaderAllocator(ModuleHandle handle);
|
TargetPointer GetLoaderAllocator(ModuleHandle handle);
|
||||||
TargetPointer GetThunkHeap(ModuleHandle handle);
|
TargetPointer GetThunkHeap(ModuleHandle handle);
|
||||||
TargetPointer GetILBase(ModuleHandle handle);
|
TargetPointer GetILBase(ModuleHandle handle);
|
||||||
|
@ -122,6 +123,7 @@ Data descriptors used:
|
||||||
| `Module` | `Flags` | Assembly of the Module |
|
| `Module` | `Flags` | Assembly of the Module |
|
||||||
| `Module` | `LoaderAllocator` | LoaderAllocator of the Module |
|
| `Module` | `LoaderAllocator` | LoaderAllocator of the Module |
|
||||||
| `Module` | `ThunkHeap` | Pointer to the thunk heap |
|
| `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` | `DynamicMetadata` | Pointer to saved metadata for reflection emit modules |
|
||||||
| `Module` | `FieldDefToDescMap` | Mapping table |
|
| `Module` | `FieldDefToDescMap` | Mapping table |
|
||||||
| `Module` | `ManifestModuleReferencesMap` | Mapping table |
|
| `Module` | `ManifestModuleReferencesMap` | Mapping table |
|
||||||
|
@ -149,6 +151,13 @@ ModuleFlags GetFlags(ModuleHandle handle)
|
||||||
return target.Read<uint>(handle.Address + /* Module::Flags offset */);
|
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)
|
TargetPointer GetLoaderAllocator(ModuleHandle handle)
|
||||||
{
|
{
|
||||||
return target.ReadPointer(handle.Address + /* Module::LoaderAllocator offset */);
|
return target.ReadPointer(handle.Address + /* Module::LoaderAllocator offset */);
|
||||||
|
|
|
@ -1243,6 +1243,7 @@ public:
|
||||||
HRESULT GetObjectDataImpl(CLRDATA_ADDRESS addr, struct DacpObjectData *objectData);
|
HRESULT GetObjectDataImpl(CLRDATA_ADDRESS addr, struct DacpObjectData *objectData);
|
||||||
HRESULT GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
|
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 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 GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData);
|
||||||
HRESULT GetMethodDescDataImpl(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData);
|
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);
|
HRESULT GetMethodDescNameImpl(CLRDATA_ADDRESS methodDesc, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded);
|
||||||
|
|
|
@ -2542,6 +2542,41 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
SOSDacEnter();
|
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));
|
PTR_Module pModule = PTR_Module(TO_TADDR(moduleAddr));
|
||||||
PEAssembly* pPEAssembly = pModule->GetPEAssembly();
|
PEAssembly* pPEAssembly = pModule->GetPEAssembly();
|
||||||
|
|
||||||
|
@ -2549,11 +2584,11 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In
|
||||||
if (!pPEAssembly->GetPath().IsEmpty())
|
if (!pPEAssembly->GetPath().IsEmpty())
|
||||||
{
|
{
|
||||||
if (!pPEAssembly->GetPath().DacGetUnicode(count, fileName, pNeeded))
|
if (!pPEAssembly->GetPath().DacGetUnicode(count, fileName, pNeeded))
|
||||||
hr = E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
else if (!pPEAssembly->IsReflectionEmit())
|
else if (!pPEAssembly->IsReflectionEmit())
|
||||||
{
|
{
|
||||||
hr = E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2564,8 +2599,7 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In
|
||||||
*pNeeded = 1;
|
*pNeeded = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOSDacLeave();
|
return S_OK;
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
@ -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*/, LoaderAllocator, cdac_data<Module>::LoaderAllocator)
|
||||||
CDAC_TYPE_FIELD(Module, /*pointer*/, ThunkHeap, cdac_data<Module>::ThunkHeap)
|
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*/, 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*/, FieldDefToDescMap, cdac_data<Module>::FieldDefToDescMap)
|
||||||
CDAC_TYPE_FIELD(Module, /*pointer*/, ManifestModuleReferencesMap, cdac_data<Module>::ManifestModuleReferencesMap)
|
CDAC_TYPE_FIELD(Module, /*pointer*/, ManifestModuleReferencesMap, cdac_data<Module>::ManifestModuleReferencesMap)
|
||||||
|
|
|
@ -1639,6 +1639,7 @@ struct cdac_data<Module>
|
||||||
static constexpr size_t LoaderAllocator = offsetof(Module, m_loaderAllocator);
|
static constexpr size_t LoaderAllocator = offsetof(Module, m_loaderAllocator);
|
||||||
static constexpr size_t ThunkHeap = offsetof(Module, m_pThunkHeap);
|
static constexpr size_t ThunkHeap = offsetof(Module, m_pThunkHeap);
|
||||||
static constexpr size_t DynamicMetadata = offsetof(Module, m_pDynamicMetadata);
|
static constexpr size_t DynamicMetadata = offsetof(Module, m_pDynamicMetadata);
|
||||||
|
static constexpr size_t Path = offsetof(Module, m_path);
|
||||||
|
|
||||||
// Lookup map pointers
|
// Lookup map pointers
|
||||||
static constexpr size_t FieldDefToDescMap = offsetof(Module, m_FieldDefToDescMap);
|
static constexpr size_t FieldDefToDescMap = offsetof(Module, m_FieldDefToDescMap);
|
||||||
|
|
|
@ -117,6 +117,8 @@ internal interface ILoader : IContract
|
||||||
|
|
||||||
public virtual TargetPointer GetAssembly(ModuleHandle handle) => throw new NotImplementedException();
|
public virtual TargetPointer GetAssembly(ModuleHandle handle) => throw new NotImplementedException();
|
||||||
public virtual ModuleFlags GetFlags(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 GetLoaderAllocator(ModuleHandle handle) => throw new NotImplementedException();
|
||||||
public virtual TargetPointer GetThunkHeap(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 TargetEcmaMetadata GetReadWriteMetadata(ModuleHandle handle) => throw new NotImplementedException();
|
||||||
|
|
||||||
public virtual ModuleLookupTables GetLookupTables(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
|
internal readonly struct Loader : ILoader
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Microsoft.Diagnostics.DataContractReader.Contracts;
|
namespace Microsoft.Diagnostics.DataContractReader.Contracts;
|
||||||
|
|
||||||
|
@ -35,6 +36,31 @@ internal readonly struct Loader_1 : ILoader
|
||||||
return (ModuleFlags)module.Flags;
|
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)
|
TargetPointer ILoader.GetLoaderAllocator(ModuleHandle handle)
|
||||||
{
|
{
|
||||||
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
|
Data.Module module = _target.ProcessedData.GetOrAdd<Data.Module>(handle.Address);
|
||||||
|
|
|
@ -23,6 +23,7 @@ internal sealed class Module : IData<Module>
|
||||||
LoaderAllocator = target.ReadPointer(address + (ulong)type.Fields[nameof(LoaderAllocator)].Offset);
|
LoaderAllocator = target.ReadPointer(address + (ulong)type.Fields[nameof(LoaderAllocator)].Offset);
|
||||||
ThunkHeap = target.ReadPointer(address + (ulong)type.Fields[nameof(ThunkHeap)].Offset);
|
ThunkHeap = target.ReadPointer(address + (ulong)type.Fields[nameof(ThunkHeap)].Offset);
|
||||||
DynamicMetadata = target.ReadPointer(address + (ulong)type.Fields[nameof(DynamicMetadata)].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);
|
FieldDefToDescMap = target.ReadPointer(address + (ulong)type.Fields[nameof(FieldDefToDescMap)].Offset);
|
||||||
ManifestModuleReferencesMap = target.ReadPointer(address + (ulong)type.Fields[nameof(ManifestModuleReferencesMap)].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 LoaderAllocator { get; init; }
|
||||||
public TargetPointer ThunkHeap { get; init; }
|
public TargetPointer ThunkHeap { get; init; }
|
||||||
public TargetPointer DynamicMetadata { get; init; }
|
public TargetPointer DynamicMetadata { get; init; }
|
||||||
|
public TargetPointer Path { get; init; }
|
||||||
|
|
||||||
public TargetPointer FieldDefToDescMap { get; init; }
|
public TargetPointer FieldDefToDescMap { get; init; }
|
||||||
public TargetPointer ManifestModuleReferencesMap { get; init; }
|
public TargetPointer ManifestModuleReferencesMap { get; init; }
|
||||||
|
|
|
@ -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 GetOOMData(ulong oomAddr, void* data) => HResults.E_NOTIMPL;
|
||||||
public unsafe int GetOOMStaticData(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 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 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 GetRCWData(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||||
public unsafe int GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL;
|
public unsafe int GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue