Commit 2970a036 authored by Friedemann Kleint's avatar Friedemann Kleint Committed by hjk
Browse files

CDB: Use maxStackDepth and implement reload full stack.



Task-number: QTCREATORBUG-7320

Change-Id: I78bf8cf63fa892f2a6771911333c246839439bf4
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 0a35cae9
...@@ -203,7 +203,8 @@ void ExtensionContext::notifyIdleCommand(CIDebugClient *client) ...@@ -203,7 +203,8 @@ void ExtensionContext::notifyIdleCommand(CIDebugClient *client)
else else
str << ",threads=" << threadInfo; str << ",threads=" << threadInfo;
const std::string stackInfo = gdbmiStack(exc.control(), exc.symbols(), const std::string stackInfo = gdbmiStack(exc.control(), exc.symbols(),
maxStackFrames, false, &errorMessage); ExtensionContext::instance().parameters().maxStackDepth,
false, &errorMessage);
if (stackInfo.empty()) if (stackInfo.empty())
str << ",stackerror=" << gdbmiStringFormat(errorMessage); str << ",stackerror=" << gdbmiStringFormat(errorMessage);
else else
......
...@@ -58,8 +58,6 @@ class ExtensionContext { ...@@ -58,8 +58,6 @@ class ExtensionContext {
ExtensionContext(); ExtensionContext();
public: public:
enum { maxStackFrames = 200 };
// Key used to report stop reason in StopReasonMap // Key used to report stop reason in StopReasonMap
static const char *stopReasonKeyC; static const char *stopReasonKeyC;
static const char *breakPointStopReasonC; // pre-defined stop reasons static const char *breakPointStopReasonC; // pre-defined stop reasons
......
...@@ -572,19 +572,30 @@ std::wstring memoryToHexW(CIDebugDataSpaces *ds, ULONG64 address, ULONG length, ...@@ -572,19 +572,30 @@ std::wstring memoryToHexW(CIDebugDataSpaces *ds, ULONG64 address, ULONG length,
static StackFrames getStackTrace(CIDebugControl *debugControl, static StackFrames getStackTrace(CIDebugControl *debugControl,
CIDebugSymbols *debugSymbols, CIDebugSymbols *debugSymbols,
unsigned maxFrames, unsigned maxFrames,
bool *incomplete,
std::string *errorMessage) std::string *errorMessage)
{ {
if (!maxFrames) if (maxFrames) {
*incomplete = false;
} else {
*incomplete = true;
return StackFrames(); return StackFrames();
DEBUG_STACK_FRAME *frames = new DEBUG_STACK_FRAME[maxFrames]; }
// 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; ULONG frameCount = 0;
const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, maxFrames, &frameCount); const HRESULT hr = debugControl->GetStackTrace(0, 0, 0, frames, askedFrames, &frameCount);
if (FAILED(hr)) { if (FAILED(hr)) {
delete [] frames; delete [] frames;
*errorMessage = msgDebugEngineComFailed("GetStackTrace", hr); *errorMessage = msgDebugEngineComFailed("GetStackTrace", hr);
return StackFrames(); return StackFrames();
} }
if (askedFrames == frameCount) {
--frameCount;
*incomplete = true;
}
StackFrames rc(frameCount, StackFrame()); StackFrames rc(frameCount, StackFrame());
for (ULONG f = 0; f < frameCount; ++f) for (ULONG f = 0; f < frameCount; ++f)
getFrame(debugSymbols, frames[f], &(rc[f])); getFrame(debugSymbols, frames[f], &(rc[f]));
...@@ -597,8 +608,9 @@ std::string gdbmiStack(CIDebugControl *debugControl, ...@@ -597,8 +608,9 @@ std::string gdbmiStack(CIDebugControl *debugControl,
unsigned maxFrames, unsigned maxFrames,
bool humanReadable, std::string *errorMessage) bool humanReadable, std::string *errorMessage)
{ {
bool incomplete;
const StackFrames frames = getStackTrace(debugControl, debugSymbols, const StackFrames frames = getStackTrace(debugControl, debugSymbols,
maxFrames, errorMessage); maxFrames, &incomplete, errorMessage);
if (frames.empty() && maxFrames > 0) if (frames.empty() && maxFrames > 0)
return std::string(); return std::string();
...@@ -612,6 +624,8 @@ std::string gdbmiStack(CIDebugControl *debugControl, ...@@ -612,6 +624,8 @@ std::string gdbmiStack(CIDebugControl *debugControl,
if (humanReadable) if (humanReadable)
str << '\n'; str << '\n';
} }
if (incomplete) // Empty elements indicates incomplete.
str <<",{}";
str << ']'; str << ']';
return str.str(); return str.str();
} }
......
...@@ -165,7 +165,7 @@ std::wstring memoryToHexW(CIDebugDataSpaces *ds, ULONG64 address, ULONG length, ...@@ -165,7 +165,7 @@ std::wstring memoryToHexW(CIDebugDataSpaces *ds, ULONG64 address, ULONG length,
std::string *errorMessage = 0); std::string *errorMessage = 0);
// Stack helpers // Stack helpers
StackFrames getStackTrace(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols, StackFrames getStackTrace(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols,
unsigned maxFrames, std::string *errorMessage); unsigned maxFrames, bool *incomplete, std::string *errorMessage);
std::string gdbmiStack(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols, std::string gdbmiStack(CIDebugControl *debugControl, CIDebugSymbols *debugSymbols,
unsigned maxFrames, bool humanReadable, unsigned maxFrames, bool humanReadable,
......
...@@ -168,7 +168,7 @@ static const CommandDescription commandDescriptions[] = { ...@@ -168,7 +168,7 @@ static const CommandDescription commandDescriptions[] = {
{"help","Prints help.",""}, {"help","Prints help.",""},
{"memory","Prints memory contents in Base64 encoding.","[-t token] <address> <length>"}, {"memory","Prints memory contents in Base64 encoding.","[-t token] <address> <length>"},
{"expression","Prints expression value.","[-t token] <expression>"}, {"expression","Prints expression value.","[-t token] <expression>"},
{"stack","Prints stack in GDBMI format.","[-t token] [max-frames]"}, {"stack","Prints stack in GDBMI format.","[-t token] [<max-frames>|unlimited]"},
{"shutdownex","Unhooks output callbacks.\nNeeds to be called explicitly only in case of remote debugging.",""}, {"shutdownex","Unhooks output callbacks.\nNeeds to be called explicitly only in case of remote debugging.",""},
{"addwatch","Add watch expression","<iname> <expression>"}, {"addwatch","Add watch expression","<iname> <expression>"},
{"widgetat","Return address of widget at position","<x> <y>"}, {"widgetat","Return address of widget at position","<x> <y>"},
...@@ -1005,15 +1005,20 @@ extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn) ...@@ -1005,15 +1005,20 @@ extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn)
int token; int token;
bool humanReadable = false; bool humanReadable = false;
unsigned maxFrames = ExtensionContext::maxStackFrames; unsigned maxFrames = ExtensionContext::instance().parameters().maxStackDepth;
StringList tokens = commandTokens<StringList>(argsIn, &token); StringList tokens = commandTokens<StringList>(argsIn, &token);
if (!tokens.empty() && tokens.front() == "-h") { if (!tokens.empty() && tokens.front() == "-h") {
humanReadable = true; humanReadable = true;
tokens.pop_front(); tokens.pop_front();
} }
if (!tokens.empty()) if (!tokens.empty()) {
integerFromString(tokens.front(), &maxFrames); if (tokens.front() == "unlimited") {
maxFrames = 1000;
} else {
integerFromString(tokens.front(), &maxFrames);
}
}
const std::string stack = gdbmiStack(exc.control(), exc.symbols(), const std::string stack = gdbmiStack(exc.control(), exc.symbols(),
maxFrames, humanReadable, &errorMessage); maxFrames, humanReadable, &errorMessage);
......
...@@ -1449,7 +1449,10 @@ void CdbEngine::activateFrame(int index) ...@@ -1449,7 +1449,10 @@ void CdbEngine::activateFrame(int index)
if (index < 0) if (index < 0)
return; return;
const StackFrames &frames = stackHandler()->frames(); const StackFrames &frames = stackHandler()->frames();
QTC_ASSERT(index < frames.size(), return); if (index >= frames.size()) {
reloadFullStack(); // Clicked on "More...".
return;
}
const StackFrame frame = frames.at(index); const StackFrame frame = frames.at(index);
if (debug || debugLocals) if (debug || debugLocals)
...@@ -2840,13 +2843,20 @@ CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDeb ...@@ -2840,13 +2843,20 @@ CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDeb
// Parse frame from GDBMI. Duplicate of the gdb code, but that // Parse frame from GDBMI. Duplicate of the gdb code, but that
// has more processing. // has more processing.
static StackFrames parseFrames(const GdbMi &gdbmi) static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = 0)
{ {
if (incomplete)
*incomplete = false;
StackFrames rc; StackFrames rc;
const int count = gdbmi.childCount(); const int count = gdbmi.childCount();
rc.reserve(count); rc.reserve(count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
const GdbMi &frameMi = gdbmi.childAt(i); const GdbMi &frameMi = gdbmi.childAt(i);
if (!frameMi.childCount()) { // Empty item indicates "More...".
if (incomplete)
*incomplete = true;
break;
}
StackFrame frame; StackFrame frame;
frame.level = i; frame.level = i;
const GdbMi fullName = frameMi.findChild("fullname"); const GdbMi fullName = frameMi.findChild("fullname");
...@@ -2871,7 +2881,8 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto) ...@@ -2871,7 +2881,8 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
// 'ILT+'). If that is the case, execute another 't' to step into the actual function. . // 'ILT+'). If that is the case, execute another 't' to step into the actual function. .
// Note that executing 't 2' does not work since it steps 2 instructions on a non-call code line. // Note that executing 't 2' does not work since it steps 2 instructions on a non-call code line.
int current = -1; int current = -1;
StackFrames frames = parseFrames(data); bool incomplete;
StackFrames frames = parseFrames(data, &incomplete);
const int count = frames.size(); const int count = frames.size();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
const bool hasFile = !frames.at(i).file.isEmpty(); const bool hasFile = !frames.at(i).file.isEmpty();
...@@ -2891,7 +2902,7 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto) ...@@ -2891,7 +2902,7 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
if (count && current == -1) // No usable frame, use assembly. if (count && current == -1) // No usable frame, use assembly.
current = 0; current = 0;
// Set // Set
stackHandler()->setFrames(frames); stackHandler()->setFrames(frames, incomplete);
activateFrame(current); activateFrame(current);
return 0; return 0;
} }
...@@ -2959,7 +2970,7 @@ void CdbEngine::postCommandSequence(unsigned mask) ...@@ -2959,7 +2970,7 @@ void CdbEngine::postCommandSequence(unsigned mask)
return; return;
} }
if (mask & CommandListStack) { if (mask & CommandListStack) {
postExtensionCommand("stack", QByteArray(), 0, &CdbEngine::handleStackTrace, mask & ~CommandListStack); postExtensionCommand("stack", "unlimited", 0, &CdbEngine::handleStackTrace, mask & ~CommandListStack);
return; return;
} }
if (mask & CommandListRegisters) { if (mask & CommandListRegisters) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment