Esempio n. 1
0
HRESULT 
LLDBServices::GetThreadContextById(
    /* in */ ULONG32 threadID,
    /* in */ ULONG32 contextFlags,
    /* in */ ULONG32 contextSize,
    /* out */ PBYTE context)
{
    lldb::SBProcess process;
    lldb::SBThread thread;
    lldb::SBFrame frame;
    DT_CONTEXT *dtcontext;
    HRESULT hr = E_FAIL;

    if (context == NULL || contextSize < sizeof(DT_CONTEXT))
    {
        goto exit;
    }
    memset(context, 0, contextSize);

    process = GetCurrentProcess();
    if (!process.IsValid())
    {
        goto exit;
    }

    // If we have a "fake" thread OS (system) id and a fake thread index,
    // use the fake thread index to get the context.
    if (g_currentThreadSystemId == threadID && g_currentThreadIndex != -1)
    {
        thread = process.GetThreadByIndexID(g_currentThreadIndex);
    }
    else
    {
        thread = process.GetThreadByID(threadID);
    }
    
    if (!thread.IsValid())
    {
        goto exit;
    }

    frame = thread.GetFrameAtIndex(0);
    if (!frame.IsValid())
    {
        goto exit;
    }

    dtcontext = (DT_CONTEXT*)context;
    dtcontext->ContextFlags = contextFlags;

    GetContextFromFrame(frame, dtcontext);
    hr = S_OK;

exit:
    return hr;
}
Esempio n. 2
0
HRESULT
LLDBServices::GetContextStackTrace(
    PVOID startContext,
    ULONG startContextSize,
    PDEBUG_STACK_FRAME frames,
    ULONG framesSize,
    PVOID frameContexts,
    ULONG frameContextsSize,
    ULONG frameContextsEntrySize,
    PULONG framesFilled)
{
    DT_CONTEXT *currentContext = (DT_CONTEXT*)frameContexts;
    PDEBUG_STACK_FRAME currentFrame = frames;
    lldb::SBThread thread;
    lldb::SBFrame frame;
    ULONG cFrames = 0;
    HRESULT hr = S_OK;

    // Doesn't support a starting context
    if (startContext != NULL || frames == NULL || frameContexts == NULL || frameContextsEntrySize != sizeof(DT_CONTEXT))
    {
        hr = E_INVALIDARG;
        goto exit;
    }

    thread = GetCurrentThread();
    if (!thread.IsValid())
    {
        hr = E_FAIL;
        goto exit;
    }

    frame = thread.GetFrameAtIndex(0);
    for (int i = 0; i < thread.GetNumFrames(); i++)
    {
        if (!frame.IsValid() || (cFrames > framesSize) || ((char *)currentContext > ((char *)frameContexts + frameContextsSize)))
        {
            break;
        }
        lldb::SBFrame framePrevious;
        lldb::SBFrame frameNext;

        currentFrame->InstructionOffset = frame.GetPC();
        currentFrame->StackOffset = frame.GetSP();

        currentFrame->FuncTableEntry = 0;
        currentFrame->Params[0] = 0;
        currentFrame->Params[1] = 0;
        currentFrame->Params[2] = 0;
        currentFrame->Params[3] = 0;
        currentFrame->Virtual = i == 0 ? TRUE : FALSE;
        currentFrame->FrameNumber = frame.GetFrameID();

        frameNext = thread.GetFrameAtIndex(i + 1);
        if (frameNext.IsValid())
        {
            currentFrame->ReturnOffset = frameNext.GetPC();
        }

        if (framePrevious.IsValid())
        {
            currentFrame->FrameOffset = framePrevious.GetSP();
        }
        else
        {
            currentFrame->FrameOffset = frame.GetSP();
        }

        GetContextFromFrame(frame, currentContext);

        framePrevious = frame;
        frame = frameNext;
        currentContext++;
        currentFrame++;
        cFrames++;
    }

exit:
    if (framesFilled != NULL)
    {
        *framesFilled = cFrames;
    }
    return hr;
}
Esempio n. 3
0
//
// lldb doesn't have a way or API to unwind an arbitary context (IP, SP)
// and return the next frame so we have to stick with the native frames
// lldb has found and find the closest frame to the incoming context SP.
//
HRESULT 
LLDBServices::VirtualUnwind(
    DWORD threadID,
    ULONG32 contextSize,
    PBYTE context)
{
    lldb::SBProcess process;
    lldb::SBThread thread;

    if (context == NULL || contextSize < sizeof(DT_CONTEXT))
    {
        return E_INVALIDARG;
    }

    process = GetCurrentProcess();
    if (!process.IsValid())
    {
        return E_FAIL;
    }

    thread = process.GetThreadByID(threadID);
    if (!thread.IsValid())
    {
        return E_FAIL;
    }

    DT_CONTEXT *dtcontext = (DT_CONTEXT*)context;
    lldb::SBFrame frameFound;

#ifdef DBG_TARGET_AMD64
    DWORD64 spToFind = dtcontext->Rsp;
#elif DBG_TARGET_X86
    DWORD spToFind = dtcontext->Esp;
#elif DBG_TARGET_ARM
    DWORD spToFind = dtcontext->Sp;
#endif
    
    int numFrames = thread.GetNumFrames();
    for (int i = 0; i < numFrames; i++)
    {
        lldb::SBFrame frame = thread.GetFrameAtIndex(i);
        if (!frame.IsValid())
        {
            break;
        }
        lldb::addr_t sp = frame.GetSP();

        if ((i + 1) < numFrames)
        {
            lldb::SBFrame frameNext = thread.GetFrameAtIndex(i + 1);
            if (frameNext.IsValid())
            {
                lldb::addr_t spNext = frameNext.GetSP();

                // An exact match of the current frame's SP would be nice
                // but sometimes the incoming context is between lldb frames
                if (spToFind >= sp && spToFind < spNext)
                {
                    frameFound = frameNext;
                    break;
                }
            }
        }
    }

    if (!frameFound.IsValid())
    {
        return E_FAIL;
    }

    GetContextFromFrame(frameFound, dtcontext);

    return S_OK;
}
Esempio n. 4
0
HRESULT 
DebugClient::VirtualUnwind(
    DWORD threadID,
    ULONG32 contextSize,
    PBYTE context)
{
    lldb::SBProcess process;
    lldb::SBThread thread;

    if (context == NULL || contextSize < sizeof(DT_CONTEXT))
    {
        return E_FAIL;
    }

    process = GetCurrentProcess();
    if (!process.IsValid())
    {
        return E_FAIL;
    }

    thread = process.GetThreadByID(threadID);
    if (!thread.IsValid())
    {
        return E_FAIL;
    }

    DT_CONTEXT *dtcontext = (DT_CONTEXT*)context;
    lldb::SBFrame frameFound;

#ifdef DBG_TARGET_AMD64
    DWORD64 spToFind = dtcontext->Rsp;
#elif DBG_TARGET_ARM
    DWORD spToFind = dtcontext->Sp;
#endif
    
    int numFrames = thread.GetNumFrames();
    for (int i = 0; i < numFrames; i++)
    {
        lldb::SBFrame frame = thread.GetFrameAtIndex(i);
        if (!frame.IsValid())
        {
            break;
        }

        lldb::addr_t sp = frame.GetSP();

        if (sp == spToFind && (i + 1) < numFrames)
        {
            // Get next frame after finding the match
            frameFound = thread.GetFrameAtIndex(i + 1);
            break;
        }
    }

    if (!frameFound.IsValid())
    {
        return E_FAIL;
    }

    GetContextFromFrame(frameFound, dtcontext);

    return S_OK;
}