From 538b09efc801e80c64df7ab9f07121c15bf47fae Mon Sep 17 00:00:00 2001 From: hjk <qtc-committer@nokia.com> Date: Wed, 29 Jun 2011 11:48:12 +0200 Subject: [PATCH] debugger: add missing bridge.py Change-Id: I7e236964007462ca203b898db06e15f77857916b Reviewed-on: http://codereview.qt.nokia.com/1036 Reviewed-by: hjk <qthjk@ovi.com> --- share/qtcreator/dumper/bridge.py | 239 ++++++++++++++++++ .../gdbdebugger/simple/simple_gdbtest_app.cpp | 26 ++ 2 files changed, 265 insertions(+) create mode 100644 share/qtcreator/dumper/bridge.py diff --git a/share/qtcreator/dumper/bridge.py b/share/qtcreator/dumper/bridge.py new file mode 100644 index 00000000000..43c67f6f75f --- /dev/null +++ b/share/qtcreator/dumper/bridge.py @@ -0,0 +1,239 @@ + +try: + import lldb_bridge + +except: + pass + + +#try: +if True: + import gdb + + def registerCommand(name, func): + + class Command(gdb.Command): + def __init__(self): + super(Command, self).__init__(name, gdb.COMMAND_OBSCURE) + def invoke(self, args, from_tty): + output = func(args) + try: + print(output) + except: + out = "" + for c in output: + cc = ord(c) + if cc > 127: + out += "\\\\%d" % cc + elif cc < 0: + out += "\\\\%d" % (cc + 256) + else: + out += c + print(out) + + + + Command() + + + def isGoodGdb(): + #return gdb.VERSION.startswith("6.8.50.2009") \ + # and gdb.VERSION != "6.8.50.20090630-cvs" + return 'parse_and_eval' in __builtin__.dir(gdb) + + + def parseAndEvaluate(exp): + if isGoodGdb(): + return gdb.parse_and_eval(exp) + # Work around non-existing gdb.parse_and_eval as in released 7.0 + gdb.execute("set logging redirect on") + gdb.execute("set logging on") + try: + gdb.execute("print %s" % exp) + except: + gdb.execute("set logging off") + gdb.execute("set logging redirect off") + return None + gdb.execute("set logging off") + gdb.execute("set logging redirect off") + return gdb.history(0) + + + def listOfLocals(varList): + frame = gdb.selected_frame() + try: + frame = gdb.selected_frame() + #warn("FRAME %s: " % frame) + except RuntimeError, error: + warn("FRAME NOT ACCESSIBLE: %s" % error) + return [] + except: + warn("FRAME NOT ACCESSIBLE FOR UNKNOWN REASONS") + return [] + + # New in 7.2 + hasBlock = 'block' in __builtin__.dir(frame) + + items = [] + #warn("HAS BLOCK: %s" % hasBlock) + if hasBlock and isGoodGdb(): + #warn("IS GOOD: %s " % varList) + try: + block = frame.block() + #warn("BLOCK: %s " % block) + except RuntimeError, error: + warn("BLOCK IN FRAME NOT ACCESSIBLE: %s" % error) + return items + except: + warn("BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS") + return items + + shadowed = {} + while True: + if block is None: + warn("UNEXPECTED 'None' BLOCK") + break + for symbol in block: + name = symbol.print_name + + if name == "__in_chrg": + continue + + # "NotImplementedError: Symbol type not yet supported in + # Python scripts." + #warn("SYMBOL %s: " % symbol.value) + #warn("SYMBOL %s (%s): " % (symbol, name)) + if name in shadowed: + level = shadowed[name] + name1 = "%s <shadowed %s>" % (name, level) + shadowed[name] = level + 1 + else: + name1 = name + shadowed[name] = 1 + #warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name)) + item = Item(0, "local", name1, name1) + try: + item.value = frame.read_var(name, block) # this is a gdb value + except: + try: + item.value = frame.read_var(name) # this is a gdb value + except: + # RuntimeError: happens for + # void foo() { std::string s; std::wstring w; } + # ValueError: happens for (as of 2010/11/4) + # a local struct as found e.g. in + # gcc sources in gcc.c, int execute() + continue + #warn("ITEM %s: " % item.value) + items.append(item) + # The outermost block in a function has the function member + # FIXME: check whether this is guaranteed. + if not block.function is None: + break + + block = block.superblock + else: + # Assuming gdb 7.0 release or 6.8-symbianelf. + filename, file = createTempFile() + #warn("VARLIST: %s " % varList) + #warn("FILENAME: %s " % filename) + gdb.execute("set logging off") + gdb.execute("set logging redirect off") + gdb.execute("set logging file %s" % filename) + gdb.execute("set logging redirect on") + gdb.execute("set logging on") + try: + gdb.execute("info args") + # We cannot use "info locals" as at least 6.8-symbianelf + # aborts as soon as we hit unreadable memory. + # gdb.execute("interpreter mi '-stack-list-locals 0'") + # results in &"Recursive internal problem.\n", so we have + # the frontend pass us the list of locals. + + # There are two cases, either varList is empty, so we have + # to fetch the list here, or it is not empty with the + # first entry being a dummy. + if len(varList) == 0: + gdb.execute("info locals") + else: + varList = varList[1:] + except: + pass + gdb.execute("set logging off") + gdb.execute("set logging redirect off") + + try: + temp = open(filename, "r") + for line in temp: + if len(line) == 0 or line.startswith(" "): + continue + # The function parameters + pos = line.find(" = ") + if pos < 0: + continue + varList.append(line[0:pos]) + temp.close() + except: + pass + removeTempFile(filename, file) + #warn("VARLIST: %s " % varList) + for name in varList: + #warn("NAME %s " % name) + item = Item(0, "local", name, name) + try: + item.value = frame.read_var(name) # this is a gdb value + except RuntimeError: + pass + #continue + except: + # Something breaking the list, like intermediate gdb warnings + # like 'Warning: can't find linker symbol for virtual table for + # `std::less<char const*>' value\n\nwarning: found + # `myns::QHashData::shared_null' instead [...] + # that break subsequent parsing. Chicken out and take the + # next "usable" line. + continue + items.append(item) + + return items + + + def catchCliOutput(command): + try: + return gdb.execute(command, to_string=True).split("\n") + except: + pass + filename, file = createTempFile() + gdb.execute("set logging off") + gdb.execute("set logging redirect off") + gdb.execute("set logging file %s" % filename) + gdb.execute("set logging redirect on") + gdb.execute("set logging on") + msg = "" + try: + gdb.execute(command) + except RuntimeError, error: + # For the first phase of core file loading this yield + # "No symbol table is loaded. Use the \"file\" command." + msg = str(error) + except: + msg = "Unknown error" + gdb.execute("set logging off") + gdb.execute("set logging redirect off") + if len(msg): + # Having that might confuse result handlers in the gdbengine. + #warn("CLI ERROR: %s " % msg) + return "CLI ERROR: %s " % msg + temp = open(filename, "r") + lines = [] + for line in temp: + lines.append(line) + temp.close() + removeTempFile(filename, file) + return lines + + + + +#except: +# pass diff --git a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp index 7283d7e8f56..c490f0b4193 100644 --- a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp +++ b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp @@ -2935,8 +2935,34 @@ namespace qc41700 { } // namespace qc41700 +namespace cp42895 { + + // http://codepaster.europe.nokia.com/?id=42895 + + void g(int c, int d) + { + qDebug() << c << d; + // <== break here + // Check there are frames for g and f in the stack view. + dummyStatement(&c, &d); + } + + void f(int a, int b) + { + g(a, b); + } + + void test42895() + { + f(3, 4); + } + +} // namespace cp + + int main(int argc, char *argv[]) { + cp42895::test42895(); bug5046::test5046(); bug4904::test4904(); qc41700::test41700(); -- GitLab