[x86/Linux] Do NOT use pXXX fields (dotnet/coreclr#9121)
authorJonghyun Park <parjong@gmail.com>
Thu, 2 Feb 2017 09:41:46 +0000 (18:41 +0900)
committerJan Vorlicek <janvorli@microsoft.com>
Thu, 2 Feb 2017 09:41:46 +0000 (10:41 +0100)
* [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

13 files changed:
src/coreclr/src/debug/daccess/dacdbiimplstackwalk.cpp
src/coreclr/src/debug/ee/debugger.inl
src/coreclr/src/debug/ee/i386/x86walker.cpp
src/coreclr/src/debug/shared/i386/primitives.cpp
src/coreclr/src/inc/regdisp.h
src/coreclr/src/pal/inc/pal.h
src/coreclr/src/unwinder/i386/unwinder_i386.cpp
src/coreclr/src/vm/eetwain.cpp
src/coreclr/src/vm/frames.cpp
src/coreclr/src/vm/gccover.cpp
src/coreclr/src/vm/i386/cgencpu.h
src/coreclr/src/vm/i386/cgenx86.cpp
src/coreclr/src/vm/proftoeeinterfaceimpl.cpp

index 7ab7ac7..29c9626 100644 (file)
@@ -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;
 
index 54ac8b9..5737286 100644 (file)
@@ -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);
index 5266668..8b62797 100644 (file)
@@ -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!");
index d3c7c76..ab22a5d 100644 (file)
@@ -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);
index 6f98920..d7693cb 100644 (file)
@@ -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)
index 46f4688..d0b78e9 100644 (file)
@@ -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;
index f4490ac..b506c61 100644 (file)
@@ -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;
 }
index 11a4590..8db5396 100644 (file)
@@ -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
     {
index 04a1815..ae3cfdb 100644 (file)
@@ -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;
index d5e7b60..02bb0de 100644 (file)
@@ -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();
 
index 2c29d27..8a437f7 100644 (file)
@@ -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) \
index 85db84a..2bf2fb3 100644 (file)
@@ -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*)&regs->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*) &regs->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*)&regs->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*) &regs->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<TADDR>(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<TADDR>(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*) &regs->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*) &regs->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<TADDR>(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<TADDR>(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<TADDR>(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<TADDR>(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<TADDR>(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<TADDR>(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<TADDR>(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;
 }
 
index 6a50c62..da66dbd 100644 (file)
@@ -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;
             }