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

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)
else
str << ",threads=" << threadInfo;
const std::string stackInfo = gdbmiStack(exc.control(), exc.symbols(),
maxStackFrames, false, &errorMessage);
ExtensionContext::instance().parameters().maxStackDepth,
false, &errorMessage);
if (stackInfo.empty())
str << ",stackerror=" << gdbmiStringFormat(errorMessage);
else
......
......@@ -58,8 +58,6 @@ class ExtensionContext {
ExtensionContext();
public:
enum { maxStackFrames = 200 };
// Key used to report stop reason in StopReasonMap
static const char *stopReasonKeyC;
static const char *breakPointStopReasonC; // pre-defined stop reasons
......
......@@ -572,19 +572,30 @@ std::wstring memoryToHexW(CIDebugDataSpaces *ds, ULONG64 address, ULONG length,
static StackFrames getStackTrace(CIDebugControl *debugControl,
CIDebugSymbols *debugSymbols,
unsigned maxFrames,
bool *incomplete,
std::string *errorMessage)
{
if (!maxFrames)
if (maxFrames) {
*incomplete = false;
} else {
*incomplete = true;
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;
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)) {
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]));
......@@ -597,8 +608,9 @@ std::string gdbmiStack(CIDebugControl *debugControl,
unsigned maxFrames,
bool humanReadable, std::string *errorMessage)
{
bool incomplete;
const StackFrames frames = getStackTrace(debugControl, debugSymbols,
maxFrames, errorMessage);
maxFrames, &incomplete, errorMessage);
if (frames.empty() && maxFrames > 0)
return std::string();
......@@ -612,6 +624,8 @@ std::string gdbmiStack(CIDebugControl *debugControl,
if (humanReadable)
str << '\n';
}
if (incomplete) // Empty elements indicates incomplete.
str <<",{}";
str << ']';
return str.str();
}
......
......@@ -165,7 +165,7 @@ std::wstring memoryToHexW(CIDebugDataSpaces *ds, ULONG64 address, ULONG length,
std::string *errorMessage = 0);
// Stack helpers
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,
unsigned maxFrames, bool humanReadable,
......
......@@ -168,7 +168,7 @@ static const CommandDescription commandDescriptions[] = {
{"help","Prints help.",""},
{"memory","Prints memory contents in Base64 encoding.","[-t token] <address> <length>"},
{"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.",""},
{"addwatch","Add watch expression","<iname> <expression>"},
{"widgetat","Return address of widget at position","<x> <y>"},
......@@ -1005,15 +1005,20 @@ extern "C" HRESULT CALLBACK stack(CIDebugClient *Client, PCSTR argsIn)
int token;
bool humanReadable = false;
unsigned maxFrames = ExtensionContext::maxStackFrames;
unsigned maxFrames = ExtensionContext::instance().parameters().maxStackDepth;
StringList tokens = commandTokens<StringList>(argsIn, &token);
if (!tokens.empty() && tokens.front() == "-h") {
humanReadable = true;
tokens.pop_front();
}
if (!tokens.empty())
integerFromString(tokens.front(), &maxFrames);
if (!tokens.empty()) {
if (tokens.front() == "unlimited") {
maxFrames = 1000;
} else {
integerFromString(tokens.front(), &maxFrames);
}
}
const std::string stack = gdbmiStack(exc.control(), exc.symbols(),
maxFrames, humanReadable, &errorMessage);
......
......@@ -1449,7 +1449,10 @@ void CdbEngine::activateFrame(int index)
if (index < 0)
return;
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);
if (debug || debugLocals)
......@@ -2840,13 +2843,20 @@ CdbEngine::NormalizedSourceFileName CdbEngine::sourceMapNormalizeFileNameFromDeb
// Parse frame from GDBMI. Duplicate of the gdb code, but that
// has more processing.
static StackFrames parseFrames(const GdbMi &gdbmi)
static StackFrames parseFrames(const GdbMi &gdbmi, bool *incomplete = 0)
{
if (incomplete)
*incomplete = false;
StackFrames rc;
const int count = gdbmi.childCount();
rc.reserve(count);
for (int i = 0; i < count; i++) {
const GdbMi &frameMi = gdbmi.childAt(i);
if (!frameMi.childCount()) { // Empty item indicates "More...".
if (incomplete)
*incomplete = true;
break;
}
StackFrame frame;
frame.level = i;
const GdbMi fullName = frameMi.findChild("fullname");
......@@ -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. .
// Note that executing 't 2' does not work since it steps 2 instructions on a non-call code line.
int current = -1;
StackFrames frames = parseFrames(data);
bool incomplete;
StackFrames frames = parseFrames(data, &incomplete);
const int count = frames.size();
for (int i = 0; i < count; i++) {
const bool hasFile = !frames.at(i).file.isEmpty();
......@@ -2891,7 +2902,7 @@ unsigned CdbEngine::parseStackTrace(const GdbMi &data, bool sourceStepInto)
if (count && current == -1) // No usable frame, use assembly.
current = 0;
// Set
stackHandler()->setFrames(frames);
stackHandler()->setFrames(frames, incomplete);
activateFrame(current);
return 0;
}
......@@ -2959,7 +2970,7 @@ void CdbEngine::postCommandSequence(unsigned mask)
return;
}
if (mask & CommandListStack) {
postExtensionCommand("stack", QByteArray(), 0, &CdbEngine::handleStackTrace, mask & ~CommandListStack);
postExtensionCommand("stack", "unlimited", 0, &CdbEngine::handleStackTrace, mask & ~CommandListStack);
return;
}
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