forked from qt-creator/qt-creator
Debugger: Move breakpoint markers with LLDB
Task-number: QTCREATORBUG-11564 Change-Id: I98044c641ad68431176d8ef54e8e1ec1bef296bc Reviewed-by: Christian Stenger <christian.stenger@digia.com> Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -316,6 +316,7 @@ class Dumper(DumperBase):
|
||||
self.isInterrupting_ = False
|
||||
self.dummyValue = None
|
||||
self.types_ = {}
|
||||
self.breakpointsToCheck = set([])
|
||||
|
||||
def enterSubItem(self, item):
|
||||
if isinstance(item.name, lldb.SBValue):
|
||||
@@ -804,6 +805,14 @@ class Dumper(DumperBase):
|
||||
result += '],current-thread-id="%s"},' % self.currentThread().id
|
||||
self.report(result)
|
||||
|
||||
def reportChangedBreakpoints(self):
|
||||
for i in xrange(0, self.target.GetNumBreakpoints()):
|
||||
bp = self.target.GetBreakpointAtIndex(i)
|
||||
if bp.GetID() in self.breakpointsToCheck:
|
||||
if bp.GetNumLocations():
|
||||
self.breakpointsToCheck.remove(bp.GetID())
|
||||
self.report('breakpoint-changed={%s}' % self.describeBreakpoint(bp))
|
||||
|
||||
def firstUsableFrame(self, thread):
|
||||
for i in xrange(10):
|
||||
frame = thread.GetFrameAtIndex(i)
|
||||
@@ -1283,6 +1292,7 @@ class Dumper(DumperBase):
|
||||
self.reportLocation()
|
||||
self.reportVariables()
|
||||
self.reportRegisters()
|
||||
self.reportChangedBreakpoints()
|
||||
elif type == lldb.SBProcess.eBroadcastBitInterrupt:
|
||||
pass
|
||||
elif type == lldb.SBProcess.eBroadcastBitSTDOUT:
|
||||
@@ -1297,13 +1307,12 @@ class Dumper(DumperBase):
|
||||
elif type == lldb.SBProcess.eBroadcastBitProfileData:
|
||||
pass
|
||||
|
||||
def describeBreakpoint(self, bp, modelId):
|
||||
def describeBreakpoint(self, bp):
|
||||
isWatch = isinstance(bp, lldb.SBWatchpoint)
|
||||
if isWatch:
|
||||
result = 'lldbid="%s"' % (qqWatchpointOffset + bp.GetID())
|
||||
else:
|
||||
result = 'lldbid="%s"' % bp.GetID()
|
||||
result += ',modelid="%s"' % modelId
|
||||
if not bp.IsValid():
|
||||
return
|
||||
result += ',hitcount="%s"' % bp.GetHitCount()
|
||||
@@ -1318,18 +1327,25 @@ class Dumper(DumperBase):
|
||||
result += ',valid="%s"' % (1 if bp.IsValid() else 0)
|
||||
result += ',ignorecount="%s"' % bp.GetIgnoreCount()
|
||||
result += ',locations=['
|
||||
lineEntry = None
|
||||
if hasattr(bp, 'GetNumLocations'):
|
||||
for i in xrange(bp.GetNumLocations()):
|
||||
loc = bp.GetLocationAtIndex(i)
|
||||
addr = loc.GetAddress()
|
||||
lineEntry = addr.GetLineEntry()
|
||||
result += '{locid="%s"' % loc.GetID()
|
||||
result += ',func="%s"' % addr.GetFunction().GetName()
|
||||
result += ',enabled="%s"' % (1 if loc.IsEnabled() else 0)
|
||||
result += ',resolved="%s"' % (1 if loc.IsResolved() else 0)
|
||||
result += ',valid="%s"' % (1 if loc.IsValid() else 0)
|
||||
result += ',ignorecount="%s"' % loc.GetIgnoreCount()
|
||||
result += ',file="%s"' % lineEntry.GetFileSpec()
|
||||
result += ',line="%s"' % lineEntry.GetLine()
|
||||
result += ',addr="%s"},' % loc.GetLoadAddress()
|
||||
result += '],'
|
||||
result += ']'
|
||||
if lineEntry is not None:
|
||||
result += ',file="%s"' % lineEntry.GetFileSpec()
|
||||
result += ',line="%s"' % lineEntry.GetLine()
|
||||
return result
|
||||
|
||||
def createBreakpointAtMain(self):
|
||||
@@ -1339,26 +1355,26 @@ class Dumper(DumperBase):
|
||||
def addBreakpoint(self, args):
|
||||
bpType = args["type"]
|
||||
if bpType == BreakpointByFileAndLine:
|
||||
bpNew = self.target.BreakpointCreateByLocation(
|
||||
bp = self.target.BreakpointCreateByLocation(
|
||||
str(args["file"]), int(args["line"]))
|
||||
elif bpType == BreakpointByFunction:
|
||||
bpNew = self.target.BreakpointCreateByName(args["function"])
|
||||
bp = self.target.BreakpointCreateByName(args["function"])
|
||||
elif bpType == BreakpointByAddress:
|
||||
bpNew = self.target.BreakpointCreateByAddress(args["address"])
|
||||
bp = self.target.BreakpointCreateByAddress(args["address"])
|
||||
elif bpType == BreakpointAtMain:
|
||||
bpNew = self.createBreakpointAtMain()
|
||||
bp = self.createBreakpointAtMain()
|
||||
elif bpType == BreakpointByFunction:
|
||||
bpNew = self.target.BreakpointCreateByName(args["function"])
|
||||
bp = self.target.BreakpointCreateByName(args["function"])
|
||||
elif bpType == BreakpointAtThrow:
|
||||
bpNew = self.target.BreakpointCreateForException(
|
||||
bp = self.target.BreakpointCreateForException(
|
||||
lldb.eLanguageTypeC_plus_plus, False, True)
|
||||
elif bpType == BreakpointAtCatch:
|
||||
bpNew = self.target.BreakpointCreateForException(
|
||||
bp = self.target.BreakpointCreateForException(
|
||||
lldb.eLanguageTypeC_plus_plus, True, False)
|
||||
elif bpType == WatchpointAtAddress:
|
||||
error = lldb.SBError()
|
||||
bpNew = self.target.WatchAddress(args["address"], 4, False, True, error)
|
||||
#warn("BPNEW: %s" % bpNew)
|
||||
bp = self.target.WatchAddress(args["address"], 4, False, True, error)
|
||||
#warn("BPNEW: %s" % bp)
|
||||
self.reportError(error)
|
||||
elif bpType == WatchpointAtExpression:
|
||||
# FIXME: Top level-only for now.
|
||||
@@ -1366,7 +1382,7 @@ class Dumper(DumperBase):
|
||||
frame = self.currentFrame()
|
||||
value = frame.FindVariable(args["expression"])
|
||||
error = lldb.SBError()
|
||||
bpNew = self.target.WatchAddress(value.GetLoadAddress(),
|
||||
bp = self.target.WatchAddress(value.GetLoadAddress(),
|
||||
value.GetByteSize(), False, True, error)
|
||||
except:
|
||||
return self.target.BreakpointCreateByName(None)
|
||||
@@ -1374,13 +1390,14 @@ class Dumper(DumperBase):
|
||||
# This leaves the unhandled breakpoint in a (harmless)
|
||||
# "pending" state.
|
||||
return self.target.BreakpointCreateByName(None)
|
||||
bpNew.SetIgnoreCount(int(args["ignorecount"]))
|
||||
if hasattr(bpNew, 'SetCondition'):
|
||||
bpNew.SetCondition(self.hexdecode(args["condition"]))
|
||||
bpNew.SetEnabled(int(args["enabled"]))
|
||||
if hasattr(bpNew, 'SetOneShot'):
|
||||
bpNew.SetOneShot(int(args["oneshot"]))
|
||||
return bpNew
|
||||
bp.SetIgnoreCount(int(args["ignorecount"]))
|
||||
if hasattr(bp, 'SetCondition'):
|
||||
bp.SetCondition(self.hexdecode(args["condition"]))
|
||||
bp.SetEnabled(int(args["enabled"]))
|
||||
if hasattr(bp, 'SetOneShot'):
|
||||
bp.SetOneShot(int(args["oneshot"]))
|
||||
self.breakpointsToCheck.add(bp.GetID())
|
||||
return bp
|
||||
|
||||
def changeBreakpoint(self, args):
|
||||
id = int(args["lldbid"])
|
||||
@@ -1393,6 +1410,7 @@ class Dumper(DumperBase):
|
||||
bp.SetEnabled(int(args["enabled"]))
|
||||
if hasattr(bp, 'SetOneShot'):
|
||||
bp.SetOneShot(int(args["oneshot"]))
|
||||
return bp
|
||||
|
||||
def removeBreakpoint(self, args):
|
||||
id = int(args['lldbid'])
|
||||
@@ -1408,30 +1426,27 @@ class Dumper(DumperBase):
|
||||
if needStop:
|
||||
error = self.process.Stop()
|
||||
|
||||
result = 'bkpts=['
|
||||
for bp in args['bkpts']:
|
||||
operation = bp['operation']
|
||||
modelId = bp['modelid']
|
||||
|
||||
if operation == 'add':
|
||||
bpNew = self.addBreakpoint(bp)
|
||||
result += '{operation="added",%s}' \
|
||||
% self.describeBreakpoint(bpNew, bp["modelid"])
|
||||
self.report('breakpoint-added={%s,modelid="%s"}'
|
||||
% (self.describeBreakpoint(bpNew), modelId))
|
||||
|
||||
elif operation == 'change':
|
||||
bpNew = self.changeBreakpoint(bp)
|
||||
result += '{operation="changed",%s' \
|
||||
% self.describeBreakpoint(bpNew, bp["modelid"])
|
||||
self.report('breakpoint-changed={%s,modelid="%s"}'
|
||||
% (self.describeBreakpoint(bpNew), modelId))
|
||||
|
||||
elif operation == 'remove':
|
||||
bpDead = self.removeBreakpoint(bp)
|
||||
result += '{operation="removed",modelid="%s"}' % bp["modelid"]
|
||||
|
||||
result += "]"
|
||||
self.report('breakpoint-removed={modelid="%s"}' % modelId)
|
||||
|
||||
if needStop:
|
||||
error = self.process.Continue()
|
||||
|
||||
self.report(result)
|
||||
|
||||
def listModules(self, args):
|
||||
result = 'modules=['
|
||||
|
@@ -415,8 +415,12 @@ void LldbEngine::handleResponse(const QByteArray &response)
|
||||
refreshModules(item);
|
||||
else if (name == "symbols")
|
||||
refreshSymbols(item);
|
||||
else if (name == "bkpts")
|
||||
refreshBreakpoints(item);
|
||||
else if (name == "breakpoint-added")
|
||||
refreshAddedBreakpoint(item);
|
||||
else if (name == "breakpoint-changed")
|
||||
refreshChangedBreakpoint(item);
|
||||
else if (name == "breakpoint-removed")
|
||||
refreshRemovedBreakpoint(item);
|
||||
else if (name == "output")
|
||||
refreshOutput(item);
|
||||
else if (name == "disassembly")
|
||||
@@ -605,9 +609,11 @@ void LldbEngine::attemptBreakpointSynchronization()
|
||||
void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
|
||||
{
|
||||
BreakHandler *handler = breakHandler();
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
BreakpointResponse response = handler->response(id);
|
||||
BreakpointResponseId rid = BreakpointResponseId(bkpt["lldbid"].data());
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
if (!id.isValid())
|
||||
id = handler->findBreakpointByResponseId(rid);
|
||||
BreakpointResponse response = handler->response(id);
|
||||
if (added)
|
||||
response.id = rid;
|
||||
QTC_CHECK(response.id == rid);
|
||||
@@ -616,9 +622,9 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
|
||||
response.ignoreCount = bkpt["ignorecount"].toInt();
|
||||
response.condition = QByteArray::fromHex(bkpt["condition"].data());
|
||||
response.hitCount = bkpt["hitcount"].toInt();
|
||||
response.fileName = bkpt["file"].toUtf8();
|
||||
response.lineNumber = bkpt["line"].toInt();
|
||||
|
||||
if (added) {
|
||||
// Added.
|
||||
GdbMi locations = bkpt["locations"];
|
||||
const int numChild = locations.children().size();
|
||||
if (numChild > 1) {
|
||||
@@ -629,6 +635,8 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
|
||||
sub.type = response.type;
|
||||
sub.address = location["addr"].toAddress();
|
||||
sub.functionName = location["func"].toUtf8();
|
||||
sub.fileName = location["file"].toUtf8();
|
||||
sub.lineNumber = location["line"].toInt();
|
||||
handler->insertSubBreakpoint(id, sub);
|
||||
}
|
||||
} else if (numChild == 1) {
|
||||
@@ -639,12 +647,10 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added)
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
handler->setResponse(id, response);
|
||||
if (added)
|
||||
handler->notifyBreakpointInsertOk(id);
|
||||
} else {
|
||||
// Changed.
|
||||
handler->setResponse(id, response);
|
||||
else
|
||||
handler->notifyBreakpointChangeOk(id);
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::refreshDisassembly(const GdbMi &data)
|
||||
@@ -694,25 +700,26 @@ void LldbEngine::refreshOutput(const GdbMi &output)
|
||||
showMessage(QString::fromUtf8(data), ch);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshBreakpoints(const GdbMi &bkpts)
|
||||
void LldbEngine::refreshAddedBreakpoint(const GdbMi &bkpt)
|
||||
{
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
QTC_CHECK(breakHandler()->state(id) == BreakpointInsertProceeding);
|
||||
updateBreakpointData(bkpt, true);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshChangedBreakpoint(const GdbMi &bkpt)
|
||||
{
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
QTC_CHECK(!id.isValid() || breakHandler()->state(id) == BreakpointChangeProceeding);
|
||||
updateBreakpointData(bkpt, false);
|
||||
}
|
||||
|
||||
void LldbEngine::refreshRemovedBreakpoint(const GdbMi &bkpt)
|
||||
{
|
||||
BreakHandler *handler = breakHandler();
|
||||
foreach (const GdbMi &bkpt, bkpts.children()) {
|
||||
QByteArray op = bkpt["operation"].data();
|
||||
if (op == "added") {
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
QTC_CHECK(handler->state(id) == BreakpointInsertProceeding);
|
||||
updateBreakpointData(bkpt, true);
|
||||
} else if (op == "changed") {
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
QTC_CHECK(handler->state(id) == BreakpointChangeProceeding);
|
||||
updateBreakpointData(bkpt, false);
|
||||
} else if (op == "removed") {
|
||||
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
|
||||
QTC_CHECK(handler->state(id) == BreakpointRemoveProceeding);
|
||||
handler->notifyBreakpointRemoveOk(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::loadSymbols(const QString &moduleName)
|
||||
|
@@ -174,7 +174,9 @@ private:
|
||||
void refreshModules(const GdbMi &modules);
|
||||
void refreshSymbols(const GdbMi &symbols);
|
||||
void refreshOutput(const GdbMi &output);
|
||||
void refreshBreakpoints(const GdbMi &bkpts);
|
||||
void refreshAddedBreakpoint(const GdbMi &bkpts);
|
||||
void refreshChangedBreakpoint(const GdbMi &bkpts);
|
||||
void refreshRemovedBreakpoint(const GdbMi &bkpts);
|
||||
void runContinuation(const GdbMi &data);
|
||||
|
||||
typedef void (LldbEngine::*LldbCommandContinuation)();
|
||||
|
Reference in New Issue
Block a user