From 39579c38c3bd189e37721d24c1f9f046a946aaf6 Mon Sep 17 00:00:00 2001 From: Jonghyun Park Date: Thu, 2 Feb 2017 18:41:46 +0900 Subject: [PATCH] [x86/Linux] Do NOT use pXXX fields (dotnet/coreclr#9121) * [x86/Linux] Do NOT use pXXX fields * Fix x86/Windows build error * Fix another x86/Windows build error * Fix typo * Do NOT trash EBP * Reflect the original semantics of EHContext::UpdateFrame * Unify ReadXXX/LocateXXX into GetXXXLocation, and RestoreXXX/TrashXXX into SetXXXLocation * Revert the order of pXXX fields * Revise cgenx86.cpp * Revert unnecessary changes * Remove direct accesses to CALLEE_SAVED_REGISTERS_TAG * Do NOT update pCurrentContext inside SetXXXLocation * Update RegPtr via offset * Unify REG_METHODS (and revise UpdateRegDisplay methods accordingly) * Revise per feedback * Fix x86/Windows build error Commit migrated from https://github.com/dotnet/coreclr/commit/009c70f81d2899848ea254fd39969de91fd33519 --- .../src/debug/daccess/dacdbiimplstackwalk.cpp | 14 +- src/coreclr/src/debug/ee/debugger.inl | 14 +- src/coreclr/src/debug/ee/i386/x86walker.cpp | 14 +- src/coreclr/src/debug/shared/i386/primitives.cpp | 12 +- src/coreclr/src/inc/regdisp.h | 40 ++- src/coreclr/src/pal/inc/pal.h | 13 +- src/coreclr/src/unwinder/i386/unwinder_i386.cpp | 40 +-- src/coreclr/src/vm/eetwain.cpp | 107 ++++---- src/coreclr/src/vm/frames.cpp | 4 +- src/coreclr/src/vm/gccover.cpp | 8 +- src/coreclr/src/vm/i386/cgencpu.h | 5 + src/coreclr/src/vm/i386/cgenx86.cpp | 279 ++++++++++++++------- src/coreclr/src/vm/proftoeeinterfaceimpl.cpp | 4 +- 13 files changed, 353 insertions(+), 201 deletions(-) diff --git a/src/coreclr/src/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/src/debug/daccess/dacdbiimplstackwalk.cpp index 7ab7ac7..29c9626 100644 --- a/src/coreclr/src/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/src/debug/daccess/dacdbiimplstackwalk.cpp @@ -1156,13 +1156,13 @@ void DacDbiInterfaceImpl::UpdateContextFromRegDisp(REGDISPLAY * pRegDisp, // Do a partial copy first. pContext->ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL); - pContext->Edi = *pRegDisp->pEdi; - pContext->Esi = *pRegDisp->pEsi; - pContext->Ebx = *pRegDisp->pEbx; - pContext->Ebp = *pRegDisp->pEbp; - pContext->Eax = *pRegDisp->pEax; - pContext->Ecx = *pRegDisp->pEcx; - pContext->Edx = *pRegDisp->pEdx; + pContext->Edi = *pRegDisp->GetEdiLocation(); + pContext->Esi = *pRegDisp->GetEsiLocation(); + pContext->Ebx = *pRegDisp->GetEbxLocation(); + pContext->Ebp = *pRegDisp->GetEbpLocation(); + pContext->Eax = *pRegDisp->GetEaxLocation(); + pContext->Ecx = *pRegDisp->GetEcxLocation(); + pContext->Edx = *pRegDisp->GetEdxLocation(); pContext->Esp = pRegDisp->SP; pContext->Eip = pRegDisp->ControlPC; diff --git a/src/coreclr/src/debug/ee/debugger.inl b/src/coreclr/src/debug/ee/debugger.inl index 54ac8b9..5737286 100644 --- a/src/coreclr/src/debug/ee/debugger.inl +++ b/src/coreclr/src/debug/ee/debugger.inl @@ -235,13 +235,13 @@ inline void FuncEvalFrame::UpdateRegDisplay(const PREGDISPLAY pRD) // Update all registers in the reg display from the CONTEXT we stored when the thread was hijacked for this func // eval. We have to update all registers, not just the callee saved registers, because we can hijack a thread at any // point for a func eval, not just at a call site. - pRD->pEdi = &(pDE->m_context.Edi); - pRD->pEsi = &(pDE->m_context.Esi); - pRD->pEbx = &(pDE->m_context.Ebx); - pRD->pEdx = &(pDE->m_context.Edx); - pRD->pEcx = &(pDE->m_context.Ecx); - pRD->pEax = &(pDE->m_context.Eax); - pRD->pEbp = &(pDE->m_context.Ebp); + pRD->SetEdiLocation(&(pDE->m_context.Edi)); + pRD->SetEsiLocation(&(pDE->m_context.Esi)); + pRD->SetEbxLocation(&(pDE->m_context.Ebx)); + pRD->SetEdxLocation(&(pDE->m_context.Edx)); + pRD->SetEcxLocation(&(pDE->m_context.Ecx)); + pRD->SetEaxLocation(&(pDE->m_context.Eax)); + pRD->SetEbpLocation(&(pDE->m_context.Ebp)); pRD->SP = (DWORD)GetSP(&pDE->m_context); pRD->PCTAddr = GetReturnAddressPtr(); pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); diff --git a/src/coreclr/src/debug/ee/i386/x86walker.cpp b/src/coreclr/src/debug/ee/i386/x86walker.cpp index 5266668..8b62797 100644 --- a/src/coreclr/src/debug/ee/i386/x86walker.cpp +++ b/src/coreclr/src/debug/ee/i386/x86walker.cpp @@ -292,28 +292,28 @@ DWORD NativeWalker::GetRegisterValue(int registerNumber) switch (registerNumber) { case 0: - return *m_registers->pEax; + return *m_registers->GetEaxLocation(); break; case 1: - return *m_registers->pEcx; + return *m_registers->GetEcxLocation(); break; case 2: - return *m_registers->pEdx; + return *m_registers->GetEdxLocation(); break; case 3: - return *m_registers->pEbx; + return *m_registers->GetEbxLocation(); break; case 4: return m_registers->SP; break; case 5: - return *m_registers->pEbp; + return *m_registers->GetEbpLocation(); break; case 6: - return *m_registers->pEsi; + return *m_registers->GetEsiLocation(); break; case 7: - return *m_registers->pEdi; + return *m_registers->GetEdiLocation(); break; default: _ASSERTE(!"Invalid register number!"); diff --git a/src/coreclr/src/debug/shared/i386/primitives.cpp b/src/coreclr/src/debug/shared/i386/primitives.cpp index d3c7c76..ab22a5d 100644 --- a/src/coreclr/src/debug/shared/i386/primitives.cpp +++ b/src/coreclr/src/debug/shared/i386/primitives.cpp @@ -88,12 +88,12 @@ void SetDebuggerREGDISPLAYFromREGDISPLAY(DebuggerREGDISPLAY* pDRD, REGDISPLAY* p // Frame pointer LPVOID FPAddress = GetRegdisplayFPAddress(pRD); pDRD->FP = (FPAddress == NULL ? 0 : *((SIZE_T *)FPAddress)); - pDRD->Edi = (pRD->pEdi == NULL ? 0 : *(pRD->pEdi)); - pDRD->Esi = (pRD->pEsi == NULL ? 0 : *(pRD->pEsi)); - pDRD->Ebx = (pRD->pEbx == NULL ? 0 : *(pRD->pEbx)); - pDRD->Edx = (pRD->pEdx == NULL ? 0 : *(pRD->pEdx)); - pDRD->Ecx = (pRD->pEcx == NULL ? 0 : *(pRD->pEcx)); - pDRD->Eax = (pRD->pEax == NULL ? 0 : *(pRD->pEax)); + pDRD->Edi = (pRD->GetEdiLocation() == NULL ? 0 : *pRD->GetEdiLocation()); + pDRD->Esi = (pRD->GetEsiLocation() == NULL ? 0 : *pRD->GetEsiLocation()); + pDRD->Ebx = (pRD->GetEbxLocation() == NULL ? 0 : *pRD->GetEbxLocation()); + pDRD->Edx = (pRD->GetEdxLocation() == NULL ? 0 : *pRD->GetEdxLocation()); + pDRD->Ecx = (pRD->GetEcxLocation() == NULL ? 0 : *pRD->GetEcxLocation()); + pDRD->Eax = (pRD->GetEsiLocation() == NULL ? 0 : *pRD->GetEaxLocation()); #if defined(USE_REMOTE_REGISTER_ADDRESS) pDRD->pFP = PushedRegAddr(pRD, FPAddress); diff --git a/src/coreclr/src/inc/regdisp.h b/src/coreclr/src/inc/regdisp.h index 6f98920..d7693cb 100644 --- a/src/coreclr/src/inc/regdisp.h +++ b/src/coreclr/src/inc/regdisp.h @@ -62,7 +62,6 @@ struct REGDISPLAY : public REGDISPLAY_BASE { PCONTEXT pContextForUnwind; // scratch context for unwinding // used to preserve context saved in the frame that // could be otherwise wiped by the unwinding -#endif // !WIN64EXCEPTIONS DWORD * pEdi; DWORD * pEsi; @@ -72,6 +71,33 @@ struct REGDISPLAY : public REGDISPLAY_BASE { DWORD * pEax; DWORD * pEbp; +#endif // !WIN64EXCEPTIONS + +#ifndef WIN64EXCEPTIONS + +#define REG_METHODS(reg) \ + inline PDWORD Get##reg##Location(void) { return p##reg; } \ + inline void Set##reg##Location(PDWORD p##reg) { this->p##reg = p##reg; } + +#else // !WIN64EXCEPTIONS + +#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; } + +#endif // WIN64EXCEPTIONS + + REG_METHODS(Eax) + REG_METHODS(Ecx) + REG_METHODS(Edx) + + REG_METHODS(Ebx) + REG_METHODS(Esi) + REG_METHODS(Edi) + REG_METHODS(Ebp) + +#undef REG_METHODS + TADDR PCTAddr; }; @@ -90,13 +116,13 @@ inline void SetRegdisplaySP(REGDISPLAY *display, LPVOID sp ) { inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_DAC_CONTRACT; - return (TADDR)*(display->pEbp); + return (TADDR)*display->GetEbpLocation(); } inline LPVOID GetRegdisplayFPAddress(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; - return (LPVOID)display->pEbp; + return (LPVOID)display->GetEbpLocation(); } inline PCODE GetControlPC(REGDISPLAY *display) { @@ -393,10 +419,10 @@ inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pC pRD->ctxPtrsOne.Lr = &pctx->Lr; #elif defined(_TARGET_X86_) // _TARGET_ARM_ - pRD->ctxPtrsOne.Ebx = &pctx->Ebx; - pRD->ctxPtrsOne.Esi = &pctx->Esi; - pRD->ctxPtrsOne.Edi = &pctx->Edi; - pRD->ctxPtrsOne.Ebp = &pctx->Ebp; + for (int i = 0; i < 7; i++) + { + *(&pRD->ctxPtrsOne.Esi + i) = (&pctx->Esi + i); + } #else // _TARGET_X86_ PORTABILITY_ASSERT("FillRegDisplay"); #endif // _TARGET_???_ (ELSE) diff --git a/src/coreclr/src/pal/inc/pal.h b/src/coreclr/src/pal/inc/pal.h index 46f4688..d0b78e9 100644 --- a/src/coreclr/src/pal/inc/pal.h +++ b/src/coreclr/src/pal/inc/pal.h @@ -1795,10 +1795,17 @@ typedef struct _CONTEXT { typedef struct _KNONVOLATILE_CONTEXT_POINTERS { - // TODO WIP x86/Linux, need to fix this. - PDWORD Ebx; - PDWORD Esi; + // The ordering of these fields should be aligned with that + // of corresponding fields in CONTEXT + // + // (See FillRegDisplay in inc/regdisp.h for details) PDWORD Edi; + PDWORD Esi; + PDWORD Ebx; + PDWORD Edx; + PDWORD Ecx; + PDWORD Eax; + PDWORD Ebp; } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; diff --git a/src/coreclr/src/unwinder/i386/unwinder_i386.cpp b/src/coreclr/src/unwinder/i386/unwinder_i386.cpp index f4490ac..b506c61 100644 --- a/src/coreclr/src/unwinder/i386/unwinder_i386.cpp +++ b/src/coreclr/src/unwinder/i386/unwinder_i386.cpp @@ -75,26 +75,14 @@ OOPStackUnwinderX86::VirtualUnwind( REGDISPLAY rd; - if (ContextPointers != NULL) - { -#define CALLEE_SAVED_REGISTER(reg) rd.p##reg = ContextPointers->reg; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER - } - else - { -#define CALLEE_SAVED_REGISTER(reg) rd.p##reg = NULL; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER - } + FillRegDisplay(&rd, ContextRecord); + + rd.PCTAddr = (UINT_PTR)&(ContextRecord->Eip); - if (rd.pEbp == NULL) + if (ContextPointers) { - rd.pEbp = &(ContextRecord->Ebp); + rd.pCurrentContextPointers = ContextPointers; } - rd.SP = ContextRecord->Esp; - rd.ControlPC = (PCODE)(ContextRecord->Eip); - rd.PCTAddr = (UINT_PTR)&(ContextRecord->Eip); CodeManState codeManState; codeManState.dwIsSet = 0; @@ -107,22 +95,18 @@ OOPStackUnwinderX86::VirtualUnwind( return HRESULT_FROM_WIN32(ERROR_READ_FAULT); } -#define CALLEE_SAVED_REGISTER(reg) if (rd.p##reg != NULL) { ContextRecord->reg = *rd.p##reg; } + ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; + +#define ARGUMENT_AND_SCRATCH_REGISTER(reg) if (rd.pCurrentContextPointers->reg) ContextRecord->reg = *rd.pCurrentContextPointers->reg; + ENUM_ARGUMENT_AND_SCRATCH_REGISTERS(); +#undef ARGUMENT_AND_SCRATCH_REGISTER + +#define CALLEE_SAVED_REGISTER(reg) if (rd.pCurrentContextPointers->reg) ContextRecord->reg = *rd.pCurrentContextPointers->reg; ENUM_CALLEE_SAVED_REGISTERS(); #undef CALLEE_SAVED_REGISTER - - if (ContextPointers != NULL) - { -#define CALLEE_SAVED_REGISTER(reg) if (rd.p##reg != &(ContextRecord->reg)) { ContextPointers->reg = rd.p##reg; } - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER - } - - ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; ContextRecord->Esp = rd.SP; ContextRecord->Eip = rd.ControlPC; - ContextRecord->Ebp = *rd.pEbp; return S_OK; } diff --git a/src/coreclr/src/vm/eetwain.cpp b/src/coreclr/src/vm/eetwain.cpp index 11a4590..8db5396e 100644 --- a/src/coreclr/src/vm/eetwain.cpp +++ b/src/coreclr/src/vm/eetwain.cpp @@ -1642,10 +1642,10 @@ void * getCalleeSavedReg(PREGDISPLAY pContext, regNum reg) switch (reg) { - case REGI_EBP: return pContext->pEbp; - case REGI_EBX: return pContext->pEbx; - case REGI_ESI: return pContext->pEsi; - case REGI_EDI: return pContext->pEdi; + case REGI_EBP: return pContext->GetEbpLocation(); + case REGI_EBX: return pContext->GetEbxLocation(); + case REGI_ESI: return pContext->GetEsiLocation(); + case REGI_EDI: return pContext->GetEdiLocation(); default: _ASSERTE(!"bad info.thisPtrResult"); return NULL; } @@ -2840,7 +2840,9 @@ void TRASH_CALLEE_UNSAVED_REGS(PREGDISPLAY pContext) /* This is not completely correct as we lose the current value, but it should not really be useful to anyone. */ static DWORD s_badData = 0xDEADBEEF; - pContext->pEax = pContext->pEcx = pContext->pEdx = &s_badData; + pContext->SetEaxLocation(&s_badData); + pContext->SetEcxLocation(&s_badData); + pContext->SetEdxLocation(&s_badData); #endif //_DEBUG } @@ -3126,9 +3128,11 @@ void EECodeManager::QuickUnwindStackFrame(PREGDISPLAY pRD, StackwalkCacheEntry * if (pCacheEntry->fUseEbpAsFrameReg) { _ASSERTE(pCacheEntry->fUseEbp); + TADDR curEBP = (TADDR)*pRD->GetEbpLocation(); + // EBP frame, update ESP through EBP, since ESPOffset may vary - pRD->pEbp = PTR_DWORD((TADDR)*pRD->pEbp); - pRD->SP = (TADDR)pRD->pEbp + sizeof(void*); + pRD->SetEbpLocation(PTR_DWORD(curEBP)); + pRD->SP = curEBP + sizeof(void*); } else { @@ -3203,13 +3207,32 @@ const RegMask CALLEE_SAVED_REGISTERS_MASK[] = RM_EBP // last register to be pushed }; -const SIZE_T REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[] = +static void SetLocation(PREGDISPLAY pRD, int ind, PDWORD loc) { - offsetof(REGDISPLAY, pEdi), // first register to be pushed - offsetof(REGDISPLAY, pEsi), - offsetof(REGDISPLAY, pEbx), - offsetof(REGDISPLAY, pEbp) // last register to be pushed -}; +#ifdef WIN64EXCEPTIONS + static const SIZE_T OFFSET_OF_CALLEE_SAVED_REGISTERS[] = + { + offsetof(T_KNONVOLATILE_CONTEXT_POINTERS, Edi), // first register to be pushed + offsetof(T_KNONVOLATILE_CONTEXT_POINTERS, Esi), + offsetof(T_KNONVOLATILE_CONTEXT_POINTERS, Ebx), + offsetof(T_KNONVOLATILE_CONTEXT_POINTERS, Ebp), // last register to be pushed + }; + + SIZE_T offsetOfRegPtr = OFFSET_OF_CALLEE_SAVED_REGISTERS[ind]; + *(LPVOID*)(PBYTE(pRD->pCurrentContextPointers) + offsetOfRegPtr) = loc; +#else + static const SIZE_T OFFSET_OF_CALLEE_SAVED_REGISTERS[] = + { + offsetof(REGDISPLAY, pEdi), // first register to be pushed + offsetof(REGDISPLAY, pEsi), + offsetof(REGDISPLAY, pEbx), + offsetof(REGDISPLAY, pEbp), // last register to be pushed + }; + + SIZE_T offsetOfRegPtr = OFFSET_OF_CALLEE_SAVED_REGISTERS[ind]; + *(LPVOID*)(PBYTE(pRD) + offsetOfRegPtr) = loc; +#endif +} /*****************************************************************************/ @@ -3275,8 +3298,7 @@ void UnwindEspFrameEpilog( Get the value from the stack if needed */ if ((flags & UpdateAllRegs) || (regMask == RM_EBP)) { - SIZE_T offsetOfRegPtr = REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[i - 1]; - *(LPVOID*)(PBYTE(pContext) + offsetOfRegPtr) = PTR_DWORD((TADDR)ESP); + SetLocation(pContext, i - 1, PTR_DWORD((TADDR)ESP)); } /* Adjust ESP */ @@ -3381,7 +3403,7 @@ void UnwindEbpDoubleAlignFrameEpilog( unsigned calleeSavedRegsSize = info->savedRegsCountExclFP * sizeof(void*); if (!InstructionAlreadyExecuted(offset, info->epilogOffs)) - ESP = (*pContext->pEbp) - calleeSavedRegsSize; + ESP = *pContext->GetEbpLocation() - calleeSavedRegsSize; offset = SKIP_LEA_ESP_EBP(-int(calleeSavedRegsSize), epilogBase, offset); } @@ -3399,8 +3421,7 @@ void UnwindEbpDoubleAlignFrameEpilog( { if (flags & UpdateAllRegs) { - SIZE_T offsetOfRegPtr = REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[i - 1]; - *(LPVOID*)(PBYTE(pContext) + offsetOfRegPtr) = PTR_DWORD((TADDR)ESP); + SetLocation(pContext, i - 1, PTR_DWORD((TADDR)ESP)); } ESP += sizeof(void*); } @@ -3411,7 +3432,7 @@ void UnwindEbpDoubleAlignFrameEpilog( if (needMovEspEbp) { if (!InstructionAlreadyExecuted(offset, info->epilogOffs)) - ESP = *pContext->pEbp; + ESP = *pContext->GetEbpLocation(); offset = SKIP_MOV_REG_REG(epilogBase, offset); } @@ -3419,7 +3440,7 @@ void UnwindEbpDoubleAlignFrameEpilog( // Have we executed the pop EBP? if (!InstructionAlreadyExecuted(offset, info->epilogOffs)) { - pContext->pEbp = PTR_DWORD(TADDR(ESP)); + pContext->SetEbpLocation(PTR_DWORD(TADDR(ESP))); ESP += sizeof(void*); } offset = SKIP_POP_REG(epilogBase, offset); @@ -3552,16 +3573,16 @@ void UnwindEspFrameProlog( // Always restore EBP if (regsMask & RM_EBP) - pContext->pEbp = savedRegPtr++; + pContext->SetEbpLocation(savedRegPtr++); if (flags & UpdateAllRegs) { if (regsMask & RM_EBX) - pContext->pEbx = savedRegPtr++; + pContext->SetEbxLocation(savedRegPtr++); if (regsMask & RM_ESI) - pContext->pEsi = savedRegPtr++; + pContext->SetEsiLocation(savedRegPtr++); if (regsMask & RM_EDI) - pContext->pEdi = savedRegPtr++; + pContext->SetEdiLocation(savedRegPtr++); TRASH_CALLEE_UNSAVED_REGS(pContext); } @@ -3627,8 +3648,7 @@ void UnwindEspFrame( if ((regMask & regsMask) == 0) continue; - SIZE_T offsetOfRegPtr = REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[i - 1]; - *(LPVOID*)(PBYTE(pContext) + offsetOfRegPtr) = PTR_DWORD((TADDR)ESP); + SetLocation(pContext, i - 1, PTR_DWORD((TADDR)ESP)); ESP += sizeof(unsigned); } @@ -3706,7 +3726,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->pEbp; + const unsigned curEBP = *pContext->GetEbpLocation(); if (flags & UpdateAllRegs) { @@ -3739,8 +3759,7 @@ void UnwindEbpDoubleAlignFrameProlog( if (InstructionAlreadyExecuted(offset, curOffs)) { - SIZE_T offsetOfRegPtr = REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[i]; - *(LPVOID*)(PBYTE(pContext) + offsetOfRegPtr) = --pSavedRegs; + SetLocation(pContext, i, PTR_DWORD(--pSavedRegs)); } // "push reg" @@ -3752,7 +3771,7 @@ void UnwindEbpDoubleAlignFrameProlog( /* The caller's saved EBP is pointed to by our EBP */ - pContext->pEbp = PTR_DWORD((TADDR)curEBP); + pContext->SetEbpLocation(PTR_DWORD((TADDR)curEBP)); pContext->SP = DWORD((TADDR)(curEBP + sizeof(void *))); /* Stack pointer points to return address */ @@ -3776,7 +3795,7 @@ bool UnwindEbpDoubleAlignFrame( _ASSERTE(info->ebpFrame || info->doubleAlign); const unsigned curESP = pContext->SP; - const unsigned curEBP = *pContext->pEbp; + const unsigned curEBP = *pContext->GetEbpLocation(); /* First check if we are in a filter (which is obviously after the prolog) */ @@ -3819,8 +3838,13 @@ bool UnwindEbpDoubleAlignFrame( { static DWORD s_badData = 0xDEADBEEF; - pContext->pEax = pContext->pEbx = pContext->pEcx = - pContext->pEdx = pContext->pEsi = pContext->pEdi = &s_badData; + pContext->SetEaxLocation(&s_badData); + pContext->SetEcxLocation(&s_badData); + pContext->SetEdxLocation(&s_badData); + + pContext->SetEbxLocation(&s_badData); + pContext->SetEsiLocation(&s_badData); + pContext->SetEdiLocation(&s_badData); } #endif @@ -3863,8 +3887,7 @@ bool UnwindEbpDoubleAlignFrame( if ((info->savedRegMask & regMask) == 0) continue; - SIZE_T offsetOfRegPtr = REGDISPLAY_OFFSET_OF_CALLEE_SAVED_REGISTERS[i]; - *(LPVOID*)(PBYTE(pContext) + offsetOfRegPtr) = --pSavedRegs; + SetLocation(pContext, i, --pSavedRegs); } } @@ -3879,7 +3902,7 @@ bool UnwindEbpDoubleAlignFrame( /* The caller's saved EBP is pointed to by our EBP */ - pContext->pEbp = PTR_DWORD((TADDR)curEBP); + pContext->SetEbpLocation(PTR_DWORD((TADDR)curEBP)); return true; } @@ -4118,7 +4141,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); unsigned curOffs = pCodeInfo->GetRelOffset(); - unsigned EBP = *pContext->pEbp; + unsigned EBP = *pContext->GetEbpLocation(); unsigned ESP = pContext->SP; unsigned ptrOffs; @@ -4185,7 +4208,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, if (dspPtr) \ printf(" Live pointer register %s: ", #regName); \ pCallBack(hCallBack, \ - (OBJECTREF*)(pContext->p##regName), \ + (OBJECTREF*)(pContext->Get##regName##Location()), \ (iptr ? GC_CALL_INTERIOR : 0) \ | CHECK_APP_DOMAIN \ DAC_ARG(DacSlotLocation(reg, 0, false))); \ @@ -4194,7 +4217,7 @@ bool EECodeManager::EnumGcRefs( PREGDISPLAY pContext, #define CHK_AND_REPORT_REG(reg, doIt, iptr, regName) \ if (doIt) \ pCallBack(hCallBack, \ - (OBJECTREF*)(pContext->p##regName), \ + (OBJECTREF*)(pContext->Get##regName##Location()), \ (iptr ? GC_CALL_INTERIOR : 0) \ | CHECK_APP_DOMAIN \ DAC_ARG(DacSlotLocation(reg, 0, false))); @@ -5019,7 +5042,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) (DWORD(*pRD->pEbp) - (securityObjectOffset * sizeof(void*))); + return (OBJECTREF *) (size_t) (*pRD->GetEbpLocation() - (securityObjectOffset * sizeof(void*))); #else PORTABILITY_ASSERT("EECodeManager::GetAddrOfSecurityObjectFromContext is not implemented on this platform."); return NULL; @@ -5059,7 +5082,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)(((DWORD)*pRD->pEbp) - GetSecurityObjectOffset(&stateBuf->hdrInfoBody)); + return (OBJECTREF *)(size_t)(*pRD->GetEbpLocation() - GetSecurityObjectOffset(&stateBuf->hdrInfoBody)); } } #elif defined(USE_GC_INFO_DECODER) && !defined(CROSSGEN_COMPILE) @@ -5161,7 +5184,7 @@ OBJECTREF EECodeManager::GetInstance( PREGDISPLAY pContext, if (info.ebpFrame) { _ASSERTE(stackDepth == 0); - taArgBase = *pContext->pEbp; + taArgBase = *pContext->GetEbpLocation(); } else { diff --git a/src/coreclr/src/vm/frames.cpp b/src/coreclr/src/vm/frames.cpp index 04a1815..ae3cfdb 100644 --- a/src/coreclr/src/vm/frames.cpp +++ b/src/coreclr/src/vm/frames.cpp @@ -2006,8 +2006,8 @@ BOOL MulticastFrame::TraceFrame(Thread *thread, BOOL fromPatch, #if defined(_TARGET_X86_) // At this point the counter hasn't been incremented yet. - delegateCount = *regs->pEdi + 1; - pbDel = *(BYTE **)( (size_t)*(regs->pEsi) + GetOffsetOfTransitionBlock() + ArgIterator::GetThisOffset()); + delegateCount = *regs->GetEdiLocation() + 1; + pbDel = *(BYTE **)( (size_t)*regs->GetEsiLocation() + GetOffsetOfTransitionBlock() + ArgIterator::GetThisOffset()); #elif defined(_TARGET_AMD64_) // At this point the counter hasn't been incremented yet. delegateCount = (int)regs->pCurrentContext->Rdi + 1; diff --git a/src/coreclr/src/vm/gccover.cpp b/src/coreclr/src/vm/gccover.cpp index d5e7b60..02bb0de 100644 --- a/src/coreclr/src/vm/gccover.cpp +++ b/src/coreclr/src/vm/gccover.cpp @@ -1565,10 +1565,10 @@ void DoGcStress (PCONTEXT regs, MethodDesc *pMD) _ASSERTE(pThread->PreemptiveGCDisabled()); // Epilogs should be in cooperative mode, no GC can happen right now. bool gcHappened = gcCover->gcCount != GCHeapUtilities::GetGCHeap()->GetGcCount(); - checkAndUpdateReg(gcCover->callerRegs.Edi, *regDisp.pEdi, gcHappened); - checkAndUpdateReg(gcCover->callerRegs.Esi, *regDisp.pEsi, gcHappened); - checkAndUpdateReg(gcCover->callerRegs.Ebx, *regDisp.pEbx, gcHappened); - checkAndUpdateReg(gcCover->callerRegs.Ebp, *regDisp.pEbp, gcHappened); + checkAndUpdateReg(gcCover->callerRegs.Edi, *regDisp.GetEdiLocation(), gcHappened); + checkAndUpdateReg(gcCover->callerRegs.Esi, *regDisp.GetEsiLocation(), gcHappened); + checkAndUpdateReg(gcCover->callerRegs.Ebx, *regDisp.GetEbxLocation(), gcHappened); + checkAndUpdateReg(gcCover->callerRegs.Ebp, *regDisp.GetEbpLocation(), gcHappened); gcCover->gcCount = GCHeapUtilities::GetGCHeap()->GetGcCount(); diff --git a/src/coreclr/src/vm/i386/cgencpu.h b/src/coreclr/src/vm/i386/cgencpu.h index 2c29d27..8a437f7 100644 --- a/src/coreclr/src/vm/i386/cgencpu.h +++ b/src/coreclr/src/vm/i386/cgencpu.h @@ -154,6 +154,11 @@ typedef INT32 StackElemType; // This represents some of the FramedMethodFrame fields that are // stored at negative offsets. //-------------------------------------------------------------------- +#define ENUM_ARGUMENT_AND_SCRATCH_REGISTERS() \ + ARGUMENT_AND_SCRATCH_REGISTER(Eax) \ + ARGUMENT_AND_SCRATCH_REGISTER(Ecx) \ + ARGUMENT_AND_SCRATCH_REGISTER(Edx) + #define ENUM_CALLEE_SAVED_REGISTERS() \ CALLEE_SAVED_REGISTER(Edi) \ CALLEE_SAVED_REGISTER(Esi) \ diff --git a/src/coreclr/src/vm/i386/cgenx86.cpp b/src/coreclr/src/vm/i386/cgenx86.cpp index 85db84a..2bf2fb3 100644 --- a/src/coreclr/src/vm/i386/cgenx86.cpp +++ b/src/coreclr/src/vm/i386/cgenx86.cpp @@ -60,6 +60,32 @@ extern "C" DWORD STDCALL GetSpecificCpuFeaturesAsm(DWORD *pInfo); void generate_noref_copy (unsigned nbytes, StubLinkerCPU* sl); +#ifdef WIN64EXCEPTIONS +void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * regs) +{ + LIMITED_METHOD_CONTRACT; + + T_CONTEXT * pContext = pRD->pCurrentContext; +#define CALLEE_SAVED_REGISTER(regname) pContext->regname = regs->regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + KNONVOLATILE_CONTEXT_POINTERS * pContextPointers = pRD->pCurrentContextPointers; +#define CALLEE_SAVED_REGISTER(regname) pContextPointers->regname = (DWORD*)®s->regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER +} + +void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD) +{ + LIMITED_METHOD_CONTRACT; + +#define ARGUMENT_AND_SCRATCH_REGISTER(regname) pRD->pCurrentContextPointers->regname = NULL; + ENUM_ARGUMENT_AND_SCRATCH_REGISTERS(); +#undef ARGUMENT_AND_SCRATCH_REGISTER +} +#endif // WIN64EXCEPTIONS + #ifndef DACCESS_COMPILE //============================================================================= @@ -214,10 +240,10 @@ void EHContext::Setup(PCODE resumePC, PREGDISPLAY regs) // EAX ECX EDX are scratch this->Esp = regs->SP; - this->Ebx = *regs->pEbx; - this->Esi = *regs->pEsi; - this->Edi = *regs->pEdi; - this->Ebp = *regs->pEbp; + this->Ebx = *regs->GetEbxLocation(); + this->Esi = *regs->GetEsiLocation(); + this->Edi = *regs->GetEdiLocation(); + this->Ebp = *regs->GetEbpLocation(); this->Eip = (ULONG)(size_t)resumePC; } @@ -246,15 +272,15 @@ void EHContext::UpdateFrame(PREGDISPLAY regs) // EAX ECX EDX are scratch. // No need to update ESP as unwinder takes care of that for us - LOG((LF_EH, LL_INFO1000, "Updating saved EBX: *%p= %p\n", regs->pEbx, this->Ebx)); - LOG((LF_EH, LL_INFO1000, "Updating saved ESI: *%p= %p\n", regs->pEsi, this->Esi)); - LOG((LF_EH, LL_INFO1000, "Updating saved EDI: *%p= %p\n", regs->pEdi, this->Edi)); - LOG((LF_EH, LL_INFO1000, "Updating saved EBP: *%p= %p\n", regs->pEbp, this->Ebp)); + LOG((LF_EH, LL_INFO1000, "Updating saved EBX: *%p= %p\n", regs->GetEbxLocation(), this->Ebx)); + LOG((LF_EH, LL_INFO1000, "Updating saved ESI: *%p= %p\n", regs->GetEsiLocation(), this->Esi)); + LOG((LF_EH, LL_INFO1000, "Updating saved EDI: *%p= %p\n", regs->GetEdiLocation(), this->Edi)); + LOG((LF_EH, LL_INFO1000, "Updating saved EBP: *%p= %p\n", regs->GetEbpLocation(), this->Ebp)); - *regs->pEbx = this->Ebx; - *regs->pEsi = this->Esi; - *regs->pEdi = this->Edi; - *regs->pEbp = this->Ebp; + *regs->GetEbxLocation() = this->Ebx; + *regs->GetEsiLocation() = this->Esi; + *regs->GetEdiLocation() = this->Edi; + *regs->GetEbpLocation() = this->Ebp; } void TransitionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) @@ -294,13 +320,6 @@ void TransitionFrame::UpdateRegDisplayHelper(const PREGDISPLAY pRD, UINT cbStack CalleeSavedRegisters* regs = GetCalleeSavedRegisters(); - // reset pContext; it's only valid for active (top-most) frame - - pRD->pContext = NULL; - -#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) ®s->regname; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER pRD->PCTAddr = GetReturnAddressPtr(); #ifdef WIN64EXCEPTIONS @@ -311,20 +330,20 @@ void TransitionFrame::UpdateRegDisplayHelper(const PREGDISPLAY pRD, UINT cbStack pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);; pRD->pCurrentContext->Esp = GetSP(); - T_CONTEXT * pContext = pRD->pCurrentContext; -#define CALLEE_SAVED_REGISTER(regname) pContext->regname = regs->regname; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER - - KNONVOLATILE_CONTEXT_POINTERS * pContextPointers = pRD->pCurrentContextPointers; -#define CALLEE_SAVED_REGISTER(regname) pContextPointers->regname = (DWORD*)®s->regname; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER + UpdateRegDisplayFromCalleeSavedRegisters(pRD, regs); + ClearRegDisplayArgumentAndScratchRegisters(pRD); SyncRegDisplayToCurrentContext(pRD); #else // WIN64EXCEPTIONS + // reset pContext; it's only valid for active (top-most) frame + pRD->pContext = NULL; + +#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) ®s->regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); pRD->SP = (DWORD)(pRD->PCTAddr + sizeof(TADDR) + cbStackPop); @@ -350,6 +369,38 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK HelperMethodFrame::UpdateRegDisplay cached ip:%p, sp:%p\n", m_MachState.GetRetAddr(), m_MachState.esp())); + pRD->PCTAddr = dac_cast(m_MachState.pRetAddr()); + +#ifdef WIN64EXCEPTIONS + + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + +#ifdef DACCESS_COMPILE + PORTABILITY_ASSERT("HelperMethodFrame::UpdateRegDisplay"); +#endif // DACCESS_COMPILE + + pRD->pCurrentContext->Eip = pRD->ControlPC = m_MachState.GetRetAddr(); + pRD->pCurrentContext->Esp = pRD->SP = (DWORD) m_MachState.esp(); + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = *((DWORD*) m_MachState.p##regname()); + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContextPointers->regname = (DWORD*) m_MachState.p##regname(); + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + // + // Clear all knowledge of scratch registers. We're skipping to any + // arbitrary point on the stack, and frames aren't required to preserve or + // keep track of these anyways. + // + + ClearRegDisplayArgumentAndScratchRegisters(pRD); + +#else // WIN64EXCEPTIONS + // reset pContext; it's only valid for active (top-most) frame pRD->pContext = NULL; @@ -391,15 +442,12 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) // in the real code. I'm not sure exactly // what should happen in the on-the-fly case, // but go with what would happen from an InsureInit. -#ifdef WIN64EXCEPTIONS - PORTABILITY_ASSERT("HelperMethodFrame::UpdateRegDisplay"); -#endif RETURN; } #endif // #ifdef DACCESS_COMPILE - + // DACCESS: The MachState pointers are kept as PTR_TADDR so // the host pointers here refer to the appropriate size and // these casts are not a problem. @@ -407,27 +455,10 @@ void HelperMethodFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pEsi = (DWORD*) m_MachState.pEsi(); pRD->pEbx = (DWORD*) m_MachState.pEbx(); pRD->pEbp = (DWORD*) m_MachState.pEbp(); - pRD->PCTAddr = dac_cast(m_MachState.pRetAddr()); + pRD->ControlPC = m_MachState.GetRetAddr(); pRD->SP = (DWORD) m_MachState.esp(); -#ifdef WIN64EXCEPTIONS - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - - // - // Copy the saved state from the frame to the current context. - // - pRD->pCurrentContext->Eip = pRD->ControlPC; - pRD->pCurrentContext->Esp = pRD->SP; - -#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = *pRD->p##regname; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER - -#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContextPointers->regname = pRD->p##regname; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER #endif // WIN64EXCEPTIONS RETURN; @@ -563,34 +594,36 @@ void FaultingExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD) // reset pContext; it's only valid for active (top-most) frame pRD->pContext = NULL; -#ifndef WIN64EXCEPTIONS - CalleeSavedRegisters* regs = GetCalleeSavedRegisters(); - -#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) ®s->regname; - ENUM_CALLEE_SAVED_REGISTERS(); -#undef CALLEE_SAVED_REGISTER - pRD->SP = m_Esp; pRD->PCTAddr = GetReturnAddressPtr(); - pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); - -#else // WIN64EXCEPTIONS - pRD->IsCallerContextValid = FALSE; - pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. +#ifdef WIN64EXCEPTIONS memcpy(pRD->pCurrentContext, &m_ctx, sizeof(CONTEXT)); + pRD->SP = m_ctx.Esp; + pRD->ControlPC = m_ctx.Eip; + +#define ARGUMENT_AND_SCRATCH_REGISTER(regname) pRD->pCurrentContextPointers->regname = &m_ctx.regname; + ENUM_ARGUMENT_AND_SCRATCH_REGISTERS(); +#undef ARGUMENT_AND_SCRATCH_REGISTER + #define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContextPointers->regname = &m_ctx.regname; ENUM_CALLEE_SAVED_REGISTERS(); #undef CALLEE_SAVED_REGISTER -#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = &m_ctx.regname; + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + +#else // WIN64EXCEPTIONS + + CalleeSavedRegisters* regs = GetCalleeSavedRegisters(); + +#define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) ®s->regname; ENUM_CALLEE_SAVED_REGISTERS(); #undef CALLEE_SAVED_REGISTER - pRD->SP = m_ctx.Esp; - pRD->PCTAddr = GetReturnAddressPtr(); - pRD->ControlPC = m_ctx.Eip; + pRD->SP = m_Esp; + pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); #endif // WIN64EXCEPTIONS @@ -638,36 +671,41 @@ void InlinedCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) stackArgSize = pMD->GetStackArgumentSize(); } - // reset pContext; it's only valid for active (top-most) frame - pRD->pContext = NULL; - - - pRD->pEbp = (DWORD*) &m_pCalleeSavedFP; - /* The return address is just above the "ESP" */ pRD->PCTAddr = PTR_HOST_MEMBER_TADDR(InlinedCallFrame, this, m_pCallerReturnAddress); - pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); - - /* Now we need to pop off the outgoing arguments */ - pRD->SP = (DWORD) dac_cast(m_pCallSiteSP) + stackArgSize; #ifdef WIN64EXCEPTIONS + pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. - pRD->pCurrentContext->Eip = pRD->ControlPC; - pRD->pCurrentContext->Esp = pRD->SP; - pRD->pCurrentContext->Ebp = *pRD->pEbp; + pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr); + pRD->pCurrentContext->Esp = (DWORD) dac_cast(m_pCallSiteSP) + stackArgSize; + pRD->pCurrentContext->Ebp = (DWORD) m_pCalleeSavedFP; + + ClearRegDisplayArgumentAndScratchRegisters(pRD); #define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContextPointers->regname = NULL; ENUM_CALLEE_SAVED_REGISTERS(); #undef CALLEE_SAVED_REGISTER - pRD->pCurrentContextPointers->Ebp = pRD->pEbp; + pRD->pCurrentContextPointers->Ebp = (DWORD*) &m_pCalleeSavedFP; SyncRegDisplayToCurrentContext(pRD); -#endif + +#else // WIN64EXCEPTIONS + + // reset pContext; it's only valid for active (top-most) frame + pRD->pContext = NULL; + + pRD->pEbp = (DWORD*) &m_pCalleeSavedFP; + + pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); + /* Now we need to pop off the outgoing arguments */ + pRD->SP = (DWORD) dac_cast(m_pCallSiteSP) + stackArgSize; + +#endif // WIN64EXCEPTIONS LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK InlinedCallFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); @@ -696,12 +734,33 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD) } CONTRACT_END; + pRD->PCTAddr = dac_cast(m_Regs) + offsetof(CONTEXT, Eip); + +#ifdef WIN64EXCEPTIONS + + memcpy(pRD->pCurrentContext, &m_Regs, sizeof(CONTEXT)); + + pRD->SP = m_Regs->Esp; + pRD->ControlPC = m_Regs->Eip; + +#define ARGUMENT_AND_SCRATCH_REGISTER(reg) pRD->pCurrentContextPointers->reg = &m_Regs->reg; + ENUM_ARGUMENT_AND_SCRATCH_REGISTERS(); +#undef ARGUMENT_AND_SCRATCH_REGISTER + +#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContextPointers->reg = &m_Regs->reg; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + +#else // WIN64EXCEPTIONS + // reset pContext; it's only valid for active (top-most) frame pRD->pContext = NULL; CONTEXT* pUnwoundContext = m_Regs; -#ifndef WIN64EXCEPTIONS #if !defined(DACCESS_COMPILE) // "pContextForUnwind" field is only used on X86 since not only is it initialized just for it, // but its used only under the confines of STACKWALKER_MAY_POP_FRAMES preprocessor define, @@ -721,7 +780,6 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pUnwoundContext->Eip = m_Regs->Eip; } #endif // !defined(DACCESS_COMPILE) -#endif // !WIN64EXCEPTIONS pRD->pEax = &pUnwoundContext->Eax; pRD->pEcx = &pUnwoundContext->Ecx; @@ -733,10 +791,11 @@ void ResumableFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pEbp = &pUnwoundContext->Ebp; pRD->ControlPC = pUnwoundContext->Eip; - pRD->PCTAddr = dac_cast(m_Regs) + offsetof(CONTEXT, Eip); pRD->SP = m_Regs->Esp; +#endif // !WIN64EXCEPTIONS + RETURN; } @@ -751,6 +810,34 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD) } CONTRACTL_END; + pRD->PCTAddr = dac_cast(m_Args) + offsetof(HijackArgs, Eip); + +#ifdef WIN64EXCEPTIONS + + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + + pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr); + pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR)); + +#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContext->reg = m_Args->reg; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define CALLEE_SAVED_REGISTER(reg) pRD->pCurrentContextPointers->reg = NULL; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define ARGUMENT_AND_SCRATCH_REGISTER(reg) pRD->pCurrentContextPointers->reg = NULL; + ENUM_ARGUMENT_AND_SCRATCH_REGISTERS(); +#undef ARGUMENT_AND_SCRATCH_REGISTER + + pRD->pCurrentContextPointers->Eax = (PDWORD) &m_Args->Eax; + + SyncRegDisplayToCurrentContext(pRD); + +#else // WIN64EXCEPTIONS + // This only describes the top-most frame pRD->pContext = NULL; @@ -762,9 +849,10 @@ void HijackFrame::UpdateRegDisplay(const PREGDISPLAY pRD) pRD->pEax = &m_Args->Eax; pRD->pEbp = &m_Args->Ebp; - pRD->PCTAddr = dac_cast(m_Args) + offsetof(HijackArgs, Eip); pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); pRD->SP = (DWORD)(pRD->PCTAddr + sizeof(TADDR)); + +#endif // WIN64EXCEPTIONS } #endif // FEATURE_HIJACK @@ -801,15 +889,34 @@ void TailCallFrame::UpdateRegDisplay(const PREGDISPLAY pRD) // reset pContext; it's only valid for active (top-most) frame pRD->pContext = NULL; + pRD->PCTAddr = GetReturnAddressPtr(); + +#ifdef WIN64EXCEPTIONS + + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + + pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr); + pRD->pCurrentContext->Esp = (DWORD)(pRD->PCTAddr + sizeof(TADDR)); + + UpdateRegDisplayFromCalleeSavedRegisters(pRD, &m_regs); + ClearRegDisplayArgumentAndScratchRegisters(pRD); + + SyncRegDisplayToCurrentContext(pRD); + +#else #define CALLEE_SAVED_REGISTER(regname) pRD->p##regname = (DWORD*) &m_regs.regname; ENUM_CALLEE_SAVED_REGISTERS(); #undef CALLEE_SAVED_REGISTER - pRD->PCTAddr = GetReturnAddressPtr(); pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr); pRD->SP = (DWORD)(pRD->PCTAddr + sizeof(TADDR)); +#endif + + LOG((LF_GCROOTS, LL_INFO100000, "STACKWALK TransitionFrame::UpdateRegDisplay(ip:%p, sp:%p)\n", pRD->ControlPC, pRD->SP)); + RETURN; } diff --git a/src/coreclr/src/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/src/vm/proftoeeinterfaceimpl.cpp index 6a50c62..da66dbd 100644 --- a/src/coreclr/src/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/src/vm/proftoeeinterfaceimpl.cpp @@ -7411,7 +7411,7 @@ Loop: REGDISPLAY rd; ZeroMemory(&rd, sizeof(rd)); - rd.pEbp = &ctxCur.Ebp; + rd.SetEbpLocation(&ctxCur.Ebp); rd.SP = ctxCur.Esp; rd.ControlPC = ctxCur.Eip; @@ -7422,7 +7422,7 @@ Loop: &codeManState, NULL); - ctxCur.Ebp = *(rd.pEbp); + ctxCur.Ebp = *rd.GetEbpLocation(); ctxCur.Esp = rd.SP; ctxCur.Eip = rd.ControlPC; } -- 2.7.4