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
43 changes: 21 additions & 22 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2681,7 +2681,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetExactTypeHandle(DebuggerIPCE_E

// Retrieve the generic type params for a given MethodDesc. This function is specifically
// for stackwalking because it requires the generic type token on the stack.
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetMethodDescParams(VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, OUT TypeParamsList * pGenericTypeParams)
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::EnumerateMethodDescParams(VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, FP_TYPEPARAM_CALLBACK fpCallback, CALLBACK_DATA pUserData)
{
DD_ENTER_MAY_THROW;

Expand All @@ -2694,7 +2694,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetMethodDescParams(VMPTR_MethodD
ThrowHR(E_INVALIDARG);
}

_ASSERTE((pcGenericClassTypeParams != NULL) && (pGenericTypeParams != NULL));
_ASSERTE((pcGenericClassTypeParams != NULL) && (fpCallback != NULL));

MethodDesc * pMD = vmMethodDesc.GetDacPtr();

Expand Down Expand Up @@ -2739,9 +2739,6 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetMethodDescParams(VMPTR_MethodD
_ASSERTE((classInst.IsEmpty()) == (cGenericClassTypeParams == 0));
_ASSERTE((methodInst.IsEmpty()) == (cGenericMethodTypeParams == 0));

// allocate memory for the return array
pGenericTypeParams->Alloc(cTotalGenericTypeParams);

for (UINT32 i = 0; i < cTotalGenericTypeParams; i++)
{
// Retrieve the current type parameter depending on the index.
Expand All @@ -2755,24 +2752,28 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetMethodDescParams(VMPTR_MethodD
thCurrent = methodInst[i - cGenericClassTypeParams];
}

DebuggerIPCE_ExpandedTypeData entry;

// There is the possibility that we'll get this far with a dump and not fail, but still
// not be able to get full info for a particular param.
EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
{
// Fill in the struct using the TypeHandle of the current type parameter if we can.
IfFailThrow(TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
(CORDB_ADDRESS)thCurrent.AsTAddr(),
&((*pGenericTypeParams)[i])));
&entry));
}
EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
{
// On failure for a particular type, default it back to System.__Canon.
TypeHandle thCanon = TypeHandle(g_pCanonMethodTableClass);
IfFailThrow(TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
(CORDB_ADDRESS)thCanon.AsTAddr(),
&((*pGenericTypeParams)[i])));
&entry));
}
EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER

fpCallback(&entry, pUserData);
}
}
EX_CATCH_HRESULT(hr);
Expand Down Expand Up @@ -3169,37 +3170,35 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetCollectibleTypeStaticAddress(V
return hr;
}

// DacDbi API: GetTypeHandleParams
// DacDbi API: EnumerateTypeHandleParams
// - gets the necessary data for a type handle, i.e. its type parameters, e.g. "String" and "List<int>" from the type handle
// for "Dict<String,List<int>>", and sends it back to the right side.
// - pParams is allocated and initialized by this function
// for "Dict<String,List<int>>", and sends it back to the right side via the callback.
// - This should not fail except for OOM
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetTypeHandleParams(VMPTR_TypeHandle vmTypeHandle, OUT TypeParamsList * pParams)
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::EnumerateTypeHandleParams(VMPTR_TypeHandle vmTypeHandle, FP_TYPEPARAM_CALLBACK fpCallback, CALLBACK_DATA pUserData)
{
DD_ENTER_MAY_THROW

HRESULT hr = S_OK;
EX_TRY
{
_ASSERTE(fpCallback != NULL);

TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr());
LOG((LF_CORDB, LL_INFO10000, "D::GTHP: getting type parameters for 0x%08x 0x%0x8.\n",
vmAppDomain.GetDacPtr(), typeHandle.AsPtr()));

LOG((LF_CORDB, LL_INFO10000, "D::ETHP: enumerating type parameters for 0x%p.\n", typeHandle.AsPtr()));

// Find the class given its type handle.
_ASSERTE(pParams->IsEmpty());
pParams->Alloc(typeHandle.GetNumGenericArgs());
unsigned int count = typeHandle.GetNumGenericArgs();
Instantiation inst = typeHandle.GetInstantiation();

// collect type information for each type parameter
for (unsigned int i = 0; i < pParams->Count(); ++i)
for (unsigned int i = 0; i < count; ++i)
{
DebuggerIPCE_ExpandedTypeData entry;
IfFailThrow(TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
(CORDB_ADDRESS)typeHandle.GetInstantiation()[i].AsTAddr(),
&((*pParams)[i])));
(CORDB_ADDRESS)inst[i].AsTAddr(),
&entry));
fpCallback(&entry, pUserData);
}

LOG((LF_CORDB, LL_INFO10000, "D::GTHP: sending result"));
LOG((LF_CORDB, LL_INFO10000, "D::ETHP: sending result"));
}
EX_CATCH_HRESULT(hr);
return hr;
Expand Down
12 changes: 5 additions & 7 deletions src/coreclr/debug/daccess/dacdbiimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ class DacDbiInterfaceImpl :

// Retrieve the generic type params for a given MethodDesc. This function is specifically
// for stackwalking because it requires the generic type token on the stack.
HRESULT STDMETHODCALLTYPE GetMethodDescParams(VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, OUT TypeParamsList * pGenericTypeParams);
HRESULT STDMETHODCALLTYPE EnumerateMethodDescParams(VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, FP_TYPEPARAM_CALLBACK fpCallback, CALLBACK_DATA pUserData);

// Get the target field address of a context or thread local static.
HRESULT STDMETHODCALLTYPE GetThreadStaticAddress(VMPTR_FieldDesc vmField, VMPTR_Thread vmRuntimeThread, OUT CORDB_ADDRESS * pRetVal);
Expand All @@ -273,12 +273,10 @@ class DacDbiInterfaceImpl :
// Get information about a field added with Edit And Continue.
HRESULT STDMETHODCALLTYPE GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, OUT FieldData * pFieldData, OUT BOOL * pfStatic);

// GetTypeHandleParams gets the necessary data for a type handle, i.e. its
// type parameters, e.g. "String" and "List<int>" from the type handle
// for "Dict<String,List<int>>", and sends it back to the right side.
// This should not fail except for OOM

HRESULT STDMETHODCALLTYPE GetTypeHandleParams(VMPTR_TypeHandle vmTypeHandle, OUT TypeParamsList * pParams);
// EnumerateTypeHandleParams gets the necessary data for a type handle, i.e. its type
// parameters, e.g. "String" and "List<int>" from the type handle for
// "Dict<String,List<int>>".
HRESULT STDMETHODCALLTYPE EnumerateTypeHandleParams(VMPTR_TypeHandle vmTypeHandle, FP_TYPEPARAM_CALLBACK fpCallback, CALLBACK_DATA pUserData);

// DacDbi API: GetSimpleType
// gets the metadata token and assembly corresponding to a simple type
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/debug/di/rspriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ struct CallbackAccumulator
{
return reinterpret_cast<CallbackAccumulator*>(pUserData);
}

// Adapter for FP_*_CALLBACK signatures that deliver an item by pointer
// (e.g. FP_TYPEPARAM_CALLBACK). Pass as the callback with &acc as pUserData:
// pDAC->EnumX(args, &CallbackAccumulator<T>::PushCallback, &acc);
static void PushCallback(T * pItem, CALLBACK_DATA pUserData)
{
From(pUserData)->Push(*pItem);
}
};


Expand Down
24 changes: 14 additions & 10 deletions src/coreclr/debug/di/rsthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7658,14 +7658,16 @@ void CordbJITILFrame::LoadGenericArgs()
IDacDbiInterface * pDAC = GetProcess()->GetDAC();

UINT32 cGenericClassTypeParams = 0;
DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> rgGenericTypeParams;
CallbackAccumulator<DebuggerIPCE_ExpandedTypeData> acc;

IfFailThrow(pDAC->GetMethodDescParams(m_nativeFrame->GetNativeCode()->GetVMNativeCodeMethodDescToken(),
IfFailThrow(pDAC->EnumerateMethodDescParams(m_nativeFrame->GetNativeCode()->GetVMNativeCodeMethodDescToken(),
m_frameParamsToken,
&cGenericClassTypeParams,
&rgGenericTypeParams));
&CallbackAccumulator<DebuggerIPCE_ExpandedTypeData>::PushCallback,
&acc));
IfFailThrow(acc.hrError);

UINT32 cTotalGenericTypeParams = rgGenericTypeParams.Count();
UINT32 cTotalGenericTypeParams = (UINT32)acc.items.Size();

NewInterfaceArrayHolder<CordbType> ppGenericArgs(
new CordbType *[cTotalGenericTypeParams](),
Expand All @@ -7676,7 +7678,7 @@ void CordbJITILFrame::LoadGenericArgs()
// creates a CordbType object for the generic argument
CordbType *newType;
IfFailThrow(CordbType::TypeDataToType(GetCurrentAppDomain(),
&(rgGenericTypeParams[i]),
&(acc.items[i]),
&newType));

// We add a ref as the instantiation will be stored away in the
Expand Down Expand Up @@ -11520,7 +11522,7 @@ void CordbAsyncFrame::LoadGenericArgs()
IDacDbiInterface * pDAC = GetProcess()->GetDAC();

UINT32 cGenericClassTypeParams = 0;
DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> rgGenericTypeParams;
CallbackAccumulator<DebuggerIPCE_ExpandedTypeData> acc;

UINT32 genericArgIndex;
HRESULT result = pDAC->GetGenericArgTokenIndex(
Expand Down Expand Up @@ -11552,12 +11554,14 @@ void CordbAsyncFrame::LoadGenericArgs()
genericTypeParam = resolvedToken;
}

IfFailThrow(pDAC->GetMethodDescParams(m_vmMethodDesc,
IfFailThrow(pDAC->EnumerateMethodDescParams(m_vmMethodDesc,
genericTypeParam,
&cGenericClassTypeParams,
&rgGenericTypeParams));
&CallbackAccumulator<DebuggerIPCE_ExpandedTypeData>::PushCallback,
&acc));
IfFailThrow(acc.hrError);

UINT32 cTotalGenericTypeParams = rgGenericTypeParams.Count();
UINT32 cTotalGenericTypeParams = (UINT32)acc.items.Size();

NewInterfaceArrayHolder<CordbType> ppGenericArgs(
new CordbType *[cTotalGenericTypeParams](),
Expand All @@ -11568,7 +11572,7 @@ void CordbAsyncFrame::LoadGenericArgs()
// creates a CordbType object for the generic argument
CordbType *newType;
IfFailThrow(CordbType::TypeDataToType(m_pAppDomain,
&(rgGenericTypeParams[i]),
&(acc.items[i]),
&newType));

// We add a ref as the instantiation will be stored away in the
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/debug/di/rstype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,10 @@ HRESULT CordbType::InstantiateFromTypeHandle(CordbAppDomain * pAppDomain,
TypeParamsList params;
{
RSLockHolder lockHolder(pProcess->GetProcessLock());
IfFailThrow(pProcess->GetDAC()->GetTypeHandleParams(vmTypeHandle, &params));
CallbackAccumulator<DebuggerIPCE_ExpandedTypeData> acc;
IfFailThrow(pProcess->GetDAC()->EnumerateTypeHandleParams(vmTypeHandle, &CallbackAccumulator<DebuggerIPCE_ExpandedTypeData>::PushCallback, &acc));
IfFailThrow(acc.hrError);
params.Init(acc.items.Ptr(), (int)acc.items.Size());
}

// convert the parameter type information to a list of CordbTypeInstances (one for each parameter)
Expand Down
30 changes: 16 additions & 14 deletions src/coreclr/debug/inc/dacdbiinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,11 @@ IDacDbiInterface : public IUnknown
ArgInfoList * pArgInfo,
VMPTR_TypeHandle * pVmTypeHandle) = 0;

// Callback invoked for each type parameter enumerated by EnumerateMethodDescParams or
// EnumerateTypeHandleParams. The callback must not throw. Implementations typically push
// the value into an accumulator stashed in pUserData.
typedef void (*FP_TYPEPARAM_CALLBACK)(DebuggerIPCE_ExpandedTypeData * pTypeData, CALLBACK_DATA pUserData);

//
// Retrieve the generic type params for a given MethodDesc. This function is specifically
// for stackwalking because it requires the generic type token on the stack.
Expand All @@ -1610,19 +1615,20 @@ IDacDbiInterface : public IUnknown
// vmMethodDesc - the method in question
// genericsToken - the generic type token in the stack frame owned by the method
// pcGenericClassTypeParams - [out]
// pGenericTypeParams - [out]
// fpCallback - [in]
// pUserData - [in]
//
// pcGenericClassTypeParams - out parameter; returns the number of type parameters for the class
// containing the method in question; must not be NULL
// pGenericTypeParams - out parameter; returns an array of type parameters and
// the count of the total number of type parameters; must not be NULL
// fpCallback - callback invoked once per type parameter, in order: class type parameters first
// then method type parameters; must not be NULL
// pUserData - opaque user data passed through to the callback
//
// Notes:
// The memory for the array is allocated by this function on the Dbi heap.
// The caller is responsible for releasing it.
// The callback must not throw.
//

virtual HRESULT STDMETHODCALLTYPE GetMethodDescParams(VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, OUT TypeParamsList * pGenericTypeParams) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumerateMethodDescParams(VMPTR_MethodDesc vmMethodDesc, GENERICS_TYPE_TOKEN genericsToken, OUT UINT32 * pcGenericClassTypeParams, FP_TYPEPARAM_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0;

Comment thread
rcj1 marked this conversation as resolved.
// Get the target field address of a thread local static.
// Arguments:
Expand Down Expand Up @@ -1669,20 +1675,16 @@ IDacDbiInterface : public IUnknown
virtual HRESULT STDMETHODCALLTYPE GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo, OUT FieldData * pFieldData, OUT BOOL * pfStatic) = 0;


// GetTypeHandleParams gets the necessary data for a type handle, i.e. its
// EnumerateTypeHandleParams gets the necessary data for a type handle, i.e. its
// type parameters, e.g. "String" and "List<int>" from the type handle
// for "Dict<String,List<int>>", and sends it back to the right side.
// Arguments:
// input: vmTypeHandle - type handle for the type
// output: pParams - list of instances of DebuggerIPCE_ExpandedTypeData,
// one for each type parameter. These will be used on the
// RS to build up an instantiation which will allow
// building an instance of CordbType for the top-level
// type. The memory for this list is allocated on the dbi
// heap in this function.
// fpCallback - callback invoked once per type parameter (must not be NULL)
// pUserData - opaque user data passed through to the callback
// This will not fail except for OOM

virtual HRESULT STDMETHODCALLTYPE GetTypeHandleParams(VMPTR_TypeHandle vmTypeHandle, OUT TypeParamsList * pParams) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumerateTypeHandleParams(VMPTR_TypeHandle vmTypeHandle, FP_TYPEPARAM_CALLBACK fpCallback, CALLBACK_DATA pUserData) = 0;

// GetSimpleType
// gets the metadata token and assembly corresponding to a simple type
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,7 @@ CDAC_GLOBAL(FieldOffsetBigRVA, T_UINT32, FIELD_OFFSET_BIG_RVA)
CDAC_GLOBAL(FieldOffsetDynamicRVA, T_UINT32, FIELD_OFFSET_DYNAMIC_RVA)
CDAC_GLOBAL_POINTER(ClrNotificationArguments, &::g_clrNotificationArguments)
CDAC_GLOBAL_POINTER(ArrayBoundsZero, cdac_data<ArrayBase>::ArrayBoundsZero)
CDAC_GLOBAL_POINTER(CanonMethodTable, &::g_pCanonMethodTableClass)
CDAC_GLOBAL_POINTER(ContinuationMethodTable, &::g_pContinuationClassIfSubTypeCreated)
CDAC_GLOBAL_POINTER(ContinuationSingletonEEClass, &::g_singletonContinuationEEClass)
CDAC_GLOBAL_POINTER(ExceptionMethodTable, &::g_pExceptionClass)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ public interface IRuntimeTypeSystem : IContract


ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle) => throw new NotImplementedException();

public bool IsClassInited(TypeHandle typeHandle) => throw new NotImplementedException();
public bool IsInitError(TypeHandle typeHandle) => throw new NotImplementedException();
bool IsGenericTypeDefinition(TypeHandle typeHandle) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static class Globals
public const string RecommendedReaderVersion = nameof(RecommendedReaderVersion);

public const string ContinuationMethodTable = nameof(ContinuationMethodTable);
public const string CanonMethodTable = nameof(CanonMethodTable);
public const string ContinuationSingletonEEClass = nameof(ContinuationSingletonEEClass);
Comment thread
rcj1 marked this conversation as resolved.
public const string ExceptionMethodTable = nameof(ExceptionMethodTable);
public const string FreeObjectMethodTable = nameof(FreeObjectMethodTable);
Comment thread
rcj1 marked this conversation as resolved.
Expand Down
Loading
Loading