diff options
Diffstat (limited to 'src/debug/di/module.cpp')
-rw-r--r-- | src/debug/di/module.cpp | 377 |
1 files changed, 375 insertions, 2 deletions
diff --git a/src/debug/di/module.cpp b/src/debug/di/module.cpp index 6717e8575f..36cc6f5f9e 100644 --- a/src/debug/di/module.cpp +++ b/src/debug/di/module.cpp @@ -3755,7 +3755,269 @@ HRESULT FindNativeInfoInILVariableArray(DWORD return CORDBG_E_IL_VAR_NOT_AVAILABLE; } // FindNativeInfoInILVariableArray -//* ------------------------------------------------------------------------- * + +// * ------------------------------------------------------------------------- * +// * Variable Enum class +// * ------------------------------------------------------------------------- * +//----------------------------------------------------------------------------- +// CordbVariableHome constructor +// Arguments: +// Input: +// pCode - CordbNativeCode instance containing this variable home +// pNativeVarInfo - native location, lifetime, and index information for +// this variable +// isLocal - indicates whether the instance is a local variable, +// as opposed to an argument +// index - the argument or slot index +// Output: +// fields of the CordbVariableHome instance have been initialized +//----------------------------------------------------------------------------- +CordbVariableHome::CordbVariableHome(CordbNativeCode *pCode, + const ICorDebugInfo::NativeVarInfo nativeVarInfo, + BOOL isLocal, + ULONG index) : + CordbBase(pCode->GetModule()->GetProcess(), 0) +{ + _ASSERTE(pCode != NULL); + + m_pCode.Assign(pCode); + m_nativeVarInfo = nativeVarInfo; + m_isLocal = isLocal; + m_index = index; +} + +CordbVariableHome::~CordbVariableHome() +{ + _ASSERTE(this->IsNeutered()); +} + +void CordbVariableHome::Neuter() +{ + m_pCode.Clear(); + CordbBase::Neuter(); +} + +//----------------------------------------------------------------------------- +// Public method for IUnknown::QueryInterface. +// Has standard QI semantics. +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::QueryInterface(REFIID id, void **pInterface) +{ + if (id == IID_ICorDebugVariableHome) + { + *pInterface = static_cast<ICorDebugVariableHome *>(this); + } + else if (id == IID_IUnknown) + { + *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugVariableHome *>(this)); + } + else + { + *pInterface = NULL; + return E_NOINTERFACE; + } + + ExternalAddRef(); + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetCode +// Public method to get the Code object containing this variable home. +// +// Parameters: +// ppCode - OUT: returns the Code object for this variable home. +// +// Returns: +// S_OK - on success. +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetCode(ICorDebugCode **ppCode) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(ppCode, ICorDebugCode **); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + HRESULT hr = m_pCode->QueryInterface(IID_ICorDebugCode, (LPVOID*)ppCode); + + return hr; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetSlotIndex +// Public method to get the slot index for this variable home. +// +// Parameters: +// pSlotIndex - OUT: returns the managed slot-index of this variable home. +// +// Returns: +// S_OK - on success +// E_FAIL - if the variable is not a local variable, but an argument +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetSlotIndex(ULONG32 *pSlotIndex) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pSlotIndex, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + if (!m_isLocal) + { + return E_FAIL; + } + *pSlotIndex = m_index; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetArgumentIndex +// Public method to get the slot index for this variable home. +// +// Parameters: +// pSlotIndex - OUT: returns the managed argument-index of this variable home. +// +// Returns: +// S_OK - on success +// E_FAIL - if the variable is not an argument, but a local variable +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetArgumentIndex(ULONG32 *pArgumentIndex) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pArgumentIndex, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + if (m_isLocal) + { + return E_FAIL; + } + *pArgumentIndex = m_index; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetLiveRange +// Public method to get the native range over which this variable is live. +// +// Parameters: +// pStartOffset - OUT: returns the logical offset at which the variable is +// first live +// pEndOffset - OUT: returns the logical offset immediately after that at +// which the variable is last live +// +// Returns: +// S_OK - on success +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetLiveRange(ULONG32 *pStartOffset, + ULONG32 *pEndOffset) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pStartOffset, ULONG32 *); + VALIDATE_POINTER_TO_OBJECT(pEndOffset, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + *pStartOffset = m_nativeVarInfo.startOffset; + *pEndOffset = m_nativeVarInfo.endOffset; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetLocationType +// Public method to get the type of native location for this variable home. +// +// Parameters: +// pLocationType - OUT: the type of native location +// +// Returns: +// S_OK - on success +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetLocationType(VariableLocationType *pLocationType) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pLocationType, VariableLocationType *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_REG: + *pLocationType = VLT_REGISTER; + break; + case ICorDebugInfo::VLT_STK: + *pLocationType = VLT_REGISTER_RELATIVE; + break; + default: + *pLocationType = VLT_INVALID; + } + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetRegister +// Public method to get the register or base register for this variable hom. +// +// Parameters: +// pRegister - OUT: for VLT_REGISTER location types, gives the register. +// for VLT_REGISTER_RELATIVE location types, gives the base +// register. +// +// Returns: +// S_OK - on success +// E_FAIL - for VLT_INVALID location types +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetRegister(CorDebugRegister *pRegister) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pRegister, CorDebugRegister *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_REG: + *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlReg.vlrReg); + break; + case ICorDebugInfo::VLT_STK: + *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlStk.vlsBaseReg); + break; + default: + return E_FAIL; + } + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetOffset +// Public method to get the offset from the base register for this variable home. +// +// Parameters: +// pOffset - OUT: gives the offset from the base register +// +// Returns: +// S_OK - on success +// E_FAIL - for location types other than VLT_REGISTER_RELATIVE +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetOffset(LONG *pOffset) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pOffset, LONG *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_STK: + *pOffset = m_nativeVarInfo.loc.vlStk.vlsOffset; + break; + default: + return E_FAIL; + } + return S_OK; +} + + +// * ------------------------------------------------------------------------- * // * Native Code class // * ------------------------------------------------------------------------- */ @@ -3780,7 +4042,7 @@ CordbNativeCode::CordbNativeCode(CordbFunction * pFunction, m_fIsInstantiatedGeneric(fIsInstantiatedGeneric != FALSE) { _ASSERTE(GetVersion() >= CorDB_DEFAULT_ENC_FUNCTION_VERSION); - + for (CodeBlobRegion region = kHot; region < MAX_REGIONS; ++region) { m_rgCodeRegions[region] = pJitData->m_rgCodeRegions[region]; @@ -3805,6 +4067,10 @@ HRESULT CordbNativeCode::QueryInterface(REFIID id, void ** pInterface) { *pInterface = static_cast<ICorDebugCode3 *>(this); } + else if (id == IID_ICorDebugCode4) + { + *pInterface = static_cast<ICorDebugCode4 *>(this); + } else if (id == IID_IUnknown) { *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugCode *>(this)); @@ -4111,6 +4377,113 @@ HRESULT CordbNativeCode::GetReturnValueLiveOffset(ULONG32 ILoffset, ULONG32 buff return hr; } +//----------------------------------------------------------------------------- +// CordbNativeCode::EnumerateVariableHomes +// Public method to get an enumeration of native variable homes. This may +// include multiple ICorDebugVariableHomes for the same slot or argument index +// if they have different homes at different points in the function. +// +// Parameters: +// ppEnum - OUT: returns the enum of variable homes. +// +// Returns: +// HRESULT for success or failure. +//----------------------------------------------------------------------------- +HRESULT CordbNativeCode::EnumerateVariableHomes(ICorDebugVariableHomeEnum **ppEnum) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(ppEnum, ICorDebugVariableHomeEnum **); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); + + HRESULT hr = S_OK; + + // Get the argument count + ULONG argCount = 0; + CordbFunction *func = GetFunction(); + _ASSERTE(func != NULL); + IfFailRet(func->GetSig(NULL, &argCount, NULL)); + +#ifdef _DEBUG + // Get the number of locals + ULONG localCount = 0; + EX_TRY + { + GetFunction()->GetILCode()->GetLocalVarSig(NULL, &localCount); + } + EX_CATCH_HRESULT(hr); + IfFailRet(hr); +#endif + + RSSmartPtr<CordbVariableHome> *rsHomes = NULL; + + EX_TRY + { + CordbProcess *pProcess = GetProcess(); + _ASSERTE(pProcess != NULL); + + const DacDbiArrayList<ICorDebugInfo::NativeVarInfo> *pOffsetInfoList = m_nativeVarData.GetOffsetInfoList(); + _ASSERTE(pOffsetInfoList != NULL); + DWORD countHomes = 0; + for (int i = 0; i < pOffsetInfoList->Count(); i++) + { + const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]); + _ASSERTE(pNativeVarInfo != NULL); + + // The variable information list can include variables + // with special varNumbers representing, for instance, the + // parameter types for generic methods. Here we are only + // interested in local variables and arguments. + if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM) + { + countHomes++; + } + } + rsHomes = new RSSmartPtr<CordbVariableHome>[countHomes]; + + DWORD varHomeInd = 0; + for (int i = 0; i < pOffsetInfoList->Count(); i++) + { + const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]); + + // Again, only look for native var info representing local + // variables and arguments. + if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM) + { + // determine whether this variable home represents and argument or local variable + BOOL isLocal = ((ULONG)pNativeVarInfo->varNumber >= argCount); + + // determine the argument-index or slot-index of this variable home + ULONG argOrSlotIndex; + if (isLocal) { + argOrSlotIndex = pNativeVarInfo->varNumber - argCount; + _ASSERTE(argOrSlotIndex < localCount); + } else { + argOrSlotIndex = pNativeVarInfo->varNumber; + } + + RSInitHolder<CordbVariableHome> pCVH(new CordbVariableHome(this, + (*pOffsetInfoList)[i], + isLocal, + argOrSlotIndex)); + pProcess->GetContinueNeuterList()->Add(pProcess, pCVH); + _ASSERTE(varHomeInd < countHomes); + rsHomes[varHomeInd].Assign(pCVH); + pCVH.ClearAndMarkDontNeuter(); + varHomeInd++; + } + } + + RSInitHolder<CordbVariableHomeEnumerator> pCDVHE( + new CordbVariableHomeEnumerator(GetProcess(), &rsHomes, countHomes)); + pProcess->GetContinueNeuterList()->Add(pProcess, pCDVHE); + pCDVHE.TransferOwnershipExternal(ppEnum); + } + EX_CATCH_HRESULT(hr); + + return hr; +} + int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) { #if defined(DBG_TARGET_ARM) |