// Set the stackwalker to the specified CONTEXT. void DacDbiInterfaceImpl::SetStackWalkCurrentContext(VMPTR_Thread vmThread, StackWalkHandle pSFIHandle, CorDebugSetContextFlag flag, DT_CONTEXT * pContext) { DD_ENTER_MAY_THROW; StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle); REGDISPLAY * pRD = GetRegDisplayFromHandle(pSFIHandle); #if defined(_DEBUG) // The caller should have checked this already. _ASSERTE(CheckContext(vmThread, pContext) == S_OK); #endif // _DEBUG // DD can't keep pointers back into the RS address space. // Allocate a context in DDImpl's memory space. DDImpl can't contain raw pointers back into // the client space since that may not marshal. T_CONTEXT * pContext2 = GetContextBufferFromHandle(pSFIHandle); *pContext2 = *reinterpret_cast<T_CONTEXT *>(pContext); // memcpy // update the REGDISPLAY with the given CONTEXT. // Be sure that the context is in DDImpl's memory space and not the Right-sides. FillRegDisplay(pRD, pContext2); BOOL fSuccess = pIter->ResetRegDisp(pRD, (flag == SET_CONTEXT_FLAG_ACTIVE_FRAME)); if (!fSuccess) { // ResetRegDisp() may fail for the same reason Init() may fail, i.e. // because the stackwalker tries to unwind one frame ahead of time, // or because the stackwalker needs to filter out some frames based on the stackwalk flags. ThrowHR(E_FAIL); } }
/*++ Routine Description: This function virtually unwinds the specified function by executing its prologue code backward or its epilogue code forward. If a context pointers record is specified, then the address where each nonvolatile registers is restored from is recorded in the appropriate element of the context pointers record. Arguments: HandlerType - Supplies the handler type expected for the virtual unwind. This may be either an exception or an unwind handler. A flag may optionally be supplied to avoid epilogue detection if it is known the specified control PC is not located inside a function epilogue. ImageBase - Supplies the base address of the image that contains the function being unwound. ControlPc - Supplies the address where control left the specified function. FunctionEntry - Supplies the address of the function table entry for the specified function. ContextRecord - Supplies the address of a context record. HandlerData - Supplies a pointer to a variable that receives a pointer the the language handler data. EstablisherFrame - Supplies a pointer to a variable that receives the the establisher frame pointer value. ContextPointers - Supplies an optional pointer to a context pointers record. HandlerRoutine - Supplies an optional pointer to a variable that receives the handler routine address. If control did not leave the specified function in either the prologue or an epilogue and a handler of the proper type is associated with the function, then the address of the language specific exception handler is returned. Otherwise, NULL is returned. --*/ HRESULT OOPStackUnwinderX86::VirtualUnwind( __in DWORD HandlerType, __in DWORD ImageBase, __in DWORD ControlPc, __in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, __inout PCONTEXT ContextRecord, __out PVOID *HandlerData, __out PDWORD EstablisherFrame, __inout_opt PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, __deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine ) { if (HandlerRoutine != NULL) { *HandlerRoutine = NULL; } REGDISPLAY rd; FillRegDisplay(&rd, ContextRecord); rd.SP = ContextRecord->ResumeEsp; rd.PCTAddr = (UINT_PTR)&(ContextRecord->Eip); if (ContextPointers) { rd.pCurrentContextPointers = ContextPointers; } CodeManState codeManState; codeManState.dwIsSet = 0; EECodeInfo codeInfo; codeInfo.Init((PCODE) ControlPc); if (!UnwindStackFrame(&rd, &codeInfo, UpdateAllRegs, &codeManState, NULL)) { return HRESULT_FROM_WIN32(ERROR_READ_FAULT); } 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 ContextRecord->Esp = rd.SP - codeInfo.GetCodeManager()->GetStackParameterSize(&codeInfo); ContextRecord->ResumeEsp = rd.SP; ContextRecord->Eip = rd.ControlPC; // For x86, the value of Establisher Frame Pointer is Caller SP // // (Please refers to CLR ABI for details) *EstablisherFrame = ContextRecord->Esp; return S_OK; }