Debugger: add some food for the threads view in the LLDB backend

Change-Id: I6d8ea11d6c6e1206e5d1c3f13a51ae0521f25a85
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hjk
2013-04-05 19:20:11 +02:00
parent d63e38b021
commit ecbdc68c96
3 changed files with 169 additions and 86 deletions

View File

@@ -559,6 +559,53 @@ try:
def fieldCount(type): def fieldCount(type):
return type.fieldCount(); return type.fieldCount();
def threadsData(threadsOptions):
result = "threads={threads=["
for i in range(lldb.process.num_threads):
thread = lldb.process.GetThreadAtIndex(i)
result += "{id=\"%d\"" % thread.id
result += ",target-id=\"%s\"" % thread.id
result += ",stop-reason=\"%s\"" % thread.stop_reason
if thread.IsSuspended():
result += ",state=\"stopped\""
else:
result += ",state=\"running\""
if not thread.name is None:
result += ",name=\"%s\"" % thread.name
result += ",frame={"
frame = thread.GetFrameAtIndex(0)
result += "pc=\"%s\"" % frame.pc
result += ",level=\"%d\"" % i
result += ",addr=\"%s\"" % frame.pc
result += ",fp=\"%s\"" % frame.fp
result += ",func=\"%s\"" % frame.function.name
result += ",line=\"%s\"" % frame.line_entry.line
result += ",fullname=\"%s\"" % frame.line_entry.file
result += ",file=\"%s\"" % frame.line_entry.file
result += "}},"
result += "],current-thread-id=\"%s\"}" % lldb.process.GetSelectedThread().id
return result
def stackData(stackOptions):
result = "stack=["
result += "],"
return result
def updateData(parts, localsOptions, stackOptions, threadsOptions):
result = "";
if parts & 1:
result += bb(localsOptions) + ','
if parts & 2:
result += stackData(stackOptions)
if parts & 4:
result += threadsData(threadsOptions)
return result
except: except:
#warn("LOADING LLDB FAILED") #warn("LOADING LLDB FAILED")
pass pass

View File

@@ -43,6 +43,7 @@
#include "registerhandler.h" #include "registerhandler.h"
#include "stackhandler.h" #include "stackhandler.h"
#include "sourceutils.h" #include "sourceutils.h"
#include "threadshandler.h"
#include "watchhandler.h" #include "watchhandler.h"
#include "watchutils.h" #include "watchutils.h"
@@ -360,13 +361,13 @@ void LldbEngine::activateFrame(int frameIndex)
return; return;
postCommand("frame select " + QByteArray::number(frameIndex), postCommand("frame select " + QByteArray::number(frameIndex),
CB(handleUpdateAll)); CB(triggerUpdateAll));
} }
void LldbEngine::selectThread(ThreadId threadId) void LldbEngine::selectThread(ThreadId threadId)
{ {
postCommand("thread select " + QByteArray::number(threadId.raw()), postCommand("thread select " + QByteArray::number(threadId.raw()),
CB(handleUpdateAll)); CB(triggerUpdateAll));
} }
bool LldbEngine::acceptsBreakpoint(BreakpointModelId id) const bool LldbEngine::acceptsBreakpoint(BreakpointModelId id) const
@@ -757,7 +758,7 @@ void LldbEngine::handleFirstCommand(const LldbResponse &response)
Q_UNUSED(response); Q_UNUSED(response);
} }
void LldbEngine::handleUpdateAll(const LldbResponse &response) void LldbEngine::triggerUpdateAll(const LldbResponse &response)
{ {
Q_UNUSED(response); Q_UNUSED(response);
updateAll(); updateAll();
@@ -765,12 +766,16 @@ void LldbEngine::handleUpdateAll(const LldbResponse &response)
void LldbEngine::updateAll() void LldbEngine::updateAll()
{ {
//postCommand("bt", CB(handleBacktrace)); updateData(DataKind(LocalsData | StackData | ThreadData));
updateLocals();
} }
void LldbEngine::updateLocals() void LldbEngine::updateData(DataKind kind)
{ {
QByteArray localsOptions;
QByteArray stackOptions;
QByteArray threadsOptions;
if (kind & LocalsData) {
QByteArray watchers; QByteArray watchers;
//if (!m_toolTipExpression.isEmpty()) //if (!m_toolTipExpression.isEmpty())
// watchers += m_toolTipExpression.toLatin1() // watchers += m_toolTipExpression.toLatin1()
@@ -795,13 +800,19 @@ void LldbEngine::updateLocals()
options += "defaults,"; options += "defaults,";
options.chop(1); options.chop(1);
postCommand("script bb('options:" + options + " " localsOptions = "options:" + options + " "
+ "vars: " + "vars: "
+ "expanded:" + handler->expansionRequests() + " " + "expanded:" + handler->expansionRequests() + " "
+ "typeformats:" + handler->typeFormatRequests() + " " + "typeformats:" + handler->typeFormatRequests() + " "
+ "formats:" + handler->individualFormatRequests() + " " + "formats:" + handler->individualFormatRequests() + " "
+ "watcher:" + watchers.toHex() + "')", + "watcher:" + watchers.toHex();
CB(handleListLocals)); }
postCommand("script updateData(" + QByteArray::number(kind) + ','
+ '\'' + localsOptions + "',"
+ '\'' + stackOptions + "',"
+ '\'' + threadsOptions + "')",
CB(handleUpdateData));
} }
void LldbEngine::handleBacktrace(const LldbResponse &response) void LldbEngine::handleBacktrace(const LldbResponse &response)
@@ -847,19 +858,17 @@ void LldbEngine::handleBacktrace(const LldbResponse &response)
gotoLocation(stackFrames.at(currentIndex)); gotoLocation(stackFrames.at(currentIndex));
} }
updateLocals(); updateData(LocalsData);
} }
void LldbEngine::handleListLocals(const LldbResponse &response) GdbMi LldbEngine::parseFromString(QByteArray out)
{ {
//qDebug() << " LOCALS: '" << response.data << "'"; GdbMi all;
QByteArray out = response.data;
{
int pos = out.indexOf("data="); int pos = out.indexOf("data=");
if (pos == -1) { if (pos == -1) {
showMessage(_("UNEXPECTED LOCALS OUTPUT:" + out)); showMessage(_("UNEXPECTED LOCALS OUTPUT:" + out));
return; return all;
} }
// The value in 'out' should be single-quoted as this is // The value in 'out' should be single-quoted as this is
@@ -873,12 +882,18 @@ void LldbEngine::handleListLocals(const LldbResponse &response)
out.chop(1); out.chop(1);
else else
showMessage(_("JUNK AT END OF RESPONSE: " + out)); showMessage(_("JUNK AT END OF RESPONSE: " + out));
all.fromStringMultiple(out);
return all;
} }
GdbMi all; void LldbEngine::handleUpdateData(const LldbResponse &response)
all.fromStringMultiple(out); {
GdbMi data = all.findChild("data"); //qDebug() << " LOCALS: '" << response.data << "'";
GdbMi all = parseFromString(response.data);
GdbMi vars = all.findChild("data");
if (vars.isValid()) {
const bool partial = response.cookie.toBool(); const bool partial = response.cookie.toBool();
WatchHandler *handler = watchHandler(); WatchHandler *handler = watchHandler();
QList<WatchData> list; QList<WatchData> list;
@@ -889,7 +904,7 @@ void LldbEngine::handleListLocals(const LldbResponse &response)
list.append(*handler->findData("return")); list.append(*handler->findData("return"));
} }
foreach (const GdbMi &child, data.children()) { foreach (const GdbMi &child, vars.children()) {
WatchData dummy; WatchData dummy;
dummy.iname = child.findChild("iname").data(); dummy.iname = child.findChild("iname").data();
GdbMi wname = child.findChild("wname"); GdbMi wname = child.findChild("wname");
@@ -903,6 +918,9 @@ void LldbEngine::handleListLocals(const LldbResponse &response)
} }
parseWatchData(handler->expandedINames(), dummy, child, &list); parseWatchData(handler->expandedINames(), dummy, child, &list);
} }
handler->insertData(list);
}
// const GdbMi typeInfo = all.findChild("typeinfo"); // const GdbMi typeInfo = all.findChild("typeinfo");
// if (typeInfo.type() == GdbMi::List) { // if (typeInfo.type() == GdbMi::List) {
// foreach (const GdbMi &s, typeInfo.children()) { // foreach (const GdbMi &s, typeInfo.children()) {
@@ -919,11 +937,23 @@ void LldbEngine::handleListLocals(const LldbResponse &response)
// list[i].size = ti.size; // list[i].size = ti.size;
// } // }
handler->insertData(list); GdbMi stack = all.findChild("stack");
if (stack.isValid()) {
//if (!partial)
// emit stackFrameCompleted();
}
//rebuildWatchModel(); GdbMi threads = all.findChild("threads");
if (!partial) if (threads.isValid()) {
emit stackFrameCompleted(); ThreadsHandler *handler = threadsHandler();
handler->updateThreads(threads);
if (!handler->currentThread().isValid()) {
ThreadId other = handler->threadAt(0);
if (other.isValid())
selectThread(other);
}
updateViews(); // Adjust Threads combobox.
}
} }
void LldbEngine::loadPythonDumpers() void LldbEngine::loadPythonDumpers()

View File

@@ -121,10 +121,13 @@ private:
Q_SLOT void handleOutput2(const QByteArray &data); Q_SLOT void handleOutput2(const QByteArray &data);
void handleResponse(const QByteArray &ba); void handleResponse(const QByteArray &ba);
enum DataKind { LocalsData = 1, StackData = 2, ThreadData = 4 };
void loadPythonDumpers(); void loadPythonDumpers();
void updateAll(); void updateAll();
void updateLocals(); void updateData(DataKind kind);
void handleUpdateAll(const LldbResponse &response); void triggerUpdateAll(const LldbResponse &response);
void handleUpdateData(const LldbResponse &response);
void handleFirstCommand(const LldbResponse &response); void handleFirstCommand(const LldbResponse &response);
void handleExecuteDebuggerCommand(const LldbResponse &response); void handleExecuteDebuggerCommand(const LldbResponse &response);
void handleInferiorSetup(const LldbResponse &response); void handleInferiorSetup(const LldbResponse &response);
@@ -152,6 +155,8 @@ private:
void handleListModules(const LldbResponse &response); void handleListModules(const LldbResponse &response);
void handleListSymbols(const LldbResponse &response); void handleListSymbols(const LldbResponse &response);
void handleBreakInsert(const LldbResponse &response); void handleBreakInsert(const LldbResponse &response);
void handleUpdateStack(const LldbResponse &response);
void handleUpdateThreads(const LldbResponse &response);
void handleChildren(const WatchData &data0, const GdbMi &item, void handleChildren(const WatchData &data0, const GdbMi &item,
QList<WatchData> *list); QList<WatchData> *list);
@@ -160,6 +165,7 @@ private:
const char *callbackName = 0, const char *callbackName = 0,
const QVariant &cookie = QVariant()); const QVariant &cookie = QVariant());
void postDirectCommand(const QByteArray &command); void postDirectCommand(const QByteArray &command);
GdbMi parseFromString(QByteArray out);
QQueue<LldbCommand> m_commands; QQueue<LldbCommand> m_commands;