Debugger: Progress on LLDB state handling

Change-Id: Iadf9c7026a3da0adeec8340729a303bbbee57c24
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hjk
2013-04-12 14:41:05 +02:00
parent 77abd02787
commit 4269ce4e38
4 changed files with 98 additions and 114 deletions

View File

@@ -259,6 +259,7 @@ NamespaceCode = gdb.TYPE_CODE_NAMESPACE
#Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point. #Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point.
#Code = gdb.TYPE_CODE_MODULE # Fortran #Code = gdb.TYPE_CODE_MODULE # Fortran
#Code = gdb.TYPE_CODE_INTERNAL_FUNCTION #Code = gdb.TYPE_CODE_INTERNAL_FUNCTION
SimpleValueCode = -1
####################################################################### #######################################################################

View File

@@ -109,17 +109,13 @@ class Value:
def fields(self): def fields(self):
return [Value(self.raw.GetChildAtIndex(i)) for i in range(self.raw.num_children)] return [Value(self.raw.GetChildAtIndex(i)) for i in range(self.raw.num_children)]
currentThread = None def currentFrame():
currentFrame = None currentThread = lldb.process.GetThreadAtIndex(0)
return currentThread.GetFrameAtIndex(0)
def listOfLocals(varList): def listOfLocals(varList):
global currentThread
global currentFrame
items = [] items = []
currentThread = lldb.process.GetThreadAtIndex(0) for var in currentFrame().variables:
currentFrame = currentThread.GetFrameAtIndex(0)
for var in currentFrame.variables:
item = LocalItem() item = LocalItem()
item.iname = "local." + var.name item.iname = "local." + var.name
item.name = var.name item.name = var.name
@@ -160,7 +156,7 @@ def threadsData(options):
result += ",file=\"%s\"" % frame.line_entry.file result += ",file=\"%s\"" % frame.line_entry.file
result += "}}," result += "}},"
result += "],current-thread-id=\"%s\"}" % lldb.process.selected_thread.id result += "],current-thread-id=\"%s\"}," % lldb.process.selected_thread.id
return result return result
# See lldb.StateType # See lldb.StateType
@@ -256,12 +252,9 @@ def onBreak():
result = "*stopped,frame={....}" result = "*stopped,frame={....}"
print result print result
def handleBreakpoints(opts, toAdd, toChange, toRemove): def handleBreakpoints(options, toAdd, toChange, toRemove):
#todo = json.loads(stuff)
#dumpJson(todo)
#target = lldb.debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT) #target = lldb.debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
target = lldb.debugger.GetTargetAtIndex(0) target = lldb.debugger.GetTargetAtIndex(0)
#target = lldb.target
result = "result={bkpts={added=[" result = "result={bkpts={added=["
@@ -282,8 +275,8 @@ def handleBreakpoints(opts, toAdd, toChange, toRemove):
#"breakpoint command add 1 -o \"import time; print time.asctime()\" #"breakpoint command add 1 -o \"import time; print time.asctime()\"
#cmd = "script print(11111111)" #cmd = "script print(11111111)"
cmd = "continue" cmd = "continue"
lldb.debugger.HandleCommand( #lldb.debugger.HandleCommand(
"breakpoint command add -o 'script onBreak()' %s" % bpNew.GetID()) # "breakpoint command add -o 'script onBreak()' %s" % bpNew.GetID())
result += dumpBreakpoint(bpNew, bp["modelid"]) result += dumpBreakpoint(bpNew, bp["modelid"])
@@ -306,127 +299,99 @@ def handleBreakpoints(opts, toAdd, toChange, toRemove):
result += "]}}" result += "]}}"
return result return result
def doSync(func): def createStoppedReport(options):
lldb.debugger.SetAsync(False)
func()
lldb.debugger.SetAsync(True)
def createReport(options):
result = "result={" result = "result={"
result += bb(options["locals"]) result += bb(options["locals"]) + ","
result += stackData(options["stack"], lldb.process.selected_thread.id) result += stackData(options["stack"], lldb.process.selected_thread.id)
result += threadsData({}) result += threadsData({})
result += stateData({}) result += stateData({})
result += locationData({}) result += locationData({})
result += "token=\"%s\"" % options["token"] result += "token=\"%s\"," % options["token"]
result += "}" result += "}"
return result return result
def executeNext(opts): def createRunReport(options):
doSync(lldb.thread.StepOver) result = "result={"
return createReport(opts) #result += stateData({})
result += "state=\"running\","
result += "token=\"%s\"," % options["token"]
result += "}"
return result
def executeNextI(opts): def createReport(options):
doSync(lldb.thread.StepOver) return createStoppedReport(options)
return createReport(opts)
def executeStep(opts): def executeNext(options):
lldb.thread.Step() lldb.thread.StepOver()
return createReport(opts) return createRunReport(options)
def executeStepI(opts): def executeNextI(options):
doSync(lldb.thread.StepInstOver) lldb.thread.StepOver()
return createReport(opts) return createRunReport(options)
def executeStepOut(opts): def executeStep(options):
doSync(lldb.thread.StepOut) lldb.thread.StepInto()
return createReport(opts) return createRunReport(options)
def executeRunToLine(opts): def executeStepI(options):
return "result={error={msg='Not implemented'}}" lldb.thread.StepInstOver()
return createRunReport(options)
def executeJumpToLine(opts): def executeStepOut(options):
return "result={error={msg='Not implemented'}}" lldb.thread.StepOutOfFrame(currentFrame())
return createRunReport(options)
def continueInferior(opts): def executeRunToLine(options, file, line):
#lldb.debugger.HandleCommand("process continue") lldb.thread.StepOverUntil(file, line)
return createRunReport(options)
def executeJumpToLine(options):
return "result={error={msg='Not implemented'},state='stopped'}"
def continueInferior(options):
lldb.process.Continue() lldb.process.Continue()
return "result={state='running'}" return "result={state=\"running\"}"
def interruptInferior(opts): def interruptInferior(options):
lldb.debugger.SetAsync(False)
lldb.process.Stop() lldb.process.Stop()
#lldb.process.SendAsyncInterrupt() return "result={state=\"interrupting\"}"
lldb.debugger.SetAsync(True)
return createReport()
def setupInferior(opts, fileName): def setupInferior(options, fileName):
lldb.debugger.HandleCommand("target create '%s'" % fileName) msg = lldb.debugger.HandleCommand("target create '%s'" % fileName)
return "result={state=\"inferiorsetupok\"}" return "result={state=\"inferiorsetupok\",msg=\"%s\"}" % msg
def runEngine(opts): def runEngine(options):
lldb.debugger.HandleCommand("process launch") msg = lldb.debugger.HandleCommand("process launch")
return "result={state=\"enginerunok\"}" return "result={state=\"enginerunok\",msg=\"%s\"}" % msg
def activateFrame(opts, frame): def activateFrame(options, frame):
lldb.debugger.HandleCommand("frame select " + frame) lldb.debugger.HandleCommand("frame select " + frame)
return createStoppedReport(options)
def selectThread(opts, thread): def selectThread(options, thread):
lldb.debugger.HandleCommand("thread select " + thread) lldb.debugger.HandleCommand("thread select " + thread)
return createStoppedReport(options)
def requestModuleSymbols(opts, frame): def requestModuleSymbols(options, frame):
lldb.debugger.HandleCommand("target module list " + frame) lldb.debugger.HandleCommand("target module list " + frame)
def executeDebuggerCommand(options, command):
msg = lldb.debugger.HandleCommand(command)
result = "result={"
result += bb(options["locals"]) + ","
result += stackData(options["stack"], lldb.process.selected_thread.id)
result += threadsData({})
result += stateData({})
result += locationData({})
result += "token=\"%s\"," % options["token"]
result += "msg=\"%s\"" % msg
result += "}"
return result
#SBEvent data;
#while (!stop) {
#if (self->m_listener.WaitForEvent(UINT32_MAX, data)) {
# if (data.getType() == SBProcess::eBroadcastBitStateChanged &&
#m_process.GetStateFromEvent (data) == eStateStopped) {
# SBThread th = m_process.GetSelectedThread();
# if (th.GetStopReason() == eStopReasonBreakpoint) {
# // th.GetStopReasonDataAtIndex(0) should have the breakpoint id
# }
# }
lldb.debugger.HandleCommand("setting set auto-confirm on") lldb.debugger.HandleCommand("setting set auto-confirm on")
lldb.debugger.HandleCommand("setting set interpreter.prompt-on-quit off") lldb.debugger.HandleCommand("setting set interpreter.prompt-on-quit off")
if False:
# default:
# frame-format (string) = "frame #${frame.index}: ${frame.pc}
# { ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}
# { at ${line.file.basename}:${line.number}}\n"
lldb.debugger.HandleCommand("settings set frame-format frame=\{"
+ "index='${frame.index}',"
+ "pc='${frame.pc}',"
+ "module='${module.file.basename}',"
#+ "function='${function.name-with-args}',"
+ "function='${function.name}',"
+ "pcoffset='${function.pc-offset}',"
+ "file='${line.file.basename}',"
+ "line='${line.number}'"
+ "\},")
# default:
# "thread #${thread.index}: tid = ${thread.id}{, ${frame.pc}}
# { ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}
# { at ${line.file.basename}:${line.number}}
# {, stop reason = ${thread.stop-reason}}{\nReturn value: ${thread.return-value}}\n"
lldb.debugger.HandleCommand("settings set thread-format thread=\{"
+ "index='${thread.index}',"
+ "tid='${thread.id}',"
+ "framepc='${frame.pc}',"
+ "module='${module.file.basename}',"
+ "function='${function.name}',"
+ "pcoffset='${function.pc-offset}',"
+ "stopreason='${thread.stop-reason}'"
#+ "returnvalue='${thread.return-value}'"
+ "\},")
lldbLoaded = True lldbLoaded = True
execfile(os.path.join(currentDir, "dumper.py")) execfile(os.path.join(currentDir, "dumper.py"))

View File

@@ -204,8 +204,16 @@ void LldbEngine::setupInferior()
void LldbEngine::runEngine() void LldbEngine::runEngine()
{ {
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
QByteArray command;
bool done = attemptBreakpointSynchronizationHelper(&command);
if (done) {
runEngine2();
return;
}
m_continuations.append(&LldbEngine::runEngine2); m_continuations.append(&LldbEngine::runEngine2);
attemptBreakpointSynchronization(); runCommand("handleBreakpoints", command);
} }
void LldbEngine::runEngine2() void LldbEngine::runEngine2()
@@ -329,14 +337,8 @@ bool LldbEngine::acceptsBreakpoint(BreakpointModelId id) const
&& startParameters().startMode != AttachCore; && startParameters().startMode != AttachCore;
} }
void LldbEngine::attemptBreakpointSynchronization() bool LldbEngine::attemptBreakpointSynchronizationHelper(QByteArray *command)
{ {
showMessage(_("ATTEMPT BREAKPOINT SYNCHRONIZATION"));
if (!stateAcceptsBreakpointChanges()) {
showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE"));
return;
}
BreakHandler *handler = breakHandler(); BreakHandler *handler = breakHandler();
foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) {
@@ -407,11 +409,24 @@ void LldbEngine::attemptBreakpointSynchronization()
QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state()); QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state());
} }
} }
if (!done)
*command = '[' + toAdd + "],[" + toChange + "],[" + toRemove + ']';
return done;
}
void LldbEngine::attemptBreakpointSynchronization()
{
showMessage(_("ATTEMPT BREAKPOINT SYNCHRONIZATION"));
if (!stateAcceptsBreakpointChanges()) {
showMessage(_("BREAKPOINT SYNCHRONIZATION NOT POSSIBLE IN CURRENT STATE"));
return;
}
QByteArray command;
bool done = attemptBreakpointSynchronizationHelper(&command);
if (!done) { if (!done) {
showMessage(_("BREAKPOINTS ARE NOT FULLY SYNCHRONIZED")); showMessage(_("BREAKPOINTS ARE NOT FULLY SYNCHRONIZED"));
runCommand("handleBreakpoints", runCommand("handleBreakpoints", command);
'[' + toAdd + "],[" + toChange + "],[" + toRemove + ']');
} else { } else {
showMessage(_("BREAKPOINTS ARE SYNCHRONIZED")); showMessage(_("BREAKPOINTS ARE SYNCHRONIZED"));
} }
@@ -891,6 +906,8 @@ GdbMi LldbEngine::parseResultFromString(QByteArray out)
out = out.mid(pos); out = out.mid(pos);
if (out.endsWith('\'')) if (out.endsWith('\''))
out.chop(1); out.chop(1);
else if (out.endsWith('"'))
out.chop(1);
else else
showMessage(_("JUNK AT END OF RESPONSE: " + out)); showMessage(_("JUNK AT END OF RESPONSE: " + out));

View File

@@ -85,6 +85,7 @@ private:
bool acceptsBreakpoint(BreakpointModelId id) const; bool acceptsBreakpoint(BreakpointModelId id) const;
void attemptBreakpointSynchronization(); void attemptBreakpointSynchronization();
bool attemptBreakpointSynchronizationHelper(QByteArray *command);
void assignValueInDebugger(const WatchData *data, void assignValueInDebugger(const WatchData *data,
const QString &expr, const QVariant &value); const QString &expr, const QVariant &value);