From 8931a14afe50045537c30865183a679d96c7a79d Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 6 Mar 2014 12:04:47 +0100 Subject: [PATCH] Debugger: Select topmost frame with usable data also with LLDB Task-number: QTCREATORBUG-11597 Change-Id: I5d95c9172e90b82f5671427283cf46e924456c4c Reviewed-by: Christian Stenger --- share/qtcreator/debugger/lldbbridge.py | 57 +++++++++++++++--------- src/plugins/debugger/lldb/lldbengine.cpp | 50 ++++++++++++++++----- src/plugins/debugger/lldb/lldbengine.h | 3 ++ src/plugins/debugger/stackhandler.cpp | 10 +++++ src/plugins/debugger/stackhandler.h | 1 + 5 files changed, 87 insertions(+), 34 deletions(-) diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index dabd4587b89..c1ccf4f8aee 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -831,16 +831,10 @@ class Dumper(DumperBase): if not thread: self.report('msg="No thread"') return - frame = thread.GetSelectedFrame() - if frame: - frameId = frame.GetFrameID() - else: - frameId = 0; (n, isLimited) = (limit, True) if limit > 0 else (thread.GetNumFrames(), False) - result = 'stack={current-frame="%s"' % frameId - result += ',current-thread="%s"' % thread.GetThreadID() + result = 'stack={current-thread="%s"' % thread.GetThreadID() result += ',frames=[' for i in xrange(n): frame = thread.GetFrameAtIndex(i) @@ -849,14 +843,12 @@ class Dumper(DumperBase): break lineEntry = frame.GetLineEntry() line = lineEntry.GetLine() - usable = line != 0 result += '{pc="0x%x"' % frame.GetPC() result += ',level="%d"' % frame.idx result += ',addr="0x%x"' % frame.GetPCAddress().GetLoadAddress(self.target) result += ',func="%s"' % frame.GetFunctionName() result += ',line="%d"' % line result += ',fullname="%s"' % fileName(lineEntry.file) - result += ',usable="%d"' % usable result += ',file="%s"},' % fileName(lineEntry.file) result += ']' result += ',hasmore="%d"' % isLimited @@ -864,6 +856,20 @@ class Dumper(DumperBase): result += '}' self.report(result) + def reportStackPosition(self): + thread = self.currentThread() + if not thread: + self.report('msg="No thread"') + return + frame = thread.GetSelectedFrame() + if frame: + self.report('stack-position={id="%s"}' % frame.GetFrameID()) + else: + self.report('stack-position={id="-1"}') + + def reportStackTop(self): + self.report('stack-top={}') + def putBetterType(self, type): try: self.currentType = type.GetName() @@ -1196,8 +1202,8 @@ class Dumper(DumperBase): state = self.process.GetState() if state == lldb.eStateStopped: self.reportStack() + self.reportStackPosition() self.reportThreads() - self.reportLocation() self.reportVariables() def reportRegisters(self, _ = None): @@ -1284,10 +1290,8 @@ class Dumper(DumperBase): stoppedThread = self.firstStoppedThread() if stoppedThread: self.process.SetSelectedThread(stoppedThread) - usableFrame = self.firstUsableFrame(stoppedThread) - if usableFrame: - stoppedThread.SetSelectedFrame(usableFrame) self.reportStack({'stacklimit': 20}) + self.reportStackTop() self.reportThreads() self.reportLocation() self.reportVariables() @@ -1564,9 +1568,7 @@ class Dumper(DumperBase): self.currentThread().SetSelectedFrame(args['index']) state = self.process.GetState() if state == lldb.eStateStopped: - self.reportStack(args) - self.reportThreads() - self.reportLocation() + self.reportStackPosition() self.reportVariables() def selectThread(self, args): @@ -1601,19 +1603,30 @@ class Dumper(DumperBase): self.reportVariables(args) def disassemble(self, args): - frame = self.currentFrame(); - function = frame.GetFunction() - name = function.GetName() + functionName = args.get('function', '') + flavor = args.get('flavor', '') + function = None + if len(functionName): + functions = self.target.FindFunctions(functionName).functions + if len(functions): + function = functions[0] + if function: + base = function.GetStartAddress().GetLoadAddress(self.target) + instructions = function.GetInstructions(self.target) + else: + base = args.get('address', 0) + addr = lldb.SBAddress(base, self.target) + instructions = self.target.ReadInstructions(addr, 100) + result = 'disassembly={cookie="%s",' % args['cookie'] result += ',lines=[' - base = function.GetStartAddress().GetLoadAddress(self.target) - for insn in function.GetInstructions(self.target): + for insn in instructions: comment = insn.GetComment(self.target) addr = insn.GetAddress().GetLoadAddress(self.target) result += '{address="%s"' % addr result += ',inst="%s %s"' % (insn.GetMnemonic(self.target), insn.GetOperands(self.target)) - result += ',func_name="%s"' % name + result += ',func_name="%s"' % functionName if comment: result += ',comment="%s"' % comment result += ',offset="%s"},' % (addr - base) diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 754958bf87e..d2bad378b14 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -401,6 +401,10 @@ void LldbEngine::handleResponse(const QByteArray &response) refreshLocals(item); else if (name == "stack") refreshStack(item); + else if (name == "stack-position") + refreshStackPosition(item); + else if (name == "stack-top") + refreshStackTop(item); else if (name == "registers") refreshRegisters(item); else if (name == "threads") @@ -1083,8 +1087,6 @@ void LldbEngine::refreshLocals(const GdbMi &vars) void LldbEngine::refreshStack(const GdbMi &stack) { - //if (!partial) - // emit stackFrameCompleted(); StackHandler *handler = stackHandler(); StackFrames frames; foreach (const GdbMi &item, stack["frames"].children()) { @@ -1101,9 +1103,25 @@ void LldbEngine::refreshStack(const GdbMi &stack) bool canExpand = stack["hasmore"].toInt(); debuggerCore()->action(ExpandStack)->setEnabled(canExpand); handler->setFrames(frames, canExpand); +} - int index = stack["current-frame"].toInt(); +void LldbEngine::refreshStackPosition(const GdbMi &position) +{ + setStackPosition(position["id"].toInt()); +} + +void LldbEngine::refreshStackTop(const GdbMi &) +{ + setStackPosition(stackHandler()->firstUsableIndex()); +} + +void LldbEngine::setStackPosition(int index) +{ + StackHandler *handler = stackHandler(); + handler->setFrames(handler->frames()); handler->setCurrentIndex(index); + if (index >= 0 && index < handler->stackSize()) + gotoLocation(handler->frameAt(index)); } void LldbEngine::refreshRegisters(const GdbMi ®isters) @@ -1221,7 +1239,13 @@ void LldbEngine::fetchDisassembler(DisassemblerAgent *agent) id = ++m_lastAgentId; m_disassemblerAgents.insert(p, id); } - runCommand(Command("disassemble").arg("cookie", id)); + const Location &loc = agent->location(); + Command cmd("disassemble"); + cmd.arg("cookie", id); + cmd.arg("address", loc.address()); + cmd.arg("function", loc.functionName()); + cmd.arg("flavor", debuggerCore()->boolSetting(IntelFlavor) ? "intel" : "att"); + runCommand(cmd); } @@ -1234,10 +1258,11 @@ void LldbEngine::fetchMemory(MemoryAgent *agent, QObject *editorToken, m_memoryAgents.insert(agent, id); } m_memoryAgentTokens.insert(id, editorToken); - runCommand(Command("fetchMemory") - .arg("address", addr) - .arg("length", length) - .arg("cookie", id)); + Command cmd("fetchMemory"); + cmd.arg("address", addr); + cmd.arg("length", length); + cmd.arg("cookie", id); + runCommand(cmd); } void LldbEngine::changeMemory(MemoryAgent *agent, QObject *editorToken, @@ -1249,10 +1274,11 @@ void LldbEngine::changeMemory(MemoryAgent *agent, QObject *editorToken, m_memoryAgents.insert(agent, id); m_memoryAgentTokens.insert(id, editorToken); } - runCommand(Command("writeMemory") - .arg("address", addr) - .arg("data", data.toHex()) - .arg("cookie", id)); + Command cmd("writeMemory"); + cmd.arg("address", addr); + cmd.arg("data", data.toHex()); + cmd.arg("cookie", id); + runCommand(cmd); } void LldbEngine::setRegisterValue(int regnr, const QString &value) diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 571b55cf322..df6c132ed1f 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -166,6 +166,9 @@ private: void refreshAll(const GdbMi &all); void refreshThreads(const GdbMi &threads); void refreshStack(const GdbMi &stack); + void refreshStackPosition(const GdbMi &position); + void refreshStackTop(const GdbMi &position); + void setStackPosition(int index); void refreshRegisters(const GdbMi ®isters); void refreshLocals(const GdbMi &vars); void refreshTypeInfo(const GdbMi &typeInfo); diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp index 6144d2919b9..60e0cb85523 100644 --- a/src/plugins/debugger/stackhandler.cpp +++ b/src/plugins/debugger/stackhandler.cpp @@ -219,6 +219,16 @@ void StackHandler::prependFrames(const StackFrames &frames) emit stackChanged(); } +int StackHandler::firstUsableIndex() const +{ + if (!debuggerCore()->boolSetting(OperateByInstruction)) { + for (int i = 0, n = m_stackFrames.size(); i != n; ++i) + if (m_stackFrames.at(i).isUsable()) + return i; + } + return 0; +} + const StackFrames &StackHandler::frames() const { return m_stackFrames; diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h index b896b5c4003..6fd57f2be1f 100644 --- a/src/plugins/debugger/stackhandler.h +++ b/src/plugins/debugger/stackhandler.h @@ -71,6 +71,7 @@ public: const StackFrames &frames() const; void setCurrentIndex(int index); int currentIndex() const { return m_currentIndex; } + int firstUsableIndex() const; StackFrame currentFrame() const; const StackFrame &frameAt(int index) const { return m_stackFrames.at(index); } int stackSize() const { return m_stackFrames.size(); }