Skip to content
Open
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
1 change: 1 addition & 0 deletions src/coreclr/debug/daccess/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CLR_DIR}/debug/ee)
include_directories(${CLR_DIR}/gcdump)
include_directories(${CLR_DIR}/interop/inc)
include_directories(${CLR_DIR}/debug/datadescriptor-shared/inc)

if(CLR_CMAKE_HOST_UNIX)
include_directories(${GENERATED_INCLUDE_DIR})
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/debug/daccess/dacimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,9 @@ class ClrDataAccess
HRESULT EnumMemDumpAppDomainInfo(CLRDataEnumMemoryFlags flags);
HRESULT EnumMemDumpAllThreadsStack(CLRDataEnumMemoryFlags flags);
HRESULT EnumMemCLRMainModuleInfo();
HRESULT EnumMemDataDescriptors(CLRDataEnumMemoryFlags flags);

void EnumDataDescriptorHelper(TADDR dataDescriptorAddr);

bool ReportMem(TADDR addr, TSIZE_T size, bool fExpectSuccess = true);
bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer);
Expand Down
77 changes: 77 additions & 0 deletions src/coreclr/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#endif // FEATURE_COMWRAPPERS

#include "cdacplatformmetadata.hpp"
#include "contract-descriptor.h"

extern HRESULT GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress);

Expand Down Expand Up @@ -1631,6 +1632,79 @@ HRESULT ClrDataAccess::EnumMemCLRMainModuleInfo()
return status;
}

typedef DPTR(ContractDescriptor) PTR_ContractDescriptor;
extern "C" bool TryGetSymbol(ICorDebugDataTarget* dataTarget, uint64_t baseAddress, const char* symbolName, uint64_t* symbolAddress);

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Reports datadescriptor data for the cDAC.
// Hardcodes number of subdescriptors and does not recursively enumerate them.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT ClrDataAccess::EnumMemDataDescriptors(CLRDataEnumMemoryFlags flags)
{
SUPPORTS_DAC;

uint64_t contractDescriptorAddr = 0;
if (!TryGetSymbol(m_pTarget, m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr))
return E_FAIL;

// Save the main descriptor
EnumDataDescriptorHelper((TADDR)contractDescriptorAddr);

// Assume that subdescriptors will be the n last pointers in the pointer_data array
// Must be updated if further subdescriptors are added
// This could be improved by iterating all of the pointer data recursively and identifying subdescriptors by
// the magic field in ContractDescriptor. Given the low number of subdescriptors, this is not necessary right now.
int cSubDescriptors = 1;
PTR_ContractDescriptor pContractDescriptor = dac_cast<PTR_ContractDescriptor>((TADDR)contractDescriptorAddr);
for (int i = 0; i < cSubDescriptors; i++)
{
int subDescriptorIndex = (pContractDescriptor->pointer_data_count - 1) - i;

TADDR pSubDescriptorAddr;
ULONG32 bytesRead;
if (FAILED(m_pTarget->ReadVirtual(
(TADDR)pContractDescriptor->pointer_data + subDescriptorIndex * sizeof(void*),
(PBYTE)&pSubDescriptorAddr, sizeof(TADDR), &bytesRead))
|| bytesRead != sizeof(TADDR)
|| pSubDescriptorAddr == 0)
{
continue;
}

TADDR subDescriptorAddr;
if (FAILED(m_pTarget->ReadVirtual(
pSubDescriptorAddr,
(PBYTE)&subDescriptorAddr, sizeof(TADDR), &bytesRead))
|| bytesRead != sizeof(TADDR)
|| subDescriptorAddr == 0)
{
continue;
}

// Save the subdescriptor
EnumDataDescriptorHelper(subDescriptorAddr);
}

return S_OK;
}

void ClrDataAccess::EnumDataDescriptorHelper(TADDR dataDescriptorAddr)
{
PTR_ContractDescriptor pDataDescriptor = dac_cast<PTR_ContractDescriptor>(dataDescriptorAddr);

EX_TRY
{
// Enumerate the ContractDescriptor structure
ReportMem(dac_cast<TADDR>(pDataDescriptor), sizeof(ContractDescriptor));
// Report the pointer data array
ReportMem((TADDR)pDataDescriptor->pointer_data, pDataDescriptor->pointer_data_count * sizeof(void*));
// Report the JSON blob
ReportMem((TADDR)pDataDescriptor->descriptor, pDataDescriptor->descriptor_size);
}
EX_CATCH_RETHROW_ONLY_COR_E_OPERATIONCANCELLED
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
Expand Down Expand Up @@ -2059,6 +2133,9 @@ ClrDataAccess::EnumMemoryRegions(IN ICLRDataEnumMemoryRegionsCallback* callback,
}
}
#endif

EnumMemDataDescriptors(flags);

Flush();
}
EX_CATCH
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,12 @@ CDAC_GLOBAL_POINTER(MethodDescSizeTable, &MethodDesc::s_ClassificationSizeTable)
CDAC_GLOBAL_POINTER(GCLowestAddress, &g_lowest_address)
CDAC_GLOBAL_POINTER(GCHighestAddress, &g_highest_address)


// It is important for the subdescriptor pointers to be the last pointers in the global structure.
// EnumMemDataDescriptors in enummem.cpp hardcodes the number of subdescriptors and utilizes
// this order to find and enumerate the subdescriptors.
//
// When adding a new subdescriptor, EnumMemDescriptors must be updated appropriately.
CDAC_GLOBAL_SUB_DESCRIPTOR(GC, &(g_gc_dac_vars.gc_descriptor))

CDAC_GLOBAL_CONTRACT(CodeVersions, 1)
Expand Down
Loading