From 4269ce4e38bc4cd8d10f405c2a23e9f43a100031 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 12 Apr 2013 14:41:05 +0200 Subject: [PATCH] Debugger: Progress on LLDB state handling Change-Id: Iadf9c7026a3da0adeec8340729a303bbbee57c24 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 1 + share/qtcreator/dumper/lbridge.py | 173 +++++++++-------------- src/plugins/debugger/lldb/lldbengine.cpp | 37 +++-- src/plugins/debugger/lldb/lldbengine.h | 1 + 4 files changed, 98 insertions(+), 114 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index 9b5af63fe00..6903a38c506 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -259,6 +259,7 @@ NamespaceCode = gdb.TYPE_CODE_NAMESPACE #Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point. #Code = gdb.TYPE_CODE_MODULE # Fortran #Code = gdb.TYPE_CODE_INTERNAL_FUNCTION +SimpleValueCode = -1 ####################################################################### diff --git a/share/qtcreator/dumper/lbridge.py b/share/qtcreator/dumper/lbridge.py index b0663e6b230..b9456d5681b 100644 --- a/share/qtcreator/dumper/lbridge.py +++ b/share/qtcreator/dumper/lbridge.py @@ -109,17 +109,13 @@ class Value: def fields(self): return [Value(self.raw.GetChildAtIndex(i)) for i in range(self.raw.num_children)] -currentThread = None -currentFrame = None +def currentFrame(): + currentThread = lldb.process.GetThreadAtIndex(0) + return currentThread.GetFrameAtIndex(0) def listOfLocals(varList): - global currentThread - global currentFrame - items = [] - currentThread = lldb.process.GetThreadAtIndex(0) - currentFrame = currentThread.GetFrameAtIndex(0) - for var in currentFrame.variables: + for var in currentFrame().variables: item = LocalItem() item.iname = "local." + var.name item.name = var.name @@ -160,7 +156,7 @@ def threadsData(options): result += ",file=\"%s\"" % frame.line_entry.file result += "}}," - result += "],current-thread-id=\"%s\"}" % lldb.process.selected_thread.id + result += "],current-thread-id=\"%s\"}," % lldb.process.selected_thread.id return result # See lldb.StateType @@ -256,12 +252,9 @@ def onBreak(): result = "*stopped,frame={....}" print result -def handleBreakpoints(opts, toAdd, toChange, toRemove): - #todo = json.loads(stuff) - #dumpJson(todo) +def handleBreakpoints(options, toAdd, toChange, toRemove): #target = lldb.debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT) target = lldb.debugger.GetTargetAtIndex(0) - #target = lldb.target result = "result={bkpts={added=[" @@ -282,8 +275,8 @@ def handleBreakpoints(opts, toAdd, toChange, toRemove): #"breakpoint command add 1 -o \"import time; print time.asctime()\" #cmd = "script print(11111111)" cmd = "continue" - lldb.debugger.HandleCommand( - "breakpoint command add -o 'script onBreak()' %s" % bpNew.GetID()) + #lldb.debugger.HandleCommand( + # "breakpoint command add -o 'script onBreak()' %s" % bpNew.GetID()) result += dumpBreakpoint(bpNew, bp["modelid"]) @@ -306,127 +299,99 @@ def handleBreakpoints(opts, toAdd, toChange, toRemove): result += "]}}" return result -def doSync(func): - lldb.debugger.SetAsync(False) - func() - lldb.debugger.SetAsync(True) - -def createReport(options): +def createStoppedReport(options): result = "result={" - result += bb(options["locals"]) + 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 += "token=\"%s\"," % options["token"] result += "}" return result -def executeNext(opts): - doSync(lldb.thread.StepOver) - return createReport(opts) +def createRunReport(options): + result = "result={" + #result += stateData({}) + result += "state=\"running\"," + result += "token=\"%s\"," % options["token"] + result += "}" + return result -def executeNextI(opts): - doSync(lldb.thread.StepOver) - return createReport(opts) +def createReport(options): + return createStoppedReport(options) -def executeStep(opts): - lldb.thread.Step() - return createReport(opts) +def executeNext(options): + lldb.thread.StepOver() + return createRunReport(options) -def executeStepI(opts): - doSync(lldb.thread.StepInstOver) - return createReport(opts) +def executeNextI(options): + lldb.thread.StepOver() + return createRunReport(options) -def executeStepOut(opts): - doSync(lldb.thread.StepOut) - return createReport(opts) +def executeStep(options): + lldb.thread.StepInto() + return createRunReport(options) -def executeRunToLine(opts): - return "result={error={msg='Not implemented'}}" +def executeStepI(options): + lldb.thread.StepInstOver() + return createRunReport(options) -def executeJumpToLine(opts): - return "result={error={msg='Not implemented'}}" +def executeStepOut(options): + lldb.thread.StepOutOfFrame(currentFrame()) + return createRunReport(options) -def continueInferior(opts): - #lldb.debugger.HandleCommand("process continue") +def executeRunToLine(options, file, line): + 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() - return "result={state='running'}" + return "result={state=\"running\"}" -def interruptInferior(opts): - lldb.debugger.SetAsync(False) +def interruptInferior(options): lldb.process.Stop() - #lldb.process.SendAsyncInterrupt() - lldb.debugger.SetAsync(True) - return createReport() + return "result={state=\"interrupting\"}" -def setupInferior(opts, fileName): - lldb.debugger.HandleCommand("target create '%s'" % fileName) - return "result={state=\"inferiorsetupok\"}" +def setupInferior(options, fileName): + msg = lldb.debugger.HandleCommand("target create '%s'" % fileName) + return "result={state=\"inferiorsetupok\",msg=\"%s\"}" % msg -def runEngine(opts): - lldb.debugger.HandleCommand("process launch") - return "result={state=\"enginerunok\"}" +def runEngine(options): + msg = lldb.debugger.HandleCommand("process launch") + return "result={state=\"enginerunok\",msg=\"%s\"}" % msg -def activateFrame(opts, frame): +def activateFrame(options, frame): lldb.debugger.HandleCommand("frame select " + frame) + return createStoppedReport(options) -def selectThread(opts, thread): +def selectThread(options, 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) +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 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 execfile(os.path.join(currentDir, "dumper.py")) diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 798780d99a9..a11fb59373e 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -204,8 +204,16 @@ void LldbEngine::setupInferior() void LldbEngine::runEngine() { QTC_ASSERT(state() == EngineRunRequested, qDebug() << state()); + + QByteArray command; + bool done = attemptBreakpointSynchronizationHelper(&command); + if (done) { + runEngine2(); + return; + } + m_continuations.append(&LldbEngine::runEngine2); - attemptBreakpointSynchronization(); + runCommand("handleBreakpoints", command); } void LldbEngine::runEngine2() @@ -329,14 +337,8 @@ bool LldbEngine::acceptsBreakpoint(BreakpointModelId id) const && 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(); foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { @@ -407,11 +409,24 @@ void LldbEngine::attemptBreakpointSynchronization() 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) { showMessage(_("BREAKPOINTS ARE NOT FULLY SYNCHRONIZED")); - runCommand("handleBreakpoints", - '[' + toAdd + "],[" + toChange + "],[" + toRemove + ']'); + runCommand("handleBreakpoints", command); } else { showMessage(_("BREAKPOINTS ARE SYNCHRONIZED")); } @@ -891,6 +906,8 @@ GdbMi LldbEngine::parseResultFromString(QByteArray out) out = out.mid(pos); if (out.endsWith('\'')) out.chop(1); + else if (out.endsWith('"')) + out.chop(1); else showMessage(_("JUNK AT END OF RESPONSE: " + out)); diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 0bb94637ea8..c0685883fee 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -85,6 +85,7 @@ private: bool acceptsBreakpoint(BreakpointModelId id) const; void attemptBreakpointSynchronization(); + bool attemptBreakpointSynchronizationHelper(QByteArray *command); void assignValueInDebugger(const WatchData *data, const QString &expr, const QVariant &value);