void ExtensionContext::notifyIdleCommand(CIDebugClient *client) { discardSymbolGroup(); if (m_stateNotification) { // Format full thread and stack info along with completed stop reasons. std::string errorMessage; ExtensionCommandContext exc(client); const StopReasonMap stopReasons = completeStopReasons(client, m_stopReason, executionStatus()); // Format std::ostringstream str; formatGdbmiHash(str, stopReasons, false); const std::string threadInfo = gdbmiThreadList(exc.systemObjects(), exc.symbols(), exc.control(), exc.advanced(), &errorMessage); if (threadInfo.empty()) { str << ",threaderror=" << gdbmiStringFormat(errorMessage); } else { str << ",threads=" << threadInfo; } const std::string stackInfo = gdbmiStack(exc.control(), exc.symbols(), maxStackFrames, false, &errorMessage); if (stackInfo.empty()) { str << ",stackerror=" << gdbmiStringFormat(errorMessage); } else { str << ",stack=" << stackInfo; } str << '}'; reportLong('E', 0, "session_idle", str.str()); } m_stopReason.clear(); }
std::string gdbmiModules(CIDebugSymbols *syms, bool humanReadable, std::string *errorMessage) { const Modules modules = getModules(syms, errorMessage); if (modules.empty()) return std::string(); std::ostringstream str; str << '[' << std::hex << std::showbase; const Modules::size_type size = modules.size(); for (Modules::size_type m = 0; m < size; ++m) { const Module &module = modules.at(m); if (m) str << ','; str << "{name=\"" << module.name << "\",image=\"" << gdbmiStringFormat(module.image) << "\",start=\"" << module.base << "\",end=\"" << (module.base + module.size - 1) << '"'; if (module.deferred) str << "{deferred=\"true\""; str << '}'; if (humanReadable) str << '\n'; } str << ']'; return str.str(); }
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; }
// Format a map as a GDBMI hash {key="value",..} void formatGdbmiHash(std::ostream &os, const std::map<std::string, std::string> &m, bool closeHash) { typedef std::map<std::string, std::string>::const_iterator It; const It begin = m.begin(); const It cend = m.end(); os << '{'; for (It it = begin; it != cend; ++it) { if (it != begin) os << ','; os << it->first << "=\"" << gdbmiStringFormat(it->second) << '"'; } if (closeHash) os << '}'; }
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; }