summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libs/qtcreatorcdbext/common.cpp18
-rw-r--r--src/libs/qtcreatorcdbext/common.h1
-rw-r--r--src/libs/qtcreatorcdbext/eventcallback.cpp2
-rw-r--r--src/libs/qtcreatorcdbext/extensioncontext.cpp12
-rw-r--r--src/libs/qtcreatorcdbext/extensioncontext.h1
-rw-r--r--src/libs/qtcreatorcdbext/gdbmihelpers.cpp81
-rw-r--r--src/libs/qtcreatorcdbext/gdbmihelpers.h7
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbext.def1
-rw-r--r--src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp30
-rw-r--r--src/libs/qtcreatorcdbext/symbolgroupvalue.cpp16
10 files changed, 155 insertions, 14 deletions
diff --git a/src/libs/qtcreatorcdbext/common.cpp b/src/libs/qtcreatorcdbext/common.cpp
index 18f2973a22..097264a446 100644
--- a/src/libs/qtcreatorcdbext/common.cpp
+++ b/src/libs/qtcreatorcdbext/common.cpp
@@ -122,3 +122,21 @@ ULONG currentProcessId(CIDebugClient *client)
return currentProcessId(sysObjects.data());
return 0;
}
+
+std::string moduleNameByOffset(CIDebugSymbols *symbols, ULONG64 offset)
+{
+ enum { BufSize = 512 };
+ ULONG index = 0;
+ ULONG64 base = 0;
+ // Convert module base address to module index
+ HRESULT hr = symbols->GetModuleByOffset(offset, 0, &index, &base);
+ if (FAILED(hr))
+ return std::string();
+ // Obtain module name
+ char buf[BufSize];
+ buf[0] = '\0';
+ hr = symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, index, base, buf, BufSize, 0);
+ if (FAILED(hr))
+ return std::string();
+ return std::string(buf);
+}
diff --git a/src/libs/qtcreatorcdbext/common.h b/src/libs/qtcreatorcdbext/common.h
index f13a880a34..4d4075ab5b 100644
--- a/src/libs/qtcreatorcdbext/common.h
+++ b/src/libs/qtcreatorcdbext/common.h
@@ -74,6 +74,7 @@ ULONG currentThreadId(IDebugSystemObjects *sysObjects);
ULONG currentThreadId(CIDebugClient *client);
ULONG currentProcessId(IDebugSystemObjects *sysObjects);
ULONG currentProcessId(CIDebugClient *client);
+std::string moduleNameByOffset(CIDebugSymbols *symbols, ULONG64 offset);
#ifdef QTC_TRACE
# define QTC_TRACE_IN dprintf(">%s\n", __FUNCTION__);
diff --git a/src/libs/qtcreatorcdbext/eventcallback.cpp b/src/libs/qtcreatorcdbext/eventcallback.cpp
index e2799a959e..d04ad11a57 100644
--- a/src/libs/qtcreatorcdbext/eventcallback.cpp
+++ b/src/libs/qtcreatorcdbext/eventcallback.cpp
@@ -172,7 +172,7 @@ STDMETHODIMP EventCallback::Exception(
std::ostringstream str;
formatGdbmiHash(str, parameters);
- ExtensionContext::instance().setStopReason(parameters, "exception");
+ ExtensionContext::instance().setStopReason(parameters, ExtensionContext::breakPointStopReasonC);
ExtensionContext::instance().report('E', 0, 0, "exception", "%s", str.str().c_str());
return m_wrapped ? m_wrapped->Exception(Ex, FirstChance) : S_OK;
}
diff --git a/src/libs/qtcreatorcdbext/extensioncontext.cpp b/src/libs/qtcreatorcdbext/extensioncontext.cpp
index 8d5b07affd..965aac037a 100644
--- a/src/libs/qtcreatorcdbext/extensioncontext.cpp
+++ b/src/libs/qtcreatorcdbext/extensioncontext.cpp
@@ -45,6 +45,7 @@
WINDBG_EXTENSION_APIS ExtensionApis = {sizeof(WINDBG_EXTENSION_APIS), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const char *ExtensionContext::stopReasonKeyC = "reason";
+const char *ExtensionContext::breakPointStopReasonC = "breakpoint";
ExtensionContext::ExtensionContext() :
m_hookedClient(0),
@@ -197,6 +198,17 @@ void ExtensionContext::notifyIdleCommand(CIDebugClient *client)
} else {
str << ",stack=" << stackInfo;
}
+ // Report breakpoints
+ const StopReasonMap::const_iterator rit = stopReasons.find(stopReasonKeyC);
+ if (rit != stopReasons.end() && rit->second == breakPointStopReasonC) {
+ const std::string breakpoints = gdbmiBreakpoints(exc.control(), exc.symbols(),
+ false, false, &errorMessage);
+ if (breakpoints.empty()) {
+ str << ",breakpointserror=" << gdbmiStringFormat(errorMessage);
+ } else {
+ str << ",breakpoints=" << breakpoints;
+ }
+ }
str << '}';
reportLong('E', 0, "session_idle", str.str());
}
diff --git a/src/libs/qtcreatorcdbext/extensioncontext.h b/src/libs/qtcreatorcdbext/extensioncontext.h
index abeeb2cbe7..f844783a59 100644
--- a/src/libs/qtcreatorcdbext/extensioncontext.h
+++ b/src/libs/qtcreatorcdbext/extensioncontext.h
@@ -56,6 +56,7 @@ public:
// Key used to report stop reason in StopReasonMap
static const char *stopReasonKeyC;
+ static const char *breakPointStopReasonC; // pre-defined stop reasons
// Map of parameters reported with the next stop as GDBMI
typedef std::map<std::string, std::string> StopReasonMap;
diff --git a/src/libs/qtcreatorcdbext/gdbmihelpers.cpp b/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
index 6826df9b83..e3c45f178e 100644
--- a/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
+++ b/src/libs/qtcreatorcdbext/gdbmihelpers.cpp
@@ -670,3 +670,84 @@ std::string widgetAt(const SymbolGroupValueContext &ctx, int x, int y, std::stri
wOutput.erase(sepPos, 1);
return wStringToString(wOutput);
}
+
+static inline void formatGdbmiFlag(std::ostream &str, const char *name, bool v)
+{
+ str << name << "=\"" << (v ? "true" : "false") << '"';
+}
+
+static bool gdbmiFormatBreakpoint(std::ostream &str,
+ IDebugBreakpoint *bp,
+ CIDebugSymbols *symbols /* = 0 */,
+ bool verbose, std::string *errorMessage)
+{
+ enum { BufSize = 512 };
+ ULONG64 offset = 0;
+ ULONG flags = 0;
+ 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);
+ if (verbose) {
+ formatGdbmiFlag(str, ",enabled", (flags & DEBUG_BREAKPOINT_ENABLED) != 0);
+ 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
+ char buf[BufSize];
+ if (SUCCEEDED(bp->GetOffsetExpression(buf, BUFSIZ, 0)))
+ str << ",expression=\"" << gdbmiStringFormat(buf) << '"';
+ return true;
+}
+
+// Format breakpoints as GDBMI
+std::string gdbmiBreakpoints(CIDebugControl *ctrl,
+ CIDebugSymbols *symbols /* = 0 */,
+ bool humanReadable, bool 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 << "{id=\"" << 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, verbose, errorMessage))
+ return std::string();
+ str << '}';
+ if (humanReadable)
+ str << '\n';
+ }
+ str << ']';
+ return str.str();
+}
diff --git a/src/libs/qtcreatorcdbext/gdbmihelpers.h b/src/libs/qtcreatorcdbext/gdbmihelpers.h
index 849a05faeb..54c475bd9e 100644
--- a/src/libs/qtcreatorcdbext/gdbmihelpers.h
+++ b/src/libs/qtcreatorcdbext/gdbmihelpers.h
@@ -113,6 +113,13 @@ Modules getModules(CIDebugSymbols *syms, std::string *errorMessage);
// Format modules as GDBMI
std::string gdbmiModules(CIDebugSymbols *syms, bool humanReadable, std::string *errorMessage);
+// Format breakpoints as GDBMI
+std::string gdbmiBreakpoints(CIDebugControl *ctrl,
+ CIDebugSymbols *symbols /* = 0 */,
+ bool humanReadable,
+ bool verbose,
+ std::string *errorMessage);
+
/* Helpers for registers */
struct Register
{
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
index bc91011c9b..ab4cf4ea5c 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbext.def
@@ -21,4 +21,5 @@ test
stack
addwatch
widgetat
+breakpoints
KnownStructOutput
diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
index 45dccd50d9..59d6a3c2f2 100644
--- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
+++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
@@ -101,6 +101,7 @@ enum Command {
CmdShutdownex,
CmdAddWatch,
CmdWidgetAt,
+ CmdBreakPoints,
CmdTest
};
@@ -158,6 +159,7 @@ static const CommandDescription commandDescriptions[] = {
{"shutdownex","Unhooks output callbacks.\nNeeds to be called explicitly only in case of remote debugging.",""},
{"addwatch","Add watch expression","<iname> <expression>"},
{"widgetat","Return address of widget at position","<x> <y>"},
+{"breakpoints","List breakpoints with modules","[-h] [-v]"},
{"test","Testing command","-T type | -w watch-expression"}
};
@@ -984,6 +986,34 @@ extern "C" HRESULT CALLBACK widgetat(CIDebugClient *client, PCSTR argsIn)
return S_OK;
}
+extern "C" HRESULT CALLBACK breakpoints(CIDebugClient *client, PCSTR argsIn)
+{
+ ExtensionCommandContext exc(client);
+ int token;
+ std::string errorMessage;
+ bool humanReadable = false;
+ bool verbose = false;
+ StringList tokens = commandTokens<StringList>(argsIn, &token);
+ while (!tokens.empty() && tokens.front().size() == 2 && tokens.front().at(0) == '-') {
+ switch (tokens.front().at(1)) {
+ case 'h':
+ humanReadable = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ }
+ tokens.pop_front();
+ }
+ const std::string bp = gdbmiBreakpoints(exc.control(), exc.symbols(), humanReadable, verbose, &errorMessage);
+ if (bp.empty()) {
+ ExtensionContext::instance().report('N', token, 0, "breakpoints", errorMessage.c_str());
+ } else {
+ ExtensionContext::instance().reportLong('R', token, "breakpoints", bp);
+ }
+ return S_OK;
+}
+
extern "C" HRESULT CALLBACK test(CIDebugClient *client, PCSTR argsIn)
{
enum Mode { Invalid, TestType, TestFixWatchExpression };
diff --git a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
index 3654e42a43..660cc837d1 100644
--- a/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
+++ b/src/libs/qtcreatorcdbext/symbolgroupvalue.cpp
@@ -600,20 +600,10 @@ std::string SymbolGroupValue::resolveType(const std::string &typeIn,
const ULONG typeSize = Ioctl(IG_GET_TYPE_SIZE, &symParameters, symParameters.size);
if (!typeSize || !symParameters.ModBase) // Failed?
return stripped;
- ULONG index = 0;
- ULONG64 base = 0;
- // Convert module base address to module index
- HRESULT hr = ctx.symbols->GetModuleByOffset(symParameters.ModBase, 0, &index, &base);
- if (FAILED(hr))
+ const std::string module = moduleNameByOffset(ctx.symbols, symParameters.ModBase);
+ if (module.empty())
return stripped;
- // Obtain module name
- char buf[BufSize];
- buf[0] = '\0';
- hr = ctx.symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, index, base, buf, BufSize, 0);
- if (FAILED(hr))
- return stripped;
-
- std::string rc = buf;
+ std::string rc = module;
rc.push_back('!');
rc += stripped;
return rc;