forked from qt-creator/qt-creator
Debugger: Report process state and location from LLDB bridge
Change-Id: I1e65b2f75ff4ebde17f7d8506193cb47474335f6 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -76,8 +76,8 @@ if not gdbLoaded and not cdbLoaded:
|
|||||||
|
|
||||||
|
|
||||||
# One is sufficient.
|
# One is sufficient.
|
||||||
if cdbLoaded or gdbLoaded or lldbLoaded:
|
#if cdbLoaded or gdbLoaded or lldbLoaded:
|
||||||
failReasons = []
|
# failReasons = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
execfile(os.path.join(currentDir, "dumper.py"))
|
execfile(os.path.join(currentDir, "dumper.py"))
|
||||||
|
@@ -860,7 +860,7 @@ def stripForFormat(typeName):
|
|||||||
qqStripForFormat[typeName] = stripped
|
qqStripForFormat[typeName] = stripped
|
||||||
return stripped
|
return stripped
|
||||||
|
|
||||||
def bbsetup(args):
|
def bbsetup(args = ''):
|
||||||
typeCache = {}
|
typeCache = {}
|
||||||
module = sys.modules[__name__]
|
module = sys.modules[__name__]
|
||||||
for key, value in module.__dict__.items():
|
for key, value in module.__dict__.items():
|
||||||
|
@@ -121,8 +121,19 @@ def threadsData(options):
|
|||||||
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
|
||||||
|
stateNames = ["invalid", "unloaded", "connected", "attaching", "launching", "stopped",
|
||||||
|
"running", "stepping", "crashed", "detached", "exited", "suspended" ]
|
||||||
|
|
||||||
def stateData(options):
|
def stateData(options):
|
||||||
result = "state={},"
|
state = lldb.process.GetState()
|
||||||
|
return "state=\"%s\"," % stateNames[state]
|
||||||
|
|
||||||
|
def locationData(options):
|
||||||
|
thread = lldb.process.GetSelectedThread()
|
||||||
|
frame = thread.GetFrameAtIndex(0)
|
||||||
|
return "location={file=\"%s\",line=\"%s\",addr=\"%s\"}," \
|
||||||
|
% (frame.line_entry.file, frame.line_entry.line, frame.pc)
|
||||||
|
|
||||||
def stackData(options):
|
def stackData(options):
|
||||||
try:
|
try:
|
||||||
@@ -163,6 +174,8 @@ def updateData(parts, localsOptions, stackOptions, threadOptions):
|
|||||||
result += stackData(parseOptions(stackOptions))
|
result += stackData(parseOptions(stackOptions))
|
||||||
if parts & 4:
|
if parts & 4:
|
||||||
result += threadsData(parseOptions(threadOptions))
|
result += threadsData(parseOptions(threadOptions))
|
||||||
|
result += stateData({})
|
||||||
|
result += locationData({})
|
||||||
result += "}"
|
result += "}"
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -274,42 +287,57 @@ def handleBreakpoints(stuff):
|
|||||||
result += "]}}"
|
result += "]}}"
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def doSomeStep(func)
|
def doSync(func):
|
||||||
lldb.debugger.SetAsync(False)
|
lldb.debugger.SetAsync(False)
|
||||||
func()
|
func()
|
||||||
lldb.debugger.SetAsync(True)
|
lldb.debugger.SetAsync(True)
|
||||||
|
|
||||||
|
def createReport():
|
||||||
result = "result={"
|
result = "result={"
|
||||||
result += "},"
|
|
||||||
result += stackData({'threadid': lldb.process.selected_thread.id})
|
result += stackData({'threadid': lldb.process.selected_thread.id})
|
||||||
result += threadsData({})
|
result += threadsData({})
|
||||||
result += stateData()
|
result += stateData({})
|
||||||
|
result += locationData({})
|
||||||
|
result += "}"
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def executeStepNext():
|
def executeNext():
|
||||||
return doSomeStep(lldb.thread.StepOver)
|
doSync(lldb.thread.StepOver)
|
||||||
|
return createReport()
|
||||||
|
|
||||||
def executeStepNextI():
|
def executeNextI():
|
||||||
return doSomeStep(lldb.thread.StepOver)
|
doSync(lldb.thread.StepOver)
|
||||||
|
return createReport()
|
||||||
|
|
||||||
def executeStep():
|
def executeStep():
|
||||||
return doSomeStep(lldb.thread.Step)
|
doSync(lldb.thread.Step)
|
||||||
|
return createReport()
|
||||||
|
|
||||||
def executeStepI():
|
def executeStepI():
|
||||||
return doSomeStep(lldb.thread.StepInstOver)
|
doSync(lldb.thread.StepInstOver)
|
||||||
|
return createReport()
|
||||||
|
|
||||||
def executeStepOut():
|
def executeStepOut():
|
||||||
return doSomeStep(lldb.thread.StepOut)
|
doSync(lldb.thread.StepOut)
|
||||||
|
return createReport()
|
||||||
|
|
||||||
def executeInterrupt():
|
def executeRunToLine():
|
||||||
return doSomeStep(lldb.process.Stop)
|
return "result={error={msg='Not implemented'}}"
|
||||||
|
|
||||||
def executeJumpToLine():
|
def executeJumpToLine():
|
||||||
return doSomeStep(lldb.process.Stop)
|
return "result={error={msg='Not implemented'}}"
|
||||||
|
|
||||||
|
def continueInferior():
|
||||||
|
#lldb.debugger.HandleCommand("process continue")
|
||||||
|
lldb.process.Continue()
|
||||||
|
return "result={state='running'}"
|
||||||
|
|
||||||
def interruptInferior():
|
def interruptInferior():
|
||||||
#lldb.process.Continue()
|
lldb.debugger.SetAsync(False)
|
||||||
lldb.debugger.HandleCommand("process continue")
|
lldb.process.Stop()
|
||||||
return "result={}"
|
#lldb.process.SendAsyncInterrupt()
|
||||||
|
lldb.debugger.SetAsync(True)
|
||||||
|
return createReport()
|
||||||
|
|
||||||
def setupInferior(fileName):
|
def setupInferior(fileName):
|
||||||
lldb.debugger.HandleCommand("target create '%s'" % fileName)
|
lldb.debugger.HandleCommand("target create '%s'" % fileName)
|
||||||
@@ -373,4 +401,4 @@ if False:
|
|||||||
+ "pcoffset='${function.pc-offset}',"
|
+ "pcoffset='${function.pc-offset}',"
|
||||||
+ "stopreason='${thread.stop-reason}'"
|
+ "stopreason='${thread.stop-reason}'"
|
||||||
#+ "returnvalue='${thread.return-value}'"
|
#+ "returnvalue='${thread.return-value}'"
|
||||||
+ "\},"
|
+ "\},")
|
||||||
|
@@ -316,6 +316,7 @@ void LldbEngine::handleResponse(const LldbResponse &response)
|
|||||||
refreshThreads(all.findChild("threads"));
|
refreshThreads(all.findChild("threads"));
|
||||||
refreshTypeInfo(all.findChild("typeinfo"));
|
refreshTypeInfo(all.findChild("typeinfo"));
|
||||||
refreshState(all.findChild("state"));
|
refreshState(all.findChild("state"));
|
||||||
|
refreshLocation(all.findChild("location"));
|
||||||
refreshModules(all.findChild("modules"));
|
refreshModules(all.findChild("modules"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,7 +784,7 @@ static bool isEatable(char c)
|
|||||||
void LldbEngine::readLldbStandardOutput()
|
void LldbEngine::readLldbStandardOutput()
|
||||||
{
|
{
|
||||||
QByteArray out = m_lldbProc.readAllStandardOutput();
|
QByteArray out = m_lldbProc.readAllStandardOutput();
|
||||||
showMessage(_("Lldb stdout: " + out));
|
//showMessage(_("Lldb stdout: " + out));
|
||||||
qDebug("\nLLDB RAW STDOUT: '%s'", quoteUnprintable(out).constData());
|
qDebug("\nLLDB RAW STDOUT: '%s'", quoteUnprintable(out).constData());
|
||||||
// Remove embedded backspace characters
|
// Remove embedded backspace characters
|
||||||
int j = 1;
|
int j = 1;
|
||||||
@@ -843,7 +844,7 @@ void LldbEngine::readLldbStandardOutput()
|
|||||||
if (m_inbuffer.mid(pos1 + 1).startsWith("stopped")) {
|
if (m_inbuffer.mid(pos1 + 1).startsWith("stopped")) {
|
||||||
m_inbuffer.clear();
|
m_inbuffer.clear();
|
||||||
notifyInferiorSpontaneousStop();
|
notifyInferiorSpontaneousStop();
|
||||||
gotoLocation(stackHandler()->currentFrame());
|
//gotoLocation(stackHandler()->currentFrame());
|
||||||
updateAll();
|
updateAll();
|
||||||
} else if (m_inbuffer.mid(pos1 + 1).startsWith("exited")) {
|
} else if (m_inbuffer.mid(pos1 + 1).startsWith("exited")) {
|
||||||
m_inbuffer.clear();
|
m_inbuffer.clear();
|
||||||
@@ -859,7 +860,7 @@ void LldbEngine::handleOutput2(const QByteArray &data)
|
|||||||
{
|
{
|
||||||
LldbResponse response;
|
LldbResponse response;
|
||||||
response.data = data;
|
response.data = data;
|
||||||
showMessage(_(data));
|
//showMessage(_(data));
|
||||||
QTC_ASSERT(!m_commands.isEmpty(), qDebug() << "RESPONSE: " << data; return);
|
QTC_ASSERT(!m_commands.isEmpty(), qDebug() << "RESPONSE: " << data; return);
|
||||||
LldbCommand cmd = m_commands.dequeue();
|
LldbCommand cmd = m_commands.dequeue();
|
||||||
// FIXME: Find a way to tell LLDB to no echo input.
|
// FIXME: Find a way to tell LLDB to no echo input.
|
||||||
@@ -962,7 +963,7 @@ GdbMi LldbEngine::parseResultFromString(QByteArray out)
|
|||||||
else
|
else
|
||||||
showMessage(_("JUNK AT END OF RESPONSE: " + out));
|
showMessage(_("JUNK AT END OF RESPONSE: " + out));
|
||||||
|
|
||||||
all.fromStringMultiple(out);
|
all.fromString(out);
|
||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1067,6 +1068,15 @@ void LldbEngine::refreshState(const GdbMi &reportedState)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LldbEngine::refreshLocation(const GdbMi &reportedLocation)
|
||||||
|
{
|
||||||
|
if (reportedLocation.isValid()) {
|
||||||
|
QByteArray file = reportedLocation.findChild("file").data();
|
||||||
|
int line = reportedLocation.findChild("line").data().toInt();
|
||||||
|
gotoLocation(Location(QString::fromUtf8(file), line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool LldbEngine::hasCapability(unsigned cap) const
|
bool LldbEngine::hasCapability(unsigned cap) const
|
||||||
{
|
{
|
||||||
return cap & (ReloadModuleCapability|BreakConditionCapability);
|
return cap & (ReloadModuleCapability|BreakConditionCapability);
|
||||||
|
@@ -132,6 +132,7 @@ private:
|
|||||||
void refreshLocals(const GdbMi &vars);
|
void refreshLocals(const GdbMi &vars);
|
||||||
void refreshTypeInfo(const GdbMi &typeInfo);
|
void refreshTypeInfo(const GdbMi &typeInfo);
|
||||||
void refreshState(const GdbMi &state);
|
void refreshState(const GdbMi &state);
|
||||||
|
void refreshLocation(const GdbMi &location);
|
||||||
void refreshModules(const GdbMi &modules);
|
void refreshModules(const GdbMi &modules);
|
||||||
|
|
||||||
enum DataKind { LocalsData = 1, StackData = 2, ThreadData = 4 };
|
enum DataKind { LocalsData = 1, StackData = 2, ThreadData = 4 };
|
||||||
|
Reference in New Issue
Block a user