forked from qt-creator/qt-creator
Debugger[New CDB]: Split up long extension messages.
To accommodate the limitation of output line width of CDB.
This commit is contained in:
@@ -173,7 +173,7 @@ STDMETHODIMP EventCallback::Exception(
|
|||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
formatGdbmiHash(str, parameters);
|
formatGdbmiHash(str, parameters);
|
||||||
ExtensionContext::instance().setStopReason(parameters, "exception");
|
ExtensionContext::instance().setStopReason(parameters, "exception");
|
||||||
ExtensionContext::instance().report('E', 0, "exception", "%s", str.str().c_str());
|
ExtensionContext::instance().report('E', 0, 0, "exception", "%s", str.str().c_str());
|
||||||
return m_wrapped ? m_wrapped->Exception(Ex, FirstChance) : S_OK;
|
return m_wrapped ? m_wrapped->Exception(Ex, FirstChance) : S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ STDMETHODIMP EventCallback::ExitProcess(
|
|||||||
__in ULONG ExitCode
|
__in ULONG ExitCode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ExtensionContext::instance().report('E', 0, eventContextC, "Process exited (%lu)",
|
ExtensionContext::instance().report('E', 0, 0, eventContextC, "Process exited (%lu)",
|
||||||
ExitCode);
|
ExitCode);
|
||||||
const HRESULT hr = m_wrapped ? m_wrapped->ExitProcess(ExitCode) : S_OK;
|
const HRESULT hr = m_wrapped ? m_wrapped->ExitProcess(ExitCode) : S_OK;
|
||||||
// Remotely debugged process exited, there is no session-inactive notification.
|
// Remotely debugged process exited, there is no session-inactive notification.
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
#include "outputcallback.h"
|
#include "outputcallback.h"
|
||||||
#include "stringutils.h"
|
#include "stringutils.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// wdbgexts.h declares 'extern WINDBG_EXTENSION_APIS ExtensionApis;'
|
// wdbgexts.h declares 'extern WINDBG_EXTENSION_APIS ExtensionApis;'
|
||||||
// and it's inline functions rely on its existence.
|
// and it's inline functions rely on its existence.
|
||||||
WINDBG_EXTENSION_APIS ExtensionApis = {sizeof(WINDBG_EXTENSION_APIS), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
WINDBG_EXTENSION_APIS ExtensionApis = {sizeof(WINDBG_EXTENSION_APIS), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
@@ -167,7 +169,7 @@ void ExtensionContext::notifyIdle()
|
|||||||
// Format
|
// Format
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
formatGdbmiHash(str, stopReasons);
|
formatGdbmiHash(str, stopReasons);
|
||||||
report('E', 0, "session_idle", "%s", str.str().c_str());
|
reportLong('E', 0, "session_idle", str.str());
|
||||||
m_stopReason.clear();
|
m_stopReason.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,16 +178,16 @@ void ExtensionContext::notifyState(ULONG Notify)
|
|||||||
const ULONG ex = executionStatus();
|
const ULONG ex = executionStatus();
|
||||||
switch (Notify) {
|
switch (Notify) {
|
||||||
case DEBUG_NOTIFY_SESSION_ACTIVE:
|
case DEBUG_NOTIFY_SESSION_ACTIVE:
|
||||||
report('E', 0, "session_active", "%u", ex);
|
report('E', 0, 0, "session_active", "%u", ex);
|
||||||
break;
|
break;
|
||||||
case DEBUG_NOTIFY_SESSION_ACCESSIBLE: // Meaning, commands accepted
|
case DEBUG_NOTIFY_SESSION_ACCESSIBLE: // Meaning, commands accepted
|
||||||
report('E', 0, "session_accessible", "%u", ex);
|
report('E', 0, 0, "session_accessible", "%u", ex);
|
||||||
break;
|
break;
|
||||||
case DEBUG_NOTIFY_SESSION_INACCESSIBLE:
|
case DEBUG_NOTIFY_SESSION_INACCESSIBLE:
|
||||||
report('E', 0, "session_inaccessible", "%u", ex);
|
report('E', 0, 0, "session_inaccessible", "%u", ex);
|
||||||
break;
|
break;
|
||||||
case DEBUG_NOTIFY_SESSION_INACTIVE:
|
case DEBUG_NOTIFY_SESSION_INACTIVE:
|
||||||
report('E', 0, "session_inactive", "%u", ex);
|
report('E', 0, 0, "session_inactive", "%u", ex);
|
||||||
discardSymbolGroup();
|
discardSymbolGroup();
|
||||||
// We lost the debuggee, at this point restore output.
|
// We lost the debuggee, at this point restore output.
|
||||||
if (ex & DEBUG_STATUS_NO_DEBUGGEE)
|
if (ex & DEBUG_STATUS_NO_DEBUGGEE)
|
||||||
@@ -218,12 +220,13 @@ void ExtensionContext::discardSymbolGroup()
|
|||||||
m_symbolGroup.reset();
|
m_symbolGroup.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtensionContext::report(char code, int token, const char *serviceName, PCSTR Format, ...)
|
bool ExtensionContext::report(char code, int token, int remainingChunks, const char *serviceName, PCSTR Format, ...)
|
||||||
{
|
{
|
||||||
if (!isInitialized())
|
if (!isInitialized())
|
||||||
return false;
|
return false;
|
||||||
// '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
|
// '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
|
||||||
m_control->Output(DEBUG_OUTPUT_NORMAL, "<qtcreatorcdbext>|%c|%d|%s|", code, token, serviceName);
|
m_control->Output(DEBUG_OUTPUT_NORMAL, "<qtcreatorcdbext>|%c|%d|%d|%s|",
|
||||||
|
code, token, remainingChunks, serviceName);
|
||||||
va_list Args;
|
va_list Args;
|
||||||
va_start(Args, Format);
|
va_start(Args, Format);
|
||||||
m_control->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
|
m_control->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
|
||||||
@@ -232,6 +235,26 @@ bool ExtensionContext::report(char code, int token, const char *serviceName, PCS
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExtensionContext::reportLong(char code, int token, const char *serviceName, const std::string &message)
|
||||||
|
{
|
||||||
|
const std::string::size_type size = message.size();
|
||||||
|
if (size < outputChunkSize)
|
||||||
|
return report(code, token, 0, serviceName, "%s", message.c_str());
|
||||||
|
// Split up
|
||||||
|
std::string::size_type chunkCount = size / outputChunkSize;
|
||||||
|
if (size % outputChunkSize)
|
||||||
|
chunkCount++;
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
for (int remaining = int(chunkCount) - 1; remaining >= 0 ; remaining--) {
|
||||||
|
std::string::size_type nextPos = pos + outputChunkSize; // No consistent std::min/std::max in VS8/10
|
||||||
|
if (nextPos > size)
|
||||||
|
nextPos = size;
|
||||||
|
report(code, token, remaining, serviceName, "%s", message.substr(pos, nextPos - pos).c_str());
|
||||||
|
pos = nextPos;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Exported C-functions
|
// Exported C-functions
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
|||||||
@@ -68,11 +68,17 @@ public:
|
|||||||
// Undo hooking.
|
// Undo hooking.
|
||||||
void unhookCallbacks();
|
void unhookCallbacks();
|
||||||
|
|
||||||
// Report output in standardized format understood by Qt Creator.
|
// CDB has a limitation on output, so, long messages need to be split (empirically ca 10KB)
|
||||||
// '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
|
static const size_t outputChunkSize = 10240;
|
||||||
// Char code is 'R' command reply, 'N' command fail, 'E' event notification
|
/* Report output in standardized format understood by Qt Creator.
|
||||||
bool report(char code, int token, const char *serviceName, PCSTR Format, ...);
|
* '<qtcreatorcdbext>|R|<token>|remainingChunks|<serviceName>|<one-line-output>'.
|
||||||
|
* Char code is 'R' command reply, 'N' command fail, 'E' event notification,
|
||||||
|
* 'X' exception, error. If the message is larger than outputChunkSize,
|
||||||
|
* it needs to be split up in chunks, remainingChunks needs to indicate the number
|
||||||
|
* of the following chunks (0 for just one chunk). */
|
||||||
|
bool report(char code, int remainingChunks, int token, const char *serviceName, PCSTR Format, ...);
|
||||||
|
// Convenience for reporting potentially long messages in chunks
|
||||||
|
bool reportLong(char code, int token, const char *serviceName, const std::string &message);
|
||||||
ULONG executionStatus() const;
|
ULONG executionStatus() const;
|
||||||
// Call from notify handler, tell engine about state.
|
// Call from notify handler, tell engine about state.
|
||||||
void notifyState(ULONG Notify);
|
void notifyState(ULONG Notify);
|
||||||
|
|||||||
@@ -97,6 +97,6 @@ STDMETHODIMP OutputCallback::Output(
|
|||||||
// Base encode as GDBMI is not really made for wide chars
|
// Base encode as GDBMI is not really made for wide chars
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
base64Encode(str, reinterpret_cast<const unsigned char *>(text), sizeof(wchar_t) * std::wcslen(text));
|
base64Encode(str, reinterpret_cast<const unsigned char *>(text), sizeof(wchar_t) * std::wcslen(text));
|
||||||
ExtensionContext::instance().report('E', 0, "debuggee_output", str.str().c_str());
|
ExtensionContext::instance().report('E', 0, 0, "debuggee_output", str.str().c_str());
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,9 +235,9 @@ extern "C" HRESULT CALLBACK pid(CIDebugClient *client, PCSTR args)
|
|||||||
commandTokens<StringList>(args, &token);
|
commandTokens<StringList>(args, &token);
|
||||||
|
|
||||||
if (const ULONG pid = currentProcessId(client)) {
|
if (const ULONG pid = currentProcessId(client)) {
|
||||||
ExtensionContext::instance().report('R', token, "pid", "%u", pid);
|
ExtensionContext::instance().report('R', token, 0, "pid", "%u", pid);
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('N', token, "pid", "0");
|
ExtensionContext::instance().report('N', token, 0, "pid", "0");
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -277,7 +277,7 @@ extern "C" HRESULT CALLBACK expandlocals(CIDebugClient *client, PCSTR args)
|
|||||||
symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, &errorMessage);
|
symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), frame, &errorMessage);
|
||||||
|
|
||||||
if (!symGroup) {
|
if (!symGroup) {
|
||||||
ExtensionContext::instance().report('N', token, "expandlocals", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "expandlocals", errorMessage.c_str());
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ extern "C" HRESULT CALLBACK expandlocals(CIDebugClient *client, PCSTR args)
|
|||||||
symGroup->expandListRunComplexDumpers(inames, SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), &errorMessage) :
|
symGroup->expandListRunComplexDumpers(inames, SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()), &errorMessage) :
|
||||||
symGroup->expandList(inames, &errorMessage);
|
symGroup->expandList(inames, &errorMessage);
|
||||||
|
|
||||||
ExtensionContext::instance().report('R', token, "expandlocals", "%u/%u %s",
|
ExtensionContext::instance().report('R', token, 0, "expandlocals", "%u/%u %s",
|
||||||
succeeded, unsigned(inames.size()), errorMessage.c_str());
|
succeeded, unsigned(inames.size()), errorMessage.c_str());
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -403,9 +403,9 @@ extern "C" HRESULT CALLBACK locals(CIDebugClient *client, PCSTR args)
|
|||||||
int token;
|
int token;
|
||||||
const std::string output = commmandLocals(exc, args, &token, &errorMessage);
|
const std::string output = commmandLocals(exc, args, &token, &errorMessage);
|
||||||
if (output.empty()) {
|
if (output.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "locals", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "locals", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "locals", "%s", output.c_str());
|
ExtensionContext::instance().reportLong('R', token, "locals", output);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -454,9 +454,9 @@ extern "C" HRESULT CALLBACK dumplocal(CIDebugClient *client, PCSTR argsIn)
|
|||||||
int token = 0;
|
int token = 0;
|
||||||
const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
|
const std::string value = dumplocalHelper(exc,argsIn, &token, &errorMessage);
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "dumplocal", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "dumplocal", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "dumplocal", value.c_str());
|
ExtensionContext::instance().reportLong('R', token, "dumplocal", value);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -483,9 +483,9 @@ extern "C" HRESULT CALLBACK typecast(CIDebugClient *client, PCSTR args)
|
|||||||
errorMessage = singleLineUsage(commandDescriptions[CmdTypecast]);
|
errorMessage = singleLineUsage(commandDescriptions[CmdTypecast]);
|
||||||
}
|
}
|
||||||
if (symGroup != 0 && symGroup->typeCast(iname, desiredType, &errorMessage)) {
|
if (symGroup != 0 && symGroup->typeCast(iname, desiredType, &errorMessage)) {
|
||||||
ExtensionContext::instance().report('R', token, "typecast", "OK");
|
ExtensionContext::instance().report('R', token, 0, "typecast", "OK");
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('N', token, "typecast", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "typecast", errorMessage.c_str());
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -513,9 +513,9 @@ extern "C" HRESULT CALLBACK addsymbol(CIDebugClient *client, PCSTR args)
|
|||||||
errorMessage = singleLineUsage(commandDescriptions[CmdAddsymbol]);
|
errorMessage = singleLineUsage(commandDescriptions[CmdAddsymbol]);
|
||||||
}
|
}
|
||||||
if (symGroup != 0 && symGroup->addSymbol(name, iname, &errorMessage)) {
|
if (symGroup != 0 && symGroup->addSymbol(name, iname, &errorMessage)) {
|
||||||
ExtensionContext::instance().report('R', token, "addsymbol", "OK");
|
ExtensionContext::instance().report('R', token, 0, "addsymbol", "OK");
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('N', token, "addsymbol", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "addsymbol", errorMessage.c_str());
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -554,9 +554,9 @@ extern "C" HRESULT CALLBACK assign(CIDebugClient *client, PCSTR argsIn)
|
|||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
ExtensionContext::instance().report('R', token, "assign", "Ok");
|
ExtensionContext::instance().report('R', token, 0, "assign", "Ok");
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('N', token, "assign", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str());
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -578,9 +578,9 @@ extern "C" HRESULT CALLBACK threads(CIDebugClient *client, PCSTR argsIn)
|
|||||||
exc.advanced(),
|
exc.advanced(),
|
||||||
&errorMessage);
|
&errorMessage);
|
||||||
if (gdbmi.empty()) {
|
if (gdbmi.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "threads", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "threads", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "threads", gdbmi.c_str());
|
ExtensionContext::instance().reportLong('R', token, "threads", gdbmi);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -598,9 +598,9 @@ extern "C" HRESULT CALLBACK registers(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
|
const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
|
||||||
const std::string regs = gdbmiRegisters(exc.registers(), exc.control(), humanReadable, IncludePseudoRegisters, &errorMessage);
|
const std::string regs = gdbmiRegisters(exc.registers(), exc.control(), humanReadable, IncludePseudoRegisters, &errorMessage);
|
||||||
if (regs.empty()) {
|
if (regs.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "registers", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "registers", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "registers", regs.c_str());
|
ExtensionContext::instance().reportLong('R', token, "registers", regs);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -618,9 +618,9 @@ extern "C" HRESULT CALLBACK modules(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
|
const bool humanReadable = !tokens.empty() && tokens.front() == "-h";
|
||||||
const std::string modules = gdbmiModules(exc.symbols(), humanReadable, &errorMessage);
|
const std::string modules = gdbmiModules(exc.symbols(), humanReadable, &errorMessage);
|
||||||
if (modules.empty()) {
|
if (modules.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "modules", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "modules", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "modules", modules.c_str());
|
ExtensionContext::instance().reportLong('R', token, "modules", modules);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -671,11 +671,11 @@ extern "C" HRESULT CALLBACK memory(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (memory.empty()) {
|
if (memory.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "memory", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "memory", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "memory", memory.c_str());
|
ExtensionContext::instance().reportLong('R', token, "memory", memory);
|
||||||
if (!errorMessage.empty())
|
if (!errorMessage.empty())
|
||||||
ExtensionContext::instance().report('W', token, "memory", errorMessage.c_str());
|
ExtensionContext::instance().report('W', token, 0, "memory", errorMessage.c_str());
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -704,9 +704,9 @@ extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
maxFrames, humanReadable, &errorMessage);
|
maxFrames, humanReadable, &errorMessage);
|
||||||
|
|
||||||
if (stack.empty()) {
|
if (stack.empty()) {
|
||||||
ExtensionContext::instance().report('N', token, "stack", errorMessage.c_str());
|
ExtensionContext::instance().report('N', token, 0, "stack", errorMessage.c_str());
|
||||||
} else {
|
} else {
|
||||||
ExtensionContext::instance().report('R', token, "stack", stack.c_str());
|
ExtensionContext::instance().reportLong('R', token, "stack", stack);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -950,7 +950,7 @@ bool SymbolGroupNode::expand(std::string *errorMessage)
|
|||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
*errorMessage = msgExpandFailed(name(), absoluteFullIName(), m_index, msgDebugEngineComFailed("ExpandSymbol", hr));
|
*errorMessage = msgExpandFailed(name(), absoluteFullIName(), m_index, msgDebugEngineComFailed("ExpandSymbol", hr));
|
||||||
ExtensionContext::instance().report('X', 0, "Error", "%s", errorMessage->c_str());
|
ExtensionContext::instance().report('X', 0, 0, "Error", "%s", errorMessage->c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SymbolGroup::SymbolParameterVector parameters;
|
SymbolGroup::SymbolParameterVector parameters;
|
||||||
@@ -1020,12 +1020,12 @@ SymbolGroupNode *SymbolGroupNode::addSymbolByName(const std::string &name,
|
|||||||
HRESULT hr = m_symbolGroup->debugSymbolGroup()->AddSymbol(name.c_str(), &index);
|
HRESULT hr = m_symbolGroup->debugSymbolGroup()->AddSymbol(name.c_str(), &index);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
*errorMessage = msgCannotAddSymbol(name, msgDebugEngineComFailed("AddSymbol", hr));
|
*errorMessage = msgCannotAddSymbol(name, msgDebugEngineComFailed("AddSymbol", hr));
|
||||||
ExtensionContext::instance().report('X', 0, "Error", "%s", errorMessage->c_str());
|
ExtensionContext::instance().report('X', 0, 0, "Error", "%s", errorMessage->c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (index == DEBUG_ANY_ID) { // Occasionally happens for unknown or 'complicated' types
|
if (index == DEBUG_ANY_ID) { // Occasionally happens for unknown or 'complicated' types
|
||||||
*errorMessage = msgCannotAddSymbol(name, "DEBUG_ANY_ID was returned as symbol index by AddSymbol.");
|
*errorMessage = msgCannotAddSymbol(name, "DEBUG_ANY_ID was returned as symbol index by AddSymbol.");
|
||||||
ExtensionContext::instance().report('X', 0, "Error", "%s", errorMessage->c_str());
|
ExtensionContext::instance().report('X', 0, 0, "Error", "%s", errorMessage->c_str());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
SymbolParameterVector parameters(1, DEBUG_SYMBOL_PARAMETERS());
|
SymbolParameterVector parameters(1, DEBUG_SYMBOL_PARAMETERS());
|
||||||
|
|||||||
@@ -1585,23 +1585,31 @@ void CdbEngine::parseOutputLine(QByteArray line)
|
|||||||
// can mix things up.
|
// can mix things up.
|
||||||
while (isCdbPrompt(line))
|
while (isCdbPrompt(line))
|
||||||
line.remove(0, CdbPromptLength);
|
line.remove(0, CdbPromptLength);
|
||||||
// An extension notification
|
// An extension notification (potentially consisting of several chunks)
|
||||||
if (line.startsWith(m_creatorExtPrefix)) {
|
if (line.startsWith(m_creatorExtPrefix)) {
|
||||||
// "<qtcreatorcdbext>|type_char|token|serviceName|message"
|
// "<qtcreatorcdbext>|type_char|token|remainingChunks|serviceName|message"
|
||||||
const char type = line.at(m_creatorExtPrefix.size());
|
const char type = line.at(m_creatorExtPrefix.size());
|
||||||
// integer token
|
// integer token
|
||||||
const int tokenPos = m_creatorExtPrefix.size() + 2;
|
const int tokenPos = m_creatorExtPrefix.size() + 2;
|
||||||
const int tokenEndPos = line.indexOf('|', tokenPos);
|
const int tokenEndPos = line.indexOf('|', tokenPos);
|
||||||
QTC_ASSERT(tokenEndPos != -1, return)
|
QTC_ASSERT(tokenEndPos != -1, return)
|
||||||
const int token = line.mid(tokenPos, tokenEndPos - tokenPos).toInt();
|
const int token = line.mid(tokenPos, tokenEndPos - tokenPos).toInt();
|
||||||
|
// remainingChunks
|
||||||
|
const int remainingChunksPos = tokenEndPos + 1;
|
||||||
|
const int remainingChunksEndPos = line.indexOf('|', remainingChunksPos);
|
||||||
|
QTC_ASSERT(remainingChunksEndPos != -1, return)
|
||||||
|
const int remainingChunks = line.mid(remainingChunksPos, remainingChunksEndPos - remainingChunksPos).toInt();
|
||||||
// const char 'serviceName'
|
// const char 'serviceName'
|
||||||
const int whatPos = tokenEndPos + 1;
|
const int whatPos = remainingChunksEndPos + 1;
|
||||||
const int whatEndPos = line.indexOf('|', whatPos);
|
const int whatEndPos = line.indexOf('|', whatPos);
|
||||||
QTC_ASSERT(whatEndPos != -1, return)
|
QTC_ASSERT(whatEndPos != -1, return)
|
||||||
const QByteArray what = line.mid(whatPos, whatEndPos - whatPos);
|
const QByteArray what = line.mid(whatPos, whatEndPos - whatPos);
|
||||||
// Message
|
// Build up buffer, call handler once last chunk was encountered
|
||||||
const QByteArray message = line.mid(whatEndPos + 1);
|
m_extensionMessageBuffer += line.mid(whatEndPos + 1);
|
||||||
handleExtensionMessage(type, token, what, message);
|
if (remainingChunks == 0) {
|
||||||
|
handleExtensionMessage(type, token, what, m_extensionMessageBuffer);
|
||||||
|
m_extensionMessageBuffer.clear();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Check for command start/end tokens within which the builtin command
|
// Check for command start/end tokens within which the builtin command
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ private:
|
|||||||
bool m_hasDebuggee;
|
bool m_hasDebuggee;
|
||||||
QTime m_logTime;
|
QTime m_logTime;
|
||||||
mutable int m_elapsedLogTime;
|
mutable int m_elapsedLogTime;
|
||||||
|
QByteArray m_extensionMessageBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cdb
|
} // namespace Cdb
|
||||||
|
|||||||
Reference in New Issue
Block a user