diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 158a75691db9b92a61394969094eb92186a064ed..e01f8ecca5c47ac3def78511aa41e0e3ee46be01 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -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 diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 3778edfbc2ff0ac232875ba33e5182d69c9c126d..ce3e7d2179ff477f65baf835a1552d05e8189824 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -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) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 5256c3b90cac80fc48e9d75a07262052bd3b60cf..5d35a6a225fd04522f5f68d242ca77645c7c454d 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -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; } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index f18da951c76722dd9db40de073405c3b63019429..938707ec796b484fdc3dc9dcfbf1b6fd2d3f3e3c 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -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,