forked from qt-creator/qt-creator
Debugger: Select topmost frame with usable data also with LLDB
Task-number: QTCREATORBUG-11597 Change-Id: I5d95c9172e90b82f5671427283cf46e924456c4c Reviewed-by: Christian Stenger <christian.stenger@digia.com>
This commit is contained in:
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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(); }
|
||||
|
Reference in New Issue
Block a user