diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 284d3fd1172842..b0461e50e7daa4 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -2315,6 +2315,7 @@ void DacDbiInterfaceImpl::GetClassTypeInfo(TypeHandle typeH DebuggerIPCE_ExpandedTypeData * pTypeInfo, AppDomain * pAppDomain) { + typeHandle = typeHandle.UpCastTypeIfNeeded(); Module * pModule = typeHandle.GetModule(); if (typeHandle.HasInstantiation()) // the type handle represents a generic instantiation @@ -2402,9 +2403,10 @@ void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_VALUETYPE: { - Module * pModule = typeHandle.GetModule(); + typeHandle = typeHandle.UpCastTypeIfNeeded(); - if (typeHandle.HasInstantiation()) // only set if instantiated + Module * pModule = typeHandle.GetModule(); + if (typeHandle.HasInstantiation()) // only set if instantiated { pTypeInfo->vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); } diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 546ef251ea71f1..eb5bc42d206f8a 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -11657,6 +11657,7 @@ void Debugger::TypeHandleToBasicTypeInfo(AppDomain *pAppDomain, TypeHandle th, D case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_VALUETYPE: { + th = th.UpCastTypeIfNeeded(); res->vmTypeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr(); // only set if instantiated res->metadataToken = th.GetCl(); @@ -11739,6 +11740,7 @@ void Debugger::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed boxed, case ELEMENT_TYPE_CLASS: { treatAllValuesAsBoxed: + th = th.UpCastTypeIfNeeded(); res->ClassTypeData.typeHandle = th.HasInstantiation() ? WrapTypeHandle(th) : VMPTR_TypeHandle::NullPtr(); // only set if instantiated res->ClassTypeData.metadataToken = th.GetCl(); DebuggerModule * pModule = LookupOrCreateModule(th.GetModule()); diff --git a/src/coreclr/vm/typehandle.h b/src/coreclr/vm/typehandle.h index 92af9c513a7641..9c5e5f8b424625 100644 --- a/src/coreclr/vm/typehandle.h +++ b/src/coreclr/vm/typehandle.h @@ -386,6 +386,7 @@ class TypeHandle // And some types (like ByRef or generic type parameters) have no // method table and this function returns NULL for them. inline PTR_MethodTable GetMethodTable() const; + inline TypeHandle UpCastTypeIfNeeded() const; // Returns the type which should be used for visibility checking. inline MethodTable* GetMethodTableOfRootTypeParam() const; diff --git a/src/coreclr/vm/typehandle.inl b/src/coreclr/vm/typehandle.inl index 1e022e268d1d7f..d1916c121e56c2 100644 --- a/src/coreclr/vm/typehandle.inl +++ b/src/coreclr/vm/typehandle.inl @@ -27,6 +27,24 @@ inline PTR_MethodTable TypeHandle::GetMethodTable() const return AsMethodTable(); } +// This method allows you to get the "upcasted" type handle. Currently we need this +// because continuation types for runtime-async methods are dynamically created subtypes of a +// parent continuation class that have no metadata of their own. This way, when we need to get +// the TypeHandle to retrieve metadata, we are able to get a reasonable approximation. +// If we need to handle more such types in the future we can add them here. +inline TypeHandle TypeHandle::UpCastTypeIfNeeded() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + if (IsTypeDesc()) + return *this; + if (AsMethodTable()->IsContinuation()) + { + return TypeHandle(g_pContinuationClassIfSubTypeCreated); + } + return *this; +} + inline void TypeHandle::SetIsFullyLoaded() { LIMITED_METHOD_CONTRACT;