Skip to content
Merged
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
4 changes: 4 additions & 0 deletions src/coreclr/src/debug/daccess/daccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3290,6 +3290,10 @@ ClrDataAccess::QueryInterface(THIS_
{
ifaceRet = static_cast<ISOSDacInterface7*>(this);
}
else if (IsEqualIID(interfaceId, __uuidof(ISOSDacInterface8)))
{
ifaceRet = static_cast<ISOSDacInterface8*>(this);
}
else
{
*iface = NULL;
Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/src/debug/daccess/dacimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,8 @@ class ClrDataAccess
public ISOSDacInterface4,
public ISOSDacInterface5,
public ISOSDacInterface6,
public ISOSDacInterface7
public ISOSDacInterface7,
public ISOSDacInterface8
{
public:
ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget=0);
Expand Down Expand Up @@ -1195,6 +1196,14 @@ class ClrDataAccess
virtual HRESULT STDMETHODCALLTYPE GetProfilerModifiedILInformation(CLRDATA_ADDRESS methodDesc, struct DacpProfilerILData *pILData);
virtual HRESULT STDMETHODCALLTYPE GetMethodsWithProfilerModifiedIL(CLRDATA_ADDRESS mod, CLRDATA_ADDRESS *methodDescs, int cMethodDescs, int *pcMethodDescs);

// ISOSDacInterface8
virtual HRESULT STDMETHODCALLTYPE GetNumberGenerations(unsigned int *pGenerations);
virtual HRESULT STDMETHODCALLTYPE GetGenerationTable(unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded);
virtual HRESULT STDMETHODCALLTYPE GetFinalizationFillPointers(unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded);

virtual HRESULT STDMETHODCALLTYPE GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded);
virtual HRESULT STDMETHODCALLTYPE GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded);

//
// ClrDataAccess.
//
Expand Down
199 changes: 199 additions & 0 deletions src/coreclr/src/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4500,3 +4500,202 @@ HRESULT ClrDataAccess::GetMethodsWithProfilerModifiedIL(CLRDATA_ADDRESS mod, CLR

return hr;
}

HRESULT ClrDataAccess::GetNumberGenerations(unsigned int *pGenerations)
{
if (pGenerations == NULL)
{
return E_INVALIDARG;
}

SOSDacEnter();

*pGenerations = (unsigned int)(g_gcDacGlobals->total_generation_count);

SOSDacLeave();
return S_OK;
}

HRESULT ClrDataAccess::GetGenerationTable(unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsigned int *pNeeded [](start = 113, length = 21)

is the only purpose of this arg is for verification on the sos side?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's so you can request the number of generations and dynamically allocated an array of the right size

unsigned int count;
if (SUCCEEDED(pSos->GetGenerationTable(0, NULL, &count)
{
    DacpGenerationData *pGenerationData = new DacpGenerationData[count];
    pSos->GetGenerationTable(count, pGenerationData, NULL);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I didn't know it was going to be called this way. makes sense. thanks!

{
if (cGenerations > 0 && pGenerationData == NULL)
{
return E_INVALIDARG;
}

SOSDacEnter();

HRESULT hr = S_OK;
unsigned int numGenerationTableEntries = (unsigned int)(g_gcDacGlobals->total_generation_count);
if (pNeeded != NULL)
{
*pNeeded = numGenerationTableEntries;
}

if (cGenerations < numGenerationTableEntries)
{
hr = S_FALSE;
}
else
{
if (g_gcDacGlobals->generation_table.IsValid())
{
for (unsigned int i = 0; i < numGenerationTableEntries; i++)
{
DPTR(dac_generation) generation = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
pGenerationData[i].start_segment = (CLRDATA_ADDRESS) dac_cast<TADDR>(generation->start_segment);

pGenerationData[i].allocation_start = (CLRDATA_ADDRESS) generation->allocation_start;

DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context);
pGenerationData[i].allocContextPtr = (CLRDATA_ADDRESS)alloc_context->alloc_ptr;
pGenerationData[i].allocContextLimit = (CLRDATA_ADDRESS)alloc_context->alloc_limit;
}
}
else
{
hr = E_FAIL;
}
}

SOSDacLeave();
return hr;
}

HRESULT ClrDataAccess::GetFinalizationFillPointers(unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded)
Comment thread
davmason marked this conversation as resolved.
{
if (cFillPointers > 0 && pFinalizationFillPointers == NULL)
{
return E_INVALIDARG;
Comment thread
leculver marked this conversation as resolved.
}

SOSDacEnter();

HRESULT hr = S_OK;
unsigned int numFillPointers = (unsigned int)(g_gcDacGlobals->total_generation_count + dac_finalize_queue::ExtraSegCount);
if (pNeeded != NULL)
{
*pNeeded = numFillPointers;
}

if (cFillPointers < numFillPointers)
{
hr = S_FALSE;
}
else
{
if (g_gcDacGlobals->finalize_queue.IsValid())
Comment thread
davmason marked this conversation as resolved.
{
DPTR(dac_finalize_queue) fq = Dereference(g_gcDacGlobals->finalize_queue);
DPTR(uint8_t*) fillPointersTable = dac_cast<TADDR>(fq) + offsetof(dac_finalize_queue, m_FillPointers);
for (unsigned int i = 0; i < numFillPointers; i++)
{
pFinalizationFillPointers[i] = (CLRDATA_ADDRESS)*TableIndex(fillPointersTable, i, sizeof(uint8_t*));
}
}
else
{
hr = E_FAIL;
}
}

SOSDacLeave();
return hr;
}

HRESULT ClrDataAccess::GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded)
{
if (heapAddr == NULL || (cGenerations > 0 && pGenerationData == NULL))
{
return E_INVALIDARG;
}

SOSDacEnter();

HRESULT hr = S_OK;
#ifdef FEATURE_SVR_GC
unsigned int numGenerationTableEntries = (unsigned int)(g_gcDacGlobals->total_generation_count);
if (pNeeded != NULL)
{
*pNeeded = numGenerationTableEntries;
}

if (cGenerations < numGenerationTableEntries)
{
hr = S_FALSE;
}
else
{
DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(heapAddr));

if (pHeap.IsValid())
{
for (unsigned int i = 0; i < numGenerationTableEntries; ++i)
{
DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i);
pGenerationData[i].start_segment = (CLRDATA_ADDRESS)dac_cast<TADDR>(generation->start_segment);
pGenerationData[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start;
DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context);
pGenerationData[i].allocContextPtr = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_ptr;
pGenerationData[i].allocContextLimit = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_limit;
}
}
else
{
hr = E_FAIL;
}
}
#else
hr = E_NOTIMPL;
#endif

SOSDacLeave();
return hr;
}

HRESULT ClrDataAccess::GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded)
{
if (heapAddr == NULL || (cFillPointers > 0 && pFinalizationFillPointers == NULL))
{
return E_INVALIDARG;
}

SOSDacEnter();

HRESULT hr = S_OK;
#ifdef FEATURE_SVR_GC
unsigned int numFillPointers = (unsigned int)(g_gcDacGlobals->total_generation_count + dac_finalize_queue::ExtraSegCount);
if (pNeeded != NULL)
{
*pNeeded = numFillPointers;
}

if (cFillPointers < numFillPointers)
{
hr = S_FALSE;
}
else
{
DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(heapAddr));

if (pHeap.IsValid())
{
DPTR(dac_finalize_queue) fq = pHeap->finalize_queue;
DPTR(uint8_t*) pFillPointerArray= dac_cast<TADDR>(fq) + offsetof(dac_finalize_queue, m_FillPointers);
for (unsigned int i = 0; i < numFillPointers; ++i)
{
pFinalizationFillPointers[i] = (CLRDATA_ADDRESS) pFillPointerArray[i];
}
}
else
{
hr = E_FAIL;
}
}
#else
hr = E_NOTIMPL;
#endif

SOSDacLeave();
return hr;
}
1 change: 1 addition & 0 deletions src/coreclr/src/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38637,6 +38637,7 @@ void PopulateDacVars(GcDacVars *gcDacVars)
gcDacVars->build_variant = &g_build_variant;
gcDacVars->gc_structures_invalid_cnt = const_cast<int32_t*>(&GCScan::m_GcStructuresInvalidCnt);
gcDacVars->generation_size = sizeof(generation);
gcDacVars->total_generation_count = total_generation_count;
gcDacVars->max_gen = &g_max_generation;
#ifndef MULTIPLE_HEAPS
gcDacVars->mark_array = &gc_heap::mark_array;
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/src/gc/gcinterface.dac.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
#define MAX_GC_MECHANISM_BITS_COUNT 2
#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6

// The number of generations is hardcoded in to the dac APIS (DacpGcHeapDetails hard codes the size of its arrays)
// The number of generations is hardcoded into some older dac APIS (for example DacpGcHeapDetails hard codes the size of its arrays)
// This value cannot change and should not be used in new DAC APIs. New APIs can query GcDacVars.total_generation_count
// variable which is dynamically initialized at runtime


#define NUMBERGENERATIONS 4
#define INITIAL_HANDLE_TABLE_ARRAY_SIZE 10
#define HANDLE_MAX_INTERNAL_TYPES 12
Expand Down Expand Up @@ -184,6 +190,7 @@ struct GcDacVars {
uint8_t major_version_number;
uint8_t minor_version_number;
size_t generation_size;
size_t total_generation_count;
#ifdef DACCESS_COMPILE
#define GC_DAC_VAR(type, name) DPTR(type) name;
#define GC_DAC_PTR_VAR(type, name) DPTR(type*) name;
Expand Down
18 changes: 18 additions & 0 deletions src/coreclr/src/inc/sospriv.idl
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,21 @@ interface ISOSDacInterface7 : IUnknown
HRESULT GetProfilerModifiedILInformation(CLRDATA_ADDRESS methodDesc, struct DacpProfilerILData *pILData);
HRESULT GetMethodsWithProfilerModifiedIL(CLRDATA_ADDRESS mod, CLRDATA_ADDRESS *methodDescs, int cMethodDescs, int *pcMethodDescs);
};

[
object,
local,
uuid(c12f35a9-e55c-4520-a894-b3dc5165dfce)
]
interface ISOSDacInterface8 : IUnknown
Comment thread
davmason marked this conversation as resolved.
{
HRESULT GetNumberGenerations(unsigned int *pGenerations);

// WKS
HRESULT GetGenerationTable(unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded);
HRESULT GetFinalizationFillPointers(unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded);

// SVR
HRESULT GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded);
HRESULT GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded);
}
3 changes: 3 additions & 0 deletions src/coreclr/src/pal/prebuilt/idl/sospriv_i.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface6,0x11206399,0x4B66,0x4EDB,0x98,0xEA,0

MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface7,0xc1020dde,0xfe98,0x4536,0xa5,0x3b,0xf3,0x5a,0x74,0xc3,0x27,0xeb);


MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface8,0xc12f35a9,0xe55c,0x4520,0xa8,0x94,0xb3,0xdc,0x51,0x65,0xdf,0xce);

#undef MIDL_DEFINE_GUID

#ifdef __cplusplus
Expand Down
Loading