Repository: dotnet/runtime
File: src/coreclr/debug/daccess/enummem.cpp (C++)

Code before:

        runtimeExport = pe.GetExport(DACCESS_TABLE_SYMBOL);
        if (runtimeExport != NULL)
        {
            ReportMem(dac_cast<TADDR>(runtimeExport), sizeof(DacGlobals), true);
        }
    }
    else
    {
        // We always expect (attach state, metrics and such on windows, and dac table on mac and linux).
        return E_UNEXPECTED;
    }

    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
// that needs to be present in all minidumps.
// Hardcodes number of subdescriptors and does not recursively enumerate them.
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HRESULT ClrDataAccess::EnumMemDataDescriptors(CLRDataEnumMemoryFlags flags)
{
    SUPPORTS_DAC;

    HRESULT status = S_OK;

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

    PTR_ContractDescriptor pContractDescriptor = dac_cast<PTR_ContractDescriptor>((TADDR)contractDescriptorAddr);
    // Enumerate the ContractDescriptor structure
    ReportMem(dac_cast<TADDR>(pContractDescriptor), sizeof(ContractDescriptor));
    // Report the pointer data array
    ReportMem((TADDR)pContractDescriptor->pointer_data, pContractDescriptor->pointer_data_count * sizeof(void*));
    // Report the JSON blob
    ReportMem((TADDR)pContractDescriptor->descriptor, pContractDescriptor->descriptor_size);

    // 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, but given it will eventually move to the cDAC, this is good enough for now.
    int cSubDescriptors = 1;

Review comment (suggestion):
The `flags` parameter is declared but never used in the function body. Consider removing it if not needed, or use `UNREFERENCED_PARAMETER(flags);` if it's required by the function signature for consistency with other enum methods.

Code after:

        runtimeExport = pe.GetExport(DACCESS_TABLE_SYMBOL);
        if (runtimeExport != NULL)
        {
            ReportMem(dac_cast<TADDR>(runtimeExport), sizeof(DacGlobals), true);
        }
    }
    else
    {
        // We always expect (attach state, metrics and such on windows, and dac table on mac and linux).
        return E_UNEXPECTED;
    }

    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))