Commit 1d1695c2 authored by hjk's avatar hjk
Browse files

Debugger: Move breakpoint markers with LLDB



Task-number: QTCREATORBUG-11564
Change-Id: I98044c641ad68431176d8ef54e8e1ec1bef296bc
Reviewed-by: default avatarChristian Stenger <christian.stenger@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 11cc292d
......@@ -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();
BreakpointResponseId rid = BreakpointResponseId(bkpt["lldbid"].data());
BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data());
if (!id.isValid())
id = handler->findBreakpointByResponseId(rid);
BreakpointResponse response = handler->response(id);
BreakpointResponseId rid = BreakpointResponseId(bkpt["lldbid"].data());
if (added)
response.id = rid;
QTC_CHECK(response.id == rid);
......@@ -616,35 +622,35 @@ 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();
if (added) {
// Added.
GdbMi locations = bkpt["locations"];
const int numChild = locations.children().size();
if (numChild > 1) {
foreach (const GdbMi &location, locations.children()) {
const int locid = location["locid"].toInt();
BreakpointResponse sub;
sub.id = BreakpointResponseId(rid.majorPart(), locid);
sub.type = response.type;
sub.address = location["addr"].toAddress();
sub.functionName = location["func"].toUtf8();
handler->insertSubBreakpoint(id, sub);
}
} else if (numChild == 1) {
const GdbMi location = locations.childAt(0);
response.address = location["addr"].toAddress();
response.functionName = location["func"].toUtf8();
} else {
QTC_CHECK(false);
response.fileName = bkpt["file"].toUtf8();
response.lineNumber = bkpt["line"].toInt();
GdbMi locations = bkpt["locations"];
const int numChild = locations.children().size();
if (numChild > 1) {
foreach (const GdbMi &location, locations.children()) {
const int locid = location["locid"].toInt();
BreakpointResponse sub;
sub.id = BreakpointResponseId(rid.majorPart(), locid);
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);
}
handler->setResponse(id, response);
handler->notifyBreakpointInsertOk(id);
} else if (numChild == 1) {
const GdbMi location = locations.childAt(0);
response.address = location["addr"].toAddress();
response.functionName = location["func"].toUtf8();
} else {
// Changed.
handler->setResponse(id, response);
handler->notifyBreakpointChangeOk(id);
QTC_CHECK(false);
}
handler->setResponse(id, response);
if (added)
handler->notifyBreakpointInsertOk(id);
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);
}
}
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)();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment