Exemplo n.º 1
0
// Format breakpoints as GDBMI
std::string gdbmiBreakpoints(CIDebugControl *ctrl,
                             CIDebugSymbols *symbols /* = 0 */,
                             CIDebugDataSpaces *dataSpaces /* = 0 */,
                             bool humanReadable, unsigned verbose, std::string *errorMessage)
{
    ULONG breakPointCount = 0;
    HRESULT hr = ctrl->GetNumberBreakpoints(&breakPointCount);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("GetNumberBreakpoints", hr);
        return std::string();
    }
    std::ostringstream str;
    str << '[';
    if (humanReadable)
        str << '\n';
    for (ULONG i = 0; i < breakPointCount; ++i) {
        str << "{number=\"" << i << '"';
        IDebugBreakpoint *bp = 0;
        hr = ctrl->GetBreakpointByIndex(i, &bp);
        if (FAILED(hr) || !bp) {
            *errorMessage = msgDebugEngineComFailed("GetBreakpointByIndex", hr);
            return std::string();
        }
        if (!gdbmiFormatBreakpoint(str, bp, symbols, dataSpaces, verbose, errorMessage))
            return std::string();
        str << '}';
        if (humanReadable)
            str << '\n';
    }
    str << ']';
    return str.str();
}
Exemplo n.º 2
0
bool evaluateExpression(CIDebugControl *control, const std::string expression,
                        ULONG desiredType, DEBUG_VALUE *v, std::string *errorMessage)
{
    // Ensure we are in C++
    ULONG oldSyntax;
    HRESULT hr = control->GetExpressionSyntax(&oldSyntax);
    if (FAILED(hr)) {
        *errorMessage = msgEvaluateExpressionFailed(expression, msgDebugEngineComFailed("GetExpressionSyntax", hr));
        return false;
    }
    if (oldSyntax != DEBUG_EXPR_CPLUSPLUS) {
        HRESULT hr = control->SetExpressionSyntax(DEBUG_EXPR_CPLUSPLUS);
        if (FAILED(hr)) {
            *errorMessage = msgEvaluateExpressionFailed(expression, msgDebugEngineComFailed("SetExpressionSyntax", hr));
            return false;
        }
    }
    hr = control->Evaluate(expression.c_str(), desiredType, v, NULL);
    if (FAILED(hr)) {
        *errorMessage = msgEvaluateExpressionFailed(expression, msgDebugEngineComFailed("Evaluate", hr));
        return false;
    }
    if (oldSyntax != DEBUG_EXPR_CPLUSPLUS) {
        HRESULT hr = control->SetExpressionSyntax(oldSyntax);
        if (FAILED(hr)) {
            *errorMessage = msgEvaluateExpressionFailed(expression, msgDebugEngineComFailed("SetExpressionSyntax", hr));
            return false;
        }
    }
    return true;
}
Exemplo n.º 3
0
bool threadList(CIDebugSystemObjects *debugSystemObjects,
                CIDebugSymbols *debugSymbols,
                CIDebugControl *debugControl,
                CIDebugAdvanced *debugAdvanced,
                Threads* threads, ULONG *currentThreadId,
                std::string *errorMessage)
{
    threads->clear();
    ULONG threadCount;
    *currentThreadId = 0;
    // Get count
    HRESULT hr= debugSystemObjects->GetNumberThreads(&threadCount);
    if (FAILED(hr)) {
        *errorMessage= msgGetThreadsFailed(msgDebugEngineComFailed("GetNumberThreads", hr));
        return false;
    }
    // Get index of current
    if (!threadCount)
        return true;
    hr = debugSystemObjects->GetCurrentThreadId(currentThreadId);
    if (FAILED(hr)) {
        *errorMessage= msgGetThreadsFailed(msgDebugEngineComFailed("GetCurrentThreadId", hr));
        return false;
    }
    // Get Identifiers
    threads->reserve(threadCount);
    ULONG *ids = new ULONG[threadCount];
    ULONG *systemIds = new ULONG[threadCount];
    hr = debugSystemObjects->GetThreadIdsByIndex(0, threadCount, ids, systemIds);
    if (FAILED(hr)) {
        *errorMessage= msgGetThreadsFailed(msgDebugEngineComFailed("GetThreadIdsByIndex", hr));
        return false;
    }
    // Create entries
    static WCHAR name[256];
    for (ULONG i= 0; i < threadCount ; ++i) {
        const ULONG id = ids[i];
        Thread thread(id, systemIds[i]);
        // Thread name
        ULONG bytesReceived = 0;
        hr = debugAdvanced->GetSystemObjectInformation(DEBUG_SYSOBJINFO_THREAD_NAME_WIDE,
                                                       0, id, name,
                                                       sizeof(name), &bytesReceived);
        if (SUCCEEDED(hr) && bytesReceived)
            thread.name = name;
        threads->push_back(thread);
    }
    delete [] ids;
    delete [] systemIds;
    // Get frames and at all events,
    // restore current thread after switching frames.
    const bool framesOk = getThreadFrames(debugSymbols,
                                          debugSystemObjects,
                                          debugControl,
                                          threads, errorMessage);
    const bool restoreOk =setCurrentThread(debugSystemObjects, *currentThreadId, errorMessage);
    return framesOk && restoreOk;
}
Exemplo n.º 4
0
// Format stack as GDBMI
static StackFrames getStackTrace(CIDebugControl *debugControl,
                                 CIDebugSymbols *debugSymbols,
                                 unsigned maxFrames,
                                 bool *incomplete,
                                 std::string *errorMessage)
{

    if (maxFrames) {
        *incomplete = false;
    } else {
        *incomplete = true;
        return StackFrames();
    }
    // Ask for one more frame to find out whether it is a complete listing.
    const unsigned askedFrames = maxFrames + 1;
    DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[askedFrames];
    ULONG frameCount = 0;
    const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, askedFrames, &frameCount);
    if (FAILED(hr)) {
        delete [] frames;
        *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
        return StackFrames();
    }
    if (askedFrames == frameCount) {
        --frameCount;
        *incomplete = true;
    }
    StackFrames rc(frameCount, StackFrame());
    for (ULONG f = 0; f < frameCount; ++f)
        getFrame(debugSymbols, frames[f], &(rc[f]));
    delete [] frames;
    return rc;
}
Exemplo n.º 5
0
std::string memoryToBase64(CIDebugDataSpaces *ds, ULONG64 address, ULONG length, std::string *errorMessage)
{
    unsigned char *buffer = new unsigned char[length];
    std::fill(buffer, buffer + length, 0);
    ULONG received = 0;
    const HRESULT hr = ds->ReadVirtual(address, buffer, length, &received);
    if (FAILED(hr)) {
        delete [] buffer;
        std::ostringstream estr;
        estr << "Cannot read " << length << " bytes from " << address << ": "
                << msgDebugEngineComFailed("ReadVirtual", hr);
        *errorMessage = estr.str();
        return std::string();
    }
    if (received < length) {
        std::ostringstream estr;
        estr << "Warning: Received only " << received << " bytes of " << length << " requested at " << address << '.';
        *errorMessage = estr.str();
    }

    std::ostringstream str;
    base64Encode(str, buffer, length);
    delete [] buffer;
    return str.str();
}
Exemplo n.º 6
0
static bool gdbmiFormatBreakpoint(std::ostream &str,
                                  IDebugBreakpoint *bp,
                                  CIDebugSymbols *symbols  /* = 0 */,
                                  CIDebugDataSpaces *dataSpaces /* = 0 */,
                                  unsigned verbose, std::string *errorMessage)
{
    enum { BufSize = 512 };
    ULONG flags = 0;
    ULONG id = 0;
    if (SUCCEEDED(bp->GetId(&id)))
        str << ",id=\"" << id << '"';
    HRESULT hr = bp->GetFlags(&flags);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("GetFlags", hr);
        return false;
    }
    const bool deferred = (flags & DEBUG_BREAKPOINT_DEFERRED) != 0;
    formatGdbmiFlag(str, ",deferred", deferred);
    formatGdbmiFlag(str, ",enabled", (flags & DEBUG_BREAKPOINT_ENABLED) != 0);
    if (verbose) {
        formatGdbmiFlag(str, ",oneshot", (flags & DEBUG_BREAKPOINT_ONE_SHOT) != 0);
        str << ",flags=\"" << flags << '"';
        ULONG threadId = 0;
        if (SUCCEEDED(bp->GetMatchThreadId(&threadId))) // Fails if none set
            str << ",thread=\"" << threadId << '"';
        ULONG passCount = 0;
        if (SUCCEEDED(bp->GetPassCount(&passCount)))
            str << ",passcount=\"" << passCount << '"';
    }
    // Offset: Fails for deferred ones
    if (!deferred) {
        const std::pair<ULONG64, ULONG> memoryRange = breakPointMemoryRange(bp);
        if (memoryRange.first) {
            str << ",address=\"" << std::hex << std::showbase << memoryRange.first
                << std::dec << std::noshowbase << '"';
            // Resolve module to be specified in next run for speed-up.
            if (symbols) {
                const std::string module = moduleNameByOffset(symbols, memoryRange.first);
                if (!module.empty())
                    str << ",module=\"" << module << '"';
            } // symbols
            // Report the memory of watchpoints for comparing bitfields
            if (dataSpaces && memoryRange.second > 0) {
                str << ",size=\"" << memoryRange.second << '"';
                const std::wstring memoryHex = memoryToHexW(dataSpaces, memoryRange.first, memoryRange.second);
                if (!memoryHex.empty())
                    str << ",memory=\"" << gdbmiWStringFormat(memoryHex) << '"';
            }
        } // Got address
    } // !deferred
    // Expression
    if (verbose > 1) {
        char buf[BufSize];
        if (SUCCEEDED(bp->GetOffsetExpression(buf, BUFSIZ, 0)))
            str << ",expression=\"" << gdbmiStringFormat(buf) << '"';
    }
    return true;
}
Exemplo n.º 7
0
static inline bool setCurrentThread(CIDebugSystemObjects *debugSystemObjects,
                                    ULONG id, std::string *errorMessage)
{
    const HRESULT hr = debugSystemObjects->SetCurrentThreadId(id);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("SetCurrentThreadId", hr);
        return false;
    }
    return true;
}
Exemplo n.º 8
0
static inline bool getSymbolCount(CIDebugSymbolGroup *symbolGroup,
                                  ULONG *count,
                                  std::string *errorMessage)
{
    const HRESULT hr = symbolGroup->GetNumberSymbols(count);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("GetNumberSymbols", hr);
        return false;
    }
    return true;
}
Exemplo n.º 9
0
bool ExtensionContext::call(const std::string &functionCall,
                            std::wstring *output,
                            std::string *errorMessage)
{
    if (!m_creatorOutputCallback) {
        *errorMessage = "Attempt to issue a call with no output hooked.";
        return false;
    }
    // Set up arguments
    const std::string call = ".call " + functionCall;
    HRESULT hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, call.c_str(), DEBUG_EXECUTE_ECHO);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("Execute", hr);
        return 0;
    }
    // Execute in current thread. TODO: This must not crash, else we are in an inconsistent state
    // (need to call 'gh', etc.)
    hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "~. g", DEBUG_EXECUTE_ECHO);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("Execute", hr);
        return 0;
    }
    // Wait until finished
    startRecordingOutput();
    m_stateNotification = false;
    m_control->WaitForEvent(0, INFINITE);
    *output =  stopRecordingOutput();
    m_stateNotification = true;
    // Crude attempt at recovering from a crash: Issue 'gN' (go with exception not handled).
    const bool crashed = output->find(L"This exception may be expected and handled.") != std::string::npos;
    if (crashed) {
        m_stopReason.clear();
        m_stateNotification = false;
        hr = m_control->Execute(DEBUG_OUTCTL_ALL_CLIENTS, "~. gN", DEBUG_EXECUTE_ECHO);
        m_control->WaitForEvent(0, INFINITE);
        m_stateNotification = true;
        *errorMessage = "A crash occurred while calling: " + functionCall;
        return false;
    }
    return true;
}
Exemplo n.º 10
0
Modules getModules(CIDebugSymbols *syms, std::string *errorMessage)
{
    enum { BufSize = 1024 };

    char nameBuf[BufSize];
    char fileBuf[BufSize];

    ULONG Loaded;
    ULONG Unloaded;
    HRESULT hr = syms->GetNumberModules(&Loaded, &Unloaded);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("GetNumberModules", hr);
        return Modules();
    }
    const ULONG count = Loaded + Unloaded;
    Modules rc;
    rc.reserve(count);
    DEBUG_MODULE_PARAMETERS *parameters = new DEBUG_MODULE_PARAMETERS[count];
    hr = syms->GetModuleParameters(count, NULL, 0, parameters);
    if (FAILED(hr)) {
        delete [] parameters;
        *errorMessage = msgDebugEngineComFailed("GetModuleParameters", hr);
        return Modules();
    }

    for (ULONG m = 0; m < count; ++m) {
        Module module;
        module.base = parameters[m].Base;
        module.size = parameters[m].Size;
        module.deferred = parameters[m].Flags == DEBUG_SYMTYPE_DEFERRED;
        hr = syms->GetModuleNames(m, 0, fileBuf, BufSize, NULL,
                                  nameBuf, BufSize, NULL, NULL, NULL, NULL);
        if (FAILED(hr))
            break; // Fail silently should unloaded modules not work.
        module.name = nameBuf;
        module.image = fileBuf;
        rc.push_back(module);
    }
    return rc;
}
Exemplo n.º 11
0
bool getFrame(CIDebugSymbols *debugSymbols,
              CIDebugControl *debugControl,
              unsigned n, StackFrame *f, std::string *errorMessage)
{
    DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[n + 1];
    ULONG frameCount;
    const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, n + 1, &frameCount);
    if (FAILED(hr)) {
        delete [] frames;
        *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
        return false;
    }
    getFrame(debugSymbols, frames[n], f);
    delete [] frames;
    return true;
}
Exemplo n.º 12
0
static bool gdbmiFormatBreakpoint(std::ostream &str,
                                  IDebugBreakpoint *bp,
                                  CIDebugSymbols *symbols  /* = 0 */,
                                  unsigned verbose, std::string *errorMessage)
{
    enum { BufSize = 512 };
    ULONG64 offset = 0;
    ULONG flags = 0;
    ULONG id = 0;
    if (SUCCEEDED(bp->GetId(&id)))
        str << ",id=\"" << id << '"';
    HRESULT hr = bp->GetFlags(&flags);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("GetFlags", hr);
        return false;
    }
    const bool deferred = (flags & DEBUG_BREAKPOINT_DEFERRED) != 0;
    formatGdbmiFlag(str, ",deferred", deferred);
    formatGdbmiFlag(str, ",enabled", (flags & DEBUG_BREAKPOINT_ENABLED) != 0);
    if (verbose) {
        formatGdbmiFlag(str, ",oneshot", (flags & DEBUG_BREAKPOINT_ONE_SHOT) != 0);
        str << ",flags=\"" << flags << '"';
        ULONG threadId = 0;
        if (SUCCEEDED(bp->GetMatchThreadId(&threadId))) // Fails if none set
            str << ",thread=\"" << threadId << '"';
        ULONG passCount = 0;
        if (SUCCEEDED(bp->GetPassCount(&passCount)))
            str << ",passcount=\"" << passCount << '"';
    }
    // Offset: Fails for deferred ones
    if (!deferred && SUCCEEDED(bp->GetOffset(&offset))) {
        str << ",address=\"" << std::hex << std::showbase << offset
            << std::dec << std::noshowbase << '"';
        if (symbols) {
            const std::string module = moduleNameByOffset(symbols, offset);
            if (!module.empty())
                str << ",module=\"" << module << '"';
        }
    }
    // Expression
    if (verbose > 1) {
        char buf[BufSize];
        if (SUCCEEDED(bp->GetOffsetExpression(buf, BUFSIZ, 0)))
            str << ",expression=\"" << gdbmiStringFormat(buf) << '"';
    }
    return true;
}
Exemplo n.º 13
0
// Format stack as GDBMI
static StackFrames getStackTrace(CIDebugControl *debugControl,
                                 CIDebugSymbols *debugSymbols,
                                 unsigned maxFrames,
                                 std::string *errorMessage)
{

    if (!maxFrames)
        return StackFrames();
    DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[maxFrames];
    ULONG frameCount = 0;
    const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, maxFrames, &frameCount);
    if (FAILED(hr)) {
        delete [] frames;
        *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
    }
    StackFrames rc(frameCount, StackFrame());
    for (ULONG f = 0; f < frameCount; f++)
        getFrame(debugSymbols, frames[f], &(rc[f]));
    delete [] frames;
    return rc;
}
Exemplo n.º 14
0
bool SymbolGroup::getSymbolParameters(CIDebugSymbolGroup *symbolGroup,
                                      unsigned long start,
                                      unsigned long count,
                                      SymbolParameterVector *vec,
                                      std::string *errorMessage)
{
    if (!count) {
        vec->clear();
        return true;
    }
    // Trim the count to the maximum count available. When expanding elements
    // and passing SubElements as count, SubElements might be an estimate that
    // is too large and triggers errors.
    ULONG totalCount;
    if (!getSymbolCount(symbolGroup, &totalCount, errorMessage))
        return false;
    if (start >= totalCount) {
        std::ostringstream str;
        str << "SymbolGroup::getSymbolParameters: Start parameter "
            << start << " beyond total " << totalCount << '.';
        *errorMessage = str.str();
        return  false;
    }
    if (start + count > totalCount)
        count = totalCount - start;
    // Get parameters.
    vec->resize(count);
    const HRESULT hr = symbolGroup->GetSymbolParameters(start, count, &(*vec->begin()));
    if (FAILED(hr)) {
        std::ostringstream str;
        str << "SymbolGroup::getSymbolParameters failed for index=" << start << ", count=" << count
            << ": " << msgDebugEngineComFailed("GetSymbolParameters", hr);
        *errorMessage = str.str();
        return false;
    }
    return true;
}
Exemplo n.º 15
0
Registers getRegisters(CIDebugRegisters *regs,
                       unsigned flags,
                       std::string *errorMessage)
{
    enum { bufSize= 128 };
    WCHAR buf[bufSize];

    ULONG registerCount = 0;
    HRESULT hr = regs->GetNumberRegisters(&registerCount);
    if (FAILED(hr)) {
        *errorMessage = msgDebugEngineComFailed("GetNumberRegisters", hr);
        return Registers();
    }
    ULONG pseudoRegisterCount = 0;
    if (flags & IncludePseudoRegisters) {
        hr = regs->GetNumberPseudoRegisters(&pseudoRegisterCount);
        if (FAILED(hr)) {
            *errorMessage = msgDebugEngineComFailed("GetNumberPseudoRegisters", hr);
            return Registers();
        }
    }

    Registers rc;
    rc.reserve(registerCount + pseudoRegisterCount);

    // Standard registers
    DEBUG_REGISTER_DESCRIPTION description;
    DEBUG_VALUE value;
    for (ULONG r = 0; r < registerCount; ++r) {
        hr = regs->GetDescriptionWide(r, buf, bufSize, NULL, &description);
        if (FAILED(hr)) {
            *errorMessage = msgDebugEngineComFailed("GetDescription", hr);
            return Registers();
        }
        hr = regs->GetValue(r, &value);
        if (FAILED(hr)) {
            *errorMessage = msgDebugEngineComFailed("GetValue", hr);
            return Registers();
        }
        const bool isSubRegister = (description.Flags & DEBUG_REGISTER_SUB_REGISTER);
        if (!isSubRegister || (flags & IncludeSubRegisters)) {
            Register reg;
            reg.name = buf;
            reg.description = registerDescription(description);
            reg.subRegister = isSubRegister;
            reg.value = value;
            rc.push_back(reg);
        }
    }

    // Pseudo
    for (ULONG r = 0; r < pseudoRegisterCount; ++r) {
        ULONG type;
        hr = regs->GetPseudoDescriptionWide(r, buf, bufSize, NULL, NULL, &type);
        if (FAILED(hr))
            continue; // Fails for some pseudo registers
        hr = regs->GetValue(r, &value);
        if (FAILED(hr))
            continue; // Fails for some pseudo registers
        Register reg;
        reg.pseudoRegister = true;
        reg.name = buf;
        reg.description = valueType(type);
        reg.value = value;
        rc.push_back(reg);
    }
    return rc;
}