summaryrefslogtreecommitdiff
path: root/src/debug/di
diff options
context:
space:
mode:
authorJuan Hoyos <juan.hoyos@microsoft.com>2019-06-26 10:11:56 -0700
committerGitHub <noreply@github.com>2019-06-26 10:11:56 -0700
commit394edf40a089ac3fae5415dba8235b89c7133319 (patch)
treeb345f3742355429ce2ea9d7790fe37b4ee6fe6f3 /src/debug/di
parentbe31aaea6402390d808fa41d4cd1fa9b68f4cdd0 (diff)
downloadcoreclr-394edf40a089ac3fae5415dba8235b89c7133319.tar.gz
coreclr-394edf40a089ac3fae5415dba8235b89c7133319.tar.bz2
coreclr-394edf40a089ac3fae5415dba8235b89c7133319.zip
Delegate inspection API in the DBI (#25362)
* Add ICorDebugDelegateObjectValue interfaces * Expose appropriate HR (CORDBG_E_UNSUPPORTED_DELEGATE) * Partially DACize DelegateObject * Add DacDbi method for delegate inspection
Diffstat (limited to 'src/debug/di')
-rw-r--r--src/debug/di/divalue.cpp192
-rw-r--r--src/debug/di/rspriv.h19
2 files changed, 203 insertions, 8 deletions
diff --git a/src/debug/di/divalue.cpp b/src/debug/di/divalue.cpp
index 59cd382085..a8ef5652e7 100644
--- a/src/debug/di/divalue.cpp
+++ b/src/debug/di/divalue.cpp
@@ -23,7 +23,6 @@ void localCopy(void * dest, MemoryRange source)
memcpy(dest, source.StartAddress(), source.Size());
}
-
// for an inheritance graph of the ICDValue types, // See file:./ICorDebugValueTypes.vsd for a diagram of the types.
/* ------------------------------------------------------------------------- *
@@ -271,6 +270,15 @@ void CordbValue::CreateVCObjOrRefValue(CordbAppDomain * pAppdomain
// vmObj - the remote object to get an ICDValue for
ICorDebugValue* CordbValue::CreateHeapValue(CordbAppDomain* pAppDomain, VMPTR_Object vmObj)
{
+ // Create a temporary reference and dereference it to construct the heap value we want.
+ RSSmartPtr<CordbReferenceValue> pRefValue(CordbValue::CreateHeapReferenceValue(pAppDomain, vmObj));
+ ICorDebugValue* pExtValue;
+ IfFailThrow(pRefValue->Dereference(&pExtValue));
+ return pExtValue;
+}
+
+CordbReferenceValue* CordbValue::CreateHeapReferenceValue(CordbAppDomain* pAppDomain, VMPTR_Object vmObj)
+{
IDacDbiInterface* pDac = pAppDomain->GetProcess()->GetDAC();
TargetBuffer objBuffer = pDac->GetObjectContents(vmObj);
@@ -286,11 +294,8 @@ ICorDebugValue* CordbValue::CreateHeapValue(CordbAppDomain* pAppDomain, VMPTR_Ob
VMPTR_OBJECTHANDLE::NullPtr(),
NULL,
&pRefValue));
-
- // Dereference our temporary reference value to construct the heap value we want
- ICorDebugValue* pExtValue;
- IfFailThrow(pRefValue->Dereference(&pExtValue));
- return pExtValue;
+
+ return pRefValue;
}
// Gets the size om bytes of a value from its type. If the value is complex, we assume it is represented as
@@ -1730,7 +1735,7 @@ CordbObjectValue::CordbObjectValue(CordbAppDomain * pAppdomain,
m_info(*pObjectData),
m_pObjectCopy(NULL), m_objectLocalVars(NULL), m_stringBuffer(NULL),
m_valueHome(pAppdomain->GetProcess(), remoteValue),
- m_fIsExceptionObject(FALSE), m_fIsRcw(FALSE)
+ m_fIsExceptionObject(FALSE), m_fIsRcw(FALSE), m_fIsDelegate(FALSE)
{
_ASSERTE(pAppdomain != NULL);
@@ -1754,6 +1759,15 @@ CordbObjectValue::CordbObjectValue(CordbAppDomain * pAppdomain,
if (hr == S_OK)
m_fIsRcw = TRUE;
+
+ hr = S_FALSE;
+ ALLOW_DATATARGET_MISSING_MEMORY
+ (
+ hr = IsDelegate();
+ );
+
+ if (hr == S_OK)
+ m_fIsDelegate = TRUE;
} // CordbObjectValue::CordbObjectValue
// destructor
@@ -1827,6 +1841,10 @@ HRESULT CordbObjectValue::QueryInterface(REFIID id, void **pInterface)
{
*pInterface = static_cast<ICorDebugComObjectValue*>(this);
}
+ else if (id == IID_ICorDebugDelegateObjectValue && m_fIsDelegate)
+ {
+ *pInterface = static_cast<ICorDebugDelegateObjectValue*>(this);
+ }
else if (id == IID_IUnknown)
{
*pInterface = static_cast<IUnknown*>(static_cast<ICorDebugObjectValue*>(this));
@@ -2517,6 +2535,166 @@ HRESULT CordbObjectValue::IsRcw()
return hr;
}
+HRESULT CordbObjectValue::IsDelegate()
+{
+ HRESULT hr = S_OK;
+
+ if (m_info.objTypeData.elementType != ELEMENT_TYPE_CLASS)
+ {
+ hr = S_FALSE;
+ }
+ else
+ {
+ CORDB_ADDRESS objAddr = m_valueHome.GetAddress();
+
+ if (objAddr == NULL)
+ {
+ // object is a literal
+ hr = S_FALSE;
+ }
+ else
+ {
+ IDacDbiInterface *pDAC = GetProcess()->GetDAC();
+
+ VMPTR_Object vmObj = pDAC->GetObject(objAddr);
+ BOOL fIsDelegate = pDAC->IsDelegate(vmObj);
+
+ if (!fIsDelegate)
+ hr = S_FALSE;
+ }
+ }
+
+ return hr;
+}
+
+HRESULT IsSupportedDelegateHelper(IDacDbiInterface::DelegateType delType)
+{
+ switch (delType)
+ {
+ case IDacDbiInterface::DelegateType::kClosedDelegate:
+ case IDacDbiInterface::DelegateType::kOpenDelegate:
+ return S_OK;
+ default:
+ return CORDBG_E_UNSUPPORTED_DELEGATE;
+ }
+}
+
+HRESULT CordbObjectValue::GetTargetHelper(ICorDebugReferenceValue **ppTarget)
+{
+ IDacDbiInterface::DelegateType delType;
+ VMPTR_Object pDelegateObj;
+ VMPTR_Object pDelegateTargetObj;
+ VMPTR_AppDomain pAppDomainOfTarget;
+
+ CORDB_ADDRESS delegateAddr = m_valueHome.GetAddress();
+
+ IDacDbiInterface *pDAC = GetProcess()->GetDAC();
+ pDelegateObj = pDAC->GetObject(delegateAddr);
+
+ HRESULT hr = pDAC->GetDelegateType(pDelegateObj, &delType);
+ if (hr != S_OK)
+ return hr;
+
+ hr = IsSupportedDelegateHelper(delType);
+ if (hr != S_OK)
+ return hr;
+
+ hr = pDAC->GetDelegateTargetObject(delType, pDelegateObj, &pDelegateTargetObj, &pAppDomainOfTarget);
+ if (hr != S_OK || pDelegateTargetObj.IsNull())
+ {
+ *ppTarget = NULL;
+ return hr;
+ }
+
+ RSLockHolder lockHolder(GetProcess()->GetProcessLock());
+ RSSmartPtr<CordbAppDomain> pCordbAppDomForTarget(GetProcess()->LookupOrCreateAppDomain(pAppDomainOfTarget));
+ RSSmartPtr<CordbReferenceValue> targetObjRefVal(CordbValue::CreateHeapReferenceValue(pCordbAppDomForTarget, pDelegateTargetObj));
+ *ppTarget = static_cast<ICorDebugReferenceValue*>(targetObjRefVal.GetValue());
+ targetObjRefVal->ExternalAddRef();
+
+ return S_OK;
+}
+
+HRESULT CordbObjectValue::GetFunctionHelper(ICorDebugFunction **ppFunction)
+{
+ IDacDbiInterface::DelegateType delType;
+ VMPTR_Object pDelegateObj;
+
+ *ppFunction = NULL;
+ CORDB_ADDRESS delegateAddr = m_valueHome.GetAddress();
+
+ IDacDbiInterface *pDAC = GetProcess()->GetDAC();
+ pDelegateObj = pDAC->GetObject(delegateAddr);
+
+ HRESULT hr = pDAC->GetDelegateType(pDelegateObj, &delType);
+ if (hr != S_OK)
+ return hr;
+
+ hr = IsSupportedDelegateHelper(delType);
+ if (hr != S_OK)
+ return hr;
+
+ mdMethodDef functionMethodDef = 0;
+ VMPTR_DomainFile functionDomainFile;
+ NativeCodeFunctionData nativeCodeForDelFunc;
+
+ hr = pDAC->GetDelegateFunctionData(delType, pDelegateObj, &functionDomainFile, &functionMethodDef);
+ if (hr != S_OK)
+ return hr;
+
+ // TODO: How to ensure results are sanitized?
+ // Also, this is expensive. Do we really care that much about this?
+ pDAC->GetNativeCodeInfo(functionDomainFile, functionMethodDef, &nativeCodeForDelFunc);
+
+ RSSmartPtr<CordbModule> funcModule(GetProcess()->LookupOrCreateModule(functionDomainFile));
+ RSSmartPtr<CordbFunction> func;
+ {
+ RSLockHolder lockHolder(GetProcess()->GetProcessLock());
+ func.Assign(funcModule->LookupOrCreateFunction(functionMethodDef, nativeCodeForDelFunc.encVersion));
+ }
+
+ *ppFunction = static_cast<ICorDebugFunction*> (func.GetValue());
+ func->ExternalAddRef();
+
+ return S_OK;
+}
+
+HRESULT CordbObjectValue::GetTarget(ICorDebugReferenceValue **ppObject)
+{
+ PUBLIC_API_ENTRY(this);
+ FAIL_IF_NEUTERED(this);
+ VALIDATE_POINTER_TO_OBJECT(ppObject, ICorDebugReferenceValue **);
+ ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
+ _ASSERTE(m_fIsDelegate);
+
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ hr = GetTargetHelper(ppObject);
+ }
+ EX_CATCH_HRESULT(hr);
+ return hr;
+}
+
+HRESULT CordbObjectValue::GetFunction(ICorDebugFunction **ppFunction)
+{
+ PUBLIC_API_ENTRY(this);
+ FAIL_IF_NEUTERED(this);
+ VALIDATE_POINTER_TO_OBJECT(ppFunction, ICorDebugFunction **);
+ ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
+ _ASSERTE(m_fIsDelegate);
+
+ HRESULT hr = S_OK;
+
+ EX_TRY
+ {
+ hr = GetFunctionHelper(ppFunction);
+ }
+ EX_CATCH_HRESULT(hr)
+ return hr;
+}
+
HRESULT CordbObjectValue::GetCachedInterfaceTypes(
BOOL bIInspectableOnly,
ICorDebugTypeEnum * * ppInterfacesEnum)
diff --git a/src/debug/di/rspriv.h b/src/debug/di/rspriv.h
index a6cfcf9749..6e4a93fb90 100644
--- a/src/debug/di/rspriv.h
+++ b/src/debug/di/rspriv.h
@@ -101,6 +101,7 @@ class CordbRCEventThread;
class CordbRegisterSet;
class CordbNativeFrame;
class CordbObjectValue;
+class CordbReferenceValue;
class CordbEnCErrorInfo;
class CordbEnCErrorInfoEnum;
class Instantiation;
@@ -8755,6 +8756,9 @@ public:
static ICorDebugValue* CreateHeapValue(CordbAppDomain* pAppDomain,
VMPTR_Object vmObj);
+ // Creates a proper CordbReferenceValue instance based on the given remote heap object
+ static CordbReferenceValue* CreateHeapReferenceValue(CordbAppDomain* pAppDomain,
+ VMPTR_Object vmObj);
// Returns a pointer to the ValueHome field of this instance of CordbValue if one exists or NULL
// otherwise. Therefore, this also tells us indirectly whether this instance of CordbValue is also an
@@ -9159,7 +9163,8 @@ class CordbObjectValue : public CordbValue,
public ICorDebugHeapValue2,
public ICorDebugHeapValue3,
public ICorDebugExceptionObjectValue,
- public ICorDebugComObjectValue
+ public ICorDebugComObjectValue,
+ public ICorDebugDelegateObjectValue
{
public:
@@ -9287,6 +9292,12 @@ public:
CORDB_ADDRESS * ptrs);
//-----------------------------------------------------------
+ // ICorDebugComObjectValue
+ //-----------------------------------------------------------
+ COM_METHOD GetTarget(ICorDebugReferenceValue** ppObject);
+ COM_METHOD GetFunction(ICorDebugFunction** ppFunction);
+
+ //-----------------------------------------------------------
// Non-COM methods
//-----------------------------------------------------------
@@ -9324,6 +9335,12 @@ private:
HRESULT IsRcw();
BOOL m_fIsRcw;
+
+ HRESULT IsDelegate();
+ HRESULT GetFunctionHelper(ICorDebugFunction **ppFunction);
+ HRESULT GetTargetHelper(ICorDebugReferenceValue **ppTarget);
+
+ BOOL m_fIsDelegate;
};
/* ------------------------------------------------------------------------- *