forked from qt-creator/qt-creator
CDB: Use maxStackDepth and implement reload full stack.
Task-number: QTCREATORBUG-7320 Change-Id: I78bf8cf63fa892f2a6771911333c246839439bf4 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -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())
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user