Commit 7d4b9c4b authored by hjk's avatar hjk

Debugger: Move some 'mixed native' code to DumperBase

Prepares reuse in LLDB.

Change-Id: I2238a94937411b80a9ec84ab738aba2146bba50e
Reviewed-by: default avatarhjk <hjk@theqtcompany.com>
parent 5d1e13fb
......@@ -1712,6 +1712,60 @@ class DumperBase:
sys.path.insert(1, head)
self.dumpermodules.append(os.path.splitext(tail)[0])
def sendQmlCommand(self, command, data = ""):
data += '"version":"1","command":"%s"' % command
data = data.replace('"', '\\"')
expr = 'qt_v4DebuggerHook("{%s}")' % data
try:
res = self.parseAndEvaluate(expr)
#print("QML command ok, RES: %s, CMD: %s" % (res, expr))
except RuntimeError as error:
#print("QML command failed: %s: %s" % (expr, error))
res = None
return res
def prepareQmlStep(self, _):
self.sendQmlCommand('prepareStep')
def removeQmlBreakpoint(self, args):
fullName = args['fileName']
lineNumber = args['lineNumber']
#print("Remove QML breakpoint %s:%s" % (fullName, lineNumber))
bp = self.sendQmlCommand('removeBreakpoint',
'"fullName":"%s","lineNumber":"%s",'
% (fullName, lineNumber))
if bp is None:
#print("Direct QML breakpoint removal failed: %s.")
return 0
#print("Removing QML breakpoint: %s" % bp)
return int(bp)
def insertQmlBreakpoint(self, args):
fullName = args['fileName']
lineNumber = args['lineNumber']
print("Insert QML breakpoint %s:%s" % (fullName, lineNumber))
bp = self.doInsertQmlBreakPoint(fullName, lineNumber)
res = self.sendQmlCommand('prepareStep')
#if res is None:
# print("Resetting stepping failed.")
return str(bp)
def doInsertQmlBreakPoint(self, fullName, lineNumber):
pos = fullName.rfind('/')
engineName = "qrc:/" + fullName[pos+1:]
bp = self.sendQmlCommand('insertBreakpoint',
'"fullName":"%s","lineNumber":"%s","engineName":"%s",'
% (fullName, lineNumber, engineName))
if bp is None:
#print("Direct QML breakpoint insertion failed.")
#print("Make pending.")
self.createResolvePendingBreakpointsHookBreakpoint(fullName, lineNumber)
return 0
print("Resolving QML breakpoint: %s" % bp)
return int(bp)
# Some "Enums"
# Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h
......
......@@ -274,6 +274,7 @@ class Dumper(DumperBase):
self.typesToReport = {}
self.qtNamespaceToReport = None
self.qmlEngines = []
self.qmlBreakpoints = []
def prepare(self, args):
self.output = []
......@@ -1811,6 +1812,29 @@ class Dumper(DumperBase):
return ''.join(self.output)
def createResolvePendingBreakpointsHookBreakpoint(self, fullName, lineNumber):
class Resolver(gdb.Breakpoint):
def __init__(self, dumper, fullName, lineNumber):
self.dumper = dumper
self.fullName = fullName
self.lineNumber = lineNumber
spec = "qt_v4ResolvePendingBreakpointsHook"
print("Preparing hook to resolve pending QML breakpoint at %s:%s"
% (self.fullName, self.lineNumber))
super(Resolver, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False)
def stop(self):
bp = self.dumper.doInsertQmlBreakPoint(self.fullName, self.lineNumber)
print("Resolving QML breakpoint %s:%s -> %s"
% (self.fullName, self.lineNumber, bp))
self.enabled = False
return False
self.qmlBreakpoints.append(Resolver(self, fullName, lineNumber))
class CliDumper(Dumper):
def __init__(self):
Dumper.__init__(self)
......@@ -1916,7 +1940,6 @@ class CliDumper(Dumper):
self.putItem(value)
return self.output
def pp(args):
return theDumper.run(args)
......@@ -2056,78 +2079,3 @@ class TriggeredBreakpointHookBreakpoint(gdb.Breakpoint):
TriggeredBreakpointHookBreakpoint()
class ResolvePendingBreakpointsHookBreakpoint(gdb.Breakpoint):
def __init__(self, fullName, lineNumber):
self.fullName = fullName
self.lineNumber = lineNumber
spec = "qt_v4ResolvePendingBreakpointsHook"
print("Preparing hook to resolve pending QML breakpoint at %s:%s"
% (self.fullName, self.lineNumber))
super(ResolvePendingBreakpointsHookBreakpoint, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False)
def stop(self):
bp = doInsertQmlBreakPoint(self.fullName, self.lineNumber)
print("Resolving QML breakpoint %s:%s -> %s"
% (self.fullName, self.lineNumber, bp))
self.enabled = False
return False
def sendQmlCommand(command, data = ""):
data += '"version":"1","command":"%s"' % command
data = data.replace('"', '\\"')
expr = 'qt_v4DebuggerHook("{%s}")' % data
try:
res = gdb.parse_and_eval(expr)
print("QML command ok, RES: %s, CMD: %s" % (res, expr))
gdb.execute("p qt_v4Output")
except RuntimeError as error:
print("QML command failed: gdb.parse_and_eval(%s): %s" % (expr, error))
res = None
return res
def doInsertQmlBreakPoint(fullName, lineNumber):
pos = fullName.rfind('/')
engineName = "qrc:/" + fullName[pos+1:]
bp = sendQmlCommand('insertBreakpoint',
'"fullName":"%s","lineNumber":"%s","engineName":"%s",'
% (fullName, lineNumber, engineName))
if bp is None:
print("Direct QML breakpoint insertion failed.")
print("Make pending.")
ResolvePendingBreakpointsHookBreakpoint(fullName, lineNumber)
return 0
print("Resolving QML breakpoint: %s" % bp)
return int(bp)
def insertQmlBreakpoint(arg):
(fullName, lineNumber) = arg.split(' ')
print("Insert QML breakpoint %s:%s" % (fullName, lineNumber))
bp = doInsertQmlBreakPoint(fullName, lineNumber)
res = sendQmlCommand('prepareStep')
if res is None:
print("Resetting stepping failed.")
return str(bp)
registerCommand("insertQmlBreakpoint", insertQmlBreakpoint)
def removeQmlBreakpoint(arg):
(fullName, lineNumber) = arg.split(' ')
print("Remove QML breakpoint %s:%s" % (fullName, lineNumber))
bp = sendQmlCommand('removeBreakpoint',
'"fullName":"%s","lineNumber":"%s",'
% (fullName, lineNumber))
if bp is None:
print("Direct QML breakpoint removal failed: %s.")
return 0
print("Removing QML breakpoint: %s" % bp)
return int(bp)
registerCommand("removeQmlBreakpoint", removeQmlBreakpoint)
def prepareQmlStep(arg):
sendQmlCommand('prepareStep')
registerCommand("prepareQmlStep", prepareQmlStep)
......@@ -853,6 +853,12 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
notifyInferiorPid(pid);
}
void GdbEngine::runCommand(const DebuggerCommand &command)
{
QByteArray cmd = command.function + "({" + command.args + "})";
postCommand("python theDumper." + cmd);
}
void GdbEngine::postCommand(const QByteArray &command, GdbCommandCallback callback,
const char *callbackName, const QVariant &cookie)
{
......@@ -2054,7 +2060,7 @@ void GdbEngine::executeStep()
notifyInferiorRunRequested();
showStatusMessage(tr("Step requested..."), 5000);
if (isNativeMixedActive()) {
postCommand("prepareQmlStep 0");
runCommand("prepareQmlStep");
postCommand("-exec-continue", RunRequest, CB(handleExecuteContinue));
return;
}
......@@ -2752,8 +2758,11 @@ void GdbEngine::insertBreakpoint(Breakpoint bp)
QVariant vid = QVariant::fromValue(bp);
if (!data.isCppBreakpoint()) {
postCommand("insertQmlBreakpoint " + data.fileName.toUtf8() + ' '
+ QByteArray::number(data.lineNumber));
DebuggerCommand cmd("insertQmlBreakpoint");
cmd.arg("fileName", data.fileName);
cmd.arg("lineNumber", data.lineNumber);
cmd.arg("condition", data.condition);
runCommand(cmd);
bp.notifyBreakpointInsertOk();
return;
}
......@@ -2902,8 +2911,10 @@ void GdbEngine::removeBreakpoint(Breakpoint bp)
const BreakpointParameters &data = bp.parameters();
if (!data.isCppBreakpoint()) {
postCommand("removeQmlBreakpoint " + data.fileName.toUtf8() + ' '
+ QByteArray::number(data.lineNumber));
DebuggerCommand cmd("removeQmlBreakpoint");
cmd.arg("fileName", data.fileName);
cmd.arg("lineNumber", data.lineNumber);
runCommand(cmd);
bp.notifyBreakpointRemoveOk();
return;
}
......
......@@ -196,6 +196,7 @@ private: ////////// Gdb Command Management //////////
// watch model updates before everything is finished.
void flushCommand(const GdbCommand &cmd);
protected:
void runCommand(const DebuggerCommand &command);
void postCommand(const QByteArray &command,
GdbCommandFlags flags,
GdbCommandCallback callback = 0,
......
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