diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index ea274a497b9..cf4abf26481 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -1784,6 +1784,53 @@ class DumperBase: def isReportableQmlFrame(self, functionName): return functionName and functionName.find("QV4::Moth::VME::exec") >= 0 + def extractQmlData(self, value): + if value.type.code == PointerCode: + value = value.dereference() + data = value["data"] + return data.cast(self.lookupType(str(value.type).replace("QV4::", "QV4::Heap::"))) + + def extractQmlRuntimeString(self, compilationUnitPtr, index): + # This mimics compilationUnit->runtimeStrings[index] + # typeof runtimeStrings = QV4.StringValue ** + runtimeStrings = compilationUnitPtr.dereference()["runtimeStrings"] + entry = runtimeStrings[index] + text = self.extractPointer(entry.dereference(), self.ptrSize()) + (elided, fn) = self.encodeStringHelper(text, 100) + return self.encodedUtf16ToUtf8(fn) + + def extractQmlLocation(self, engine): + if self.currentCallContext is None: + context = engine["current"] # QV4.ExecutionContext * or derived + self.currentCallContext = context + else: + context = self.currentCallContext["parent"] + ctxCode = int(context["type"]) + compilationUnit = context["compilationUnit"] + functionName = "Unknown JS"; + ns = self.qtNamespace() + + # QV4.ExecutionContext.Type_SimpleCallContext - 4 + # QV4.ExecutionContext.Type_CallContext - 5 + if ctxCode == 4 or ctxCode == 5: + callContextDataType = self.lookupQtType("QV4::Heap::CallContext") + callContext = context.cast(callContextDataType.pointer()) + functionObject = callContext["function"] + function = functionObject["function"] + # QV4.CompiledData.Function + compiledFunction = function["compiledFunction"].dereference() + index = int(compiledFunction["nameIndex"]) + functionName = "JS: " + self.extractQmlRuntimeString(compilationUnit, index) + + string = self.parseAndEvaluate("((%s)0x%x)->fileName()" + % (compilationUnit.type, compilationUnit)) + fileName = self.encodeStringUtf8(string) + + return {'functionName': functionName, + 'lineNumber': int(context["lineNumber"]), + 'fileName': fileName, + 'context': context } + # Some "Enums" diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 81ce5dbab3b..8c3a09baa70 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1706,52 +1706,6 @@ class Dumper(DumperBase): self.typesToReport[typestring] = typeobj return typeobj - def extractQmlData(self, value): - if value.type.code == PointerCode: - value = value.dereference() - data = value["data"] - return data.cast(self.lookupType(str(value.type).replace("QV4::", "QV4::Heap::"))) - - def extractQmlRuntimeString(self, compilationUnitPtr, index): - # This mimics compilationUnit->runtimeStrings[index] - runtimeStrings = compilationUnitPtr.dereference()["runtimeStrings"] # QV4.StringValue * - entry = (runtimeStrings + index) # QV4.StringValue * - text = entry["text"] - (elided, fn) = self.encodeStringHelper(toInteger(text), 100) - return self.encodedUtf16ToUtf8(fn) # string - - def putQmlLocation(self, level, frame, sal): - engine = frame.read_var("engine") # QV4.ExecutionEngine * - if self.currentCallContext is None: - context = engine["current"] # QV4.ExecutionContext * or derived - self.currentCallContext = context - else: - context = self.currentCallContext["parent"] - ctxCode = int(context["type"]) - compilationUnit = context["compilationUnit"] # QV4.CompiledData.CompilationUnit * - functionName = "### JS ###"; - ns = self.qtNamespace() - - # QV4.ExecutionContext.Type_SimpleCallContext - 4 - # QV4.ExecutionContext.Type_CallContext - 5 - if ctxCode == 4 or ctxCode == 5: - callContextDataType = self.lookupQtType("QV4::Heap::CallContext") - callContext = context.cast(callContextDataType.pointer()) - functionObject = callContext["function"] - function = functionObject["function"] - compiledFunction = function["compiledFunction"].dereference() # QV4.CompiledData.Function - index = int(compiledFunction["nameIndex"]) - functionName = "### JS ### " + self.extractQmlRuntimeString(compilationUnit, index) - - string = gdb.parse_and_eval("((%s)0x%x)->fileName()" - % (compilationUnit.type, compilationUnit)) - fileName = self.encodeStringUtf8(string) - - lineNumber = int(context["lineNumber"]) - self.put(('frame={level="%s",func="%s",file="%s",' - 'fullname="%s",line="%s",language="js",addr="0x%x"}') - % (level, functionName, fileName, fileName, lineNumber, context)) - def stackListFrames(self, n, options): self.prepare("options:" + options + ",pe") self.output = [] @@ -1779,7 +1733,13 @@ class Dumper(DumperBase): if self.nativeMixed: if self.isReportableQmlFrame(functionName): - self.putQmlLocation(i, frame, sal) + engine = frame.read_var("engine") + h = self.extractQmlLocation(engine) + self.put(('frame={level="%s",func="%s",file="%s",' + 'fullname="%s",line="%s",language="js",addr="0x%x"}') + % (i, h['functionName'], h['fileName'], h['fileName'], + h['lineNumber'], h['context'])) + i += 1 frame = frame.older() continue diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 337e1260c51..8e0c4367fe5 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -90,7 +90,7 @@ Value = lldb.SBValue def impl_SBValue__add__(self, offset): if self.GetType().IsPointerType(): - if isinstance(offset, int) or isinstance(offset, long): + if isinstance(offset, int): pass else: offset = offset.GetValueAsSigned() @@ -138,7 +138,7 @@ def impl_SBValue__long__(self): return int(self.GetValue(), 0) def impl_SBValue__getitem__(value, index): - if isinstance(index, int): + if isinstance(index, int) or isinstance(index, long): type = value.GetType() if type.IsPointerType(): innertype = value.Dereference().GetType() @@ -846,6 +846,7 @@ class Dumper(DumperBase): (n, isLimited) = (limit, True) if limit > 0 else (thread.GetNumFrames(), False) + self.currentCallContext = None result = 'stack={current-thread="%s"' % thread.GetThreadID() result += ',frames=[' for i in xrange(n): @@ -867,9 +868,15 @@ class Dumper(DumperBase): if self.nativeMixed: if self.isReportableQmlFrame(functionName): - #self.putQmlLocation(i, frame, sal) - functionName = "### JS ###"; - language = "js" + engine = frame.FindVariable("engine") + self.context = engine + h = self.extractQmlLocation(engine) + pc = 0 + functionName = h['functionName'] + fullname = h['fileName'] + lineNumber = h['lineNumber'] + addr = h['context'] + language = 'js' elif not functionName is None: if functionName.startswith("qt_v4"): @@ -1669,6 +1676,9 @@ class Dumper(DumperBase): instructions = function.GetInstructions(self.target) else: base = args.get('address', 0) + if int(base) == 0xffffffffffffffff: + warn("INVALID DISASSEMBLER BASE") + return addr = lldb.SBAddress(base, self.target) instructions = self.target.ReadInstructions(addr, 100) diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 05c7ccee85b..e4b1c9e4510 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -1000,6 +1000,12 @@ void LldbEngine::refreshStack(const GdbMi &stack) frame.usable = usable.data().toInt(); else frame.usable = QFileInfo(frame.file).isReadable(); + if (item["language"].data() == "js" + || frame.file.endsWith(QLatin1String(".js")) + || frame.file.endsWith(QLatin1String(".qml"))) { + frame.language = QmlLanguage; + frame.fixQmlFrame(startParameters()); + } frames.append(frame); } bool canExpand = stack["hasmore"].toInt();