From b241dc76c28557e15aef1a78f9bae5bd67134c7e Mon Sep 17 00:00:00 2001 From: Konstantin Baladurin Date: Thu, 26 Sep 2019 20:06:57 +0300 Subject: [Linux/x86] Use ebp from current context during unwinding (#26789) pCurrentContextPointers in REGDISPLAY can contain NULLs so we need to use ebp value from pCurrentContext. This patch contains following changes: - GetRegdisplayFP returns ebp from pCurrentContext - GetRegdisplayFP is used instead of *GetEbpLocation() - Set##reg##Location also updates register value in pCurrentContext --- src/debug/ee/i386/x86walker.cpp | 2 +- src/inc/regdisp.h | 11 +++++++++-- src/vm/eetwain.cpp | 21 ++++++++++----------- src/vm/proftoeeinterfaceimpl.cpp | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/debug/ee/i386/x86walker.cpp b/src/debug/ee/i386/x86walker.cpp index 8b62797484..078bc7ca75 100644 --- a/src/debug/ee/i386/x86walker.cpp +++ b/src/debug/ee/i386/x86walker.cpp @@ -307,7 +307,7 @@ DWORD NativeWalker::GetRegisterValue(int registerNumber) return m_registers->SP; break; case 5: - return *m_registers->GetEbpLocation(); + return GetRegdisplayFP(m_registers); break; case 6: return *m_registers->GetEsiLocation(); diff --git a/src/inc/regdisp.h b/src/inc/regdisp.h index 546ce2831a..e43bd0013e 100644 --- a/src/inc/regdisp.h +++ b/src/inc/regdisp.h @@ -95,7 +95,11 @@ struct REGDISPLAY : public REGDISPLAY_BASE { #define REG_METHODS(reg) \ inline PDWORD Get##reg##Location(void) { return pCurrentContextPointers->reg; } \ - inline void Set##reg##Location(PDWORD p##reg) { pCurrentContextPointers->reg = p##reg; } + inline void Set##reg##Location(PDWORD p##reg) \ + { \ + pCurrentContextPointers->reg = p##reg; \ + pCurrentContext->reg = *p##reg; \ + } #endif // WIN64EXCEPTIONS @@ -115,8 +119,11 @@ struct REGDISPLAY : public REGDISPLAY_BASE { inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_DAC_CONTRACT; - +#ifdef WIN64EXCEPTIONS + return (TADDR)display->pCurrentContext->Ebp; +#else return (TADDR)*display->GetEbpLocation(); +#endif } inline LPVOID GetRegdisplayFPAddress(REGDISPLAY *display) { diff --git a/src/vm/eetwain.cpp b/src/vm/eetwain.cpp index c0eb7aa8d0..c3e49cfe8a 100644 --- a/src/vm/eetwain.cpp +++ b/src/vm/eetwain.cpp @@ -3203,7 +3203,7 @@ void EECodeManager::QuickUnwindStackFrame(PREGDISPLAY pRD, StackwalkCacheEntry * if (pCacheEntry->fUseEbpAsFrameReg) { _ASSERTE(pCacheEntry->fUseEbp); - TADDR curEBP = (TADDR)*pRD->GetEbpLocation(); + TADDR curEBP = GetRegdisplayFP(pRD); // EBP frame, update ESP through EBP, since ESPOffset may vary pRD->SetEbpLocation(PTR_DWORD(curEBP)); @@ -3479,7 +3479,7 @@ void UnwindEbpDoubleAlignFrameEpilog( unsigned calleeSavedRegsSize = info->savedRegsCountExclFP * sizeof(void*); if (!InstructionAlreadyExecuted(offset, info->epilogOffs)) - ESP = *pContext->GetEbpLocation() - calleeSavedRegsSize; + ESP = GetRegdisplayFP(pContext) - calleeSavedRegsSize; offset = SKIP_LEA_ESP_EBP(-int(calleeSavedRegsSize), epilogBase, offset); } @@ -3508,7 +3508,7 @@ void UnwindEbpDoubleAlignFrameEpilog( if (needMovEspEbp) { if (!InstructionAlreadyExecuted(offset, info->epilogOffs)) - ESP = *pContext->GetEbpLocation(); + ESP = GetRegdisplayFP(pContext); offset = SKIP_MOV_REG_REG(epilogBase, offset); } @@ -3802,7 +3802,7 @@ void UnwindEbpDoubleAlignFrameProlog( can be determined using EBP. Since we are still in the prolog, we need to know our exact location to determine the callee-saved registers */ - const unsigned curEBP = *pContext->GetEbpLocation(); + const unsigned curEBP = GetRegdisplayFP(pContext); if (flags & UpdateAllRegs) { @@ -3873,8 +3873,8 @@ bool UnwindEbpDoubleAlignFrame( _ASSERTE(info->ebpFrame || info->doubleAlign); - const unsigned curESP = pContext->SP; - const unsigned curEBP = *pContext->GetEbpLocation(); + const unsigned curESP = pContext->SP; + const unsigned curEBP = GetRegdisplayFP(pContext); /* First check if we are in a filter (which is obviously after the prolog) */ @@ -4015,7 +4015,6 @@ bool UnwindEbpDoubleAlignFrame( /* The caller's saved EBP is pointed to by our EBP */ pContext->SetEbpLocation(PTR_DWORD((TADDR)curEBP)); - return true; } @@ -4310,8 +4309,8 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); unsigned curOffs = pCodeInfo->GetRelOffset(); - unsigned EBP = *pContext->GetEbpLocation(); - unsigned ESP = pContext->SP; + unsigned EBP = GetRegdisplayFP(pContext); + unsigned ESP = pContext->SP; unsigned ptrOffs; @@ -5243,7 +5242,7 @@ OBJECTREF* EECodeManager::GetAddrOfSecurityObjectFromCachedInfo(PREGDISPLAY pRD, // We pretend that filters are ESP-based methods in UnwindEbpDoubleAlignFrame(). // Hence we cannot enforce this assert. // _ASSERTE(stackwalkCacheUnwindInfo->fUseEbpAsFrameReg); - return (OBJECTREF *) (size_t) (*pRD->GetEbpLocation() - (securityObjectOffset * sizeof(void*))); + return (OBJECTREF *) (size_t) (GetRegdisplayFP(pRD) - (securityObjectOffset * sizeof(void*))); } #endif // _TARGET_X86_ @@ -5280,7 +5279,7 @@ OBJECTREF* EECodeManager::GetAddrOfSecurityObject(CrawlFrame *pCF) if(stateBuf->hdrInfoBody.prologOffs == hdrInfo::NOT_IN_PROLOG && stateBuf->hdrInfoBody.epilogOffs == hdrInfo::NOT_IN_EPILOG) { - return (OBJECTREF *)(size_t)(*pRD->GetEbpLocation() - GetSecurityObjectOffset(&stateBuf->hdrInfoBody)); + return (OBJECTREF *)(size_t)(GetRegdisplayFP(pRD) - GetSecurityObjectOffset(&stateBuf->hdrInfoBody)); } } #else // !USE_GC_INFO_DECODER diff --git a/src/vm/proftoeeinterfaceimpl.cpp b/src/vm/proftoeeinterfaceimpl.cpp index 2a8a46c468..c20d660872 100644 --- a/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/vm/proftoeeinterfaceimpl.cpp @@ -7837,7 +7837,7 @@ Loop: CodeManState codeManState; codeManState.dwIsSet = 0; REGDISPLAY rd; - ZeroMemory(&rd, sizeof(rd)); + FillRegDisplay(&rd, &ctxCur); rd.SetEbpLocation(&ctxCur.Ebp); rd.SP = ctxCur.Esp; -- cgit v1.2.3