diff options
author | Juan Hoyos <juan.hoyos@microsoft.com> | 2019-06-26 10:11:56 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-26 10:11:56 -0700 |
commit | 394edf40a089ac3fae5415dba8235b89c7133319 (patch) | |
tree | b345f3742355429ce2ea9d7790fe37b4ee6fe6f3 /src/debug/di | |
parent | be31aaea6402390d808fa41d4cd1fa9b68f4cdd0 (diff) | |
download | coreclr-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.cpp | 192 | ||||
-rw-r--r-- | src/debug/di/rspriv.h | 19 |
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; }; /* ------------------------------------------------------------------------- * |