// 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;
// 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);
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!");
// 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);
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;
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;
};
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) {
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)
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;
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;
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;
}
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;
}
/* 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
}
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
{
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
+}
/*****************************************************************************/
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 */
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);
}
{
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*);
}
if (needMovEspEbp)
{
if (!InstructionAlreadyExecuted(offset, info->epilogOffs))
- ESP = *pContext->pEbp;
+ ESP = *pContext->GetEbpLocation();
offset = SKIP_MOV_REG_REG(epilogBase, offset);
}
// 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);
// 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);
}
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);
}
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)
{
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"
/* 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 */
_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) */
{
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
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);
}
}
/* 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;
}
GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken();
unsigned curOffs = pCodeInfo->GetRelOffset();
- unsigned EBP = *pContext->pEbp;
+ unsigned EBP = *pContext->GetEbpLocation();
unsigned ESP = pContext->SP;
unsigned ptrOffs;
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))); \
#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)));
// 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;
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)
if (info.ebpFrame)
{
_ASSERTE(stackDepth == 0);
- taArgBase = *pContext->pEbp;
+ taArgBase = *pContext->GetEbpLocation();
}
else
{
#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;
_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();
// 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) \
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
//=============================================================================
// 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;
}
// 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)
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
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);
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;
// 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.
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;
// 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
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));
}
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,
pUnwoundContext->Eip = m_Regs->Eip;
}
#endif // !defined(DACCESS_COMPILE)
-#endif // !WIN64EXCEPTIONS
pRD->pEax = &pUnwoundContext->Eax;
pRD->pEcx = &pUnwoundContext->Ecx;
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;
}
}
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;
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
// 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;
}
REGDISPLAY rd;
ZeroMemory(&rd, sizeof(rd));
- rd.pEbp = &ctxCur.Ebp;
+ rd.SetEbpLocation(&ctxCur.Ebp);
rd.SP = ctxCur.Esp;
rd.ControlPC = ctxCur.Eip;
&codeManState,
NULL);
- ctxCur.Ebp = *(rd.pEbp);
+ ctxCur.Ebp = *rd.GetEbpLocation();
ctxCur.Esp = rd.SP;
ctxCur.Eip = rd.ControlPC;
}