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: ...@@ -1712,6 +1712,60 @@ class DumperBase:
sys.path.insert(1, head) sys.path.insert(1, head)
self.dumpermodules.append(os.path.splitext(tail)[0]) 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" # Some "Enums"
# Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h # Encodings. Keep that synchronized with DebuggerEncoding in debuggerprotocol.h
......
...@@ -274,6 +274,7 @@ class Dumper(DumperBase): ...@@ -274,6 +274,7 @@ class Dumper(DumperBase):
self.typesToReport = {} self.typesToReport = {}
self.qtNamespaceToReport = None self.qtNamespaceToReport = None
self.qmlEngines = [] self.qmlEngines = []
self.qmlBreakpoints = []
def prepare(self, args): def prepare(self, args):
self.output = [] self.output = []
...@@ -1811,6 +1812,29 @@ class Dumper(DumperBase): ...@@ -1811,6 +1812,29 @@ class Dumper(DumperBase):
return ''.join(self.output) 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): class CliDumper(Dumper):
def __init__(self): def __init__(self):
Dumper.__init__(self) Dumper.__init__(self)
...@@ -1916,7 +1940,6 @@ class CliDumper(Dumper): ...@@ -1916,7 +1940,6 @@ class CliDumper(Dumper):
self.putItem(value) self.putItem(value)
return self.output return self.output
def pp(args): def pp(args):
return theDumper.run(args) return theDumper.run(args)
...@@ -2056,78 +2079,3 @@ class TriggeredBreakpointHookBreakpoint(gdb.Breakpoint): ...@@ -2056,78 +2079,3 @@ class TriggeredBreakpointHookBreakpoint(gdb.Breakpoint):
TriggeredBreakpointHookBreakpoint() 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) ...@@ -853,6 +853,12 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
notifyInferiorPid(pid); 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, void GdbEngine::postCommand(const QByteArray &command, GdbCommandCallback callback,
const char *callbackName, const QVariant &cookie) const char *callbackName, const QVariant &cookie)
{ {
...@@ -2054,7 +2060,7 @@ void GdbEngine::executeStep() ...@@ -2054,7 +2060,7 @@ void GdbEngine::executeStep()
notifyInferiorRunRequested(); notifyInferiorRunRequested();
showStatusMessage(tr("Step requested..."), 5000); showStatusMessage(tr("Step requested..."), 5000);
if (isNativeMixedActive()) { if (isNativeMixedActive()) {
postCommand("prepareQmlStep 0"); runCommand("prepareQmlStep");
postCommand("-exec-continue", RunRequest, CB(handleExecuteContinue)); postCommand("-exec-continue", RunRequest, CB(handleExecuteContinue));
return; return;
} }
...@@ -2752,8 +2758,11 @@ void GdbEngine::insertBreakpoint(Breakpoint bp) ...@@ -2752,8 +2758,11 @@ void GdbEngine::insertBreakpoint(Breakpoint bp)
QVariant vid = QVariant::fromValue(bp); QVariant vid = QVariant::fromValue(bp);
if (!data.isCppBreakpoint()) { if (!data.isCppBreakpoint()) {
postCommand("insertQmlBreakpoint " + data.fileName.toUtf8() + ' ' DebuggerCommand cmd("insertQmlBreakpoint");
+ QByteArray::number(data.lineNumber)); cmd.arg("fileName", data.fileName);
cmd.arg("lineNumber", data.lineNumber);
cmd.arg("condition", data.condition);
runCommand(cmd);
bp.notifyBreakpointInsertOk(); bp.notifyBreakpointInsertOk();
return; return;
} }
...@@ -2902,8 +2911,10 @@ void GdbEngine::removeBreakpoint(Breakpoint bp) ...@@ -2902,8 +2911,10 @@ void GdbEngine::removeBreakpoint(Breakpoint bp)
const BreakpointParameters &data = bp.parameters(); const BreakpointParameters &data = bp.parameters();
if (!data.isCppBreakpoint()) { if (!data.isCppBreakpoint()) {
postCommand("removeQmlBreakpoint " + data.fileName.toUtf8() + ' ' DebuggerCommand cmd("removeQmlBreakpoint");
+ QByteArray::number(data.lineNumber)); cmd.arg("fileName", data.fileName);
cmd.arg("lineNumber", data.lineNumber);
runCommand(cmd);
bp.notifyBreakpointRemoveOk(); bp.notifyBreakpointRemoveOk();
return; return;
} }
......
...@@ -196,6 +196,7 @@ private: ////////// Gdb Command Management ////////// ...@@ -196,6 +196,7 @@ private: ////////// Gdb Command Management //////////
// watch model updates before everything is finished. // watch model updates before everything is finished.
void flushCommand(const GdbCommand &cmd); void flushCommand(const GdbCommand &cmd);
protected: protected:
void runCommand(const DebuggerCommand &command);
void postCommand(const QByteArray &command, void postCommand(const QByteArray &command,
GdbCommandFlags flags, GdbCommandFlags flags,
GdbCommandCallback callback = 0, 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