Esempio n. 1
0
// 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);
    }
}
Esempio n. 2
0
/*++

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;
}