cdbLoaded = False lldbLoaded = False gdbLoaded = False try: #import cdb_bridge cdbLoaded = True except: pass try: #import lldb_bridge lldbLoaded = True except: pass try: import gdb gdbLoaded = True ####################################################################### # # Infrastructure # ####################################################################### 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 (%s): " % (symbol, name)) if name in shadowed: level = shadowed[name] name1 = "%s@%s" % (name, level) shadowed[name] = level + 1 else: name1 = name shadowed[name] = 1 #warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name)) item = LocalItem() item.iname = "local." + name1 item.name = name1 try: item.value = frame.read_var(name, block) #warn("READ 1: %s" % item.value) if not item.value.is_optimized_out: #warn("ITEM 1: %s" % item.value) items.append(item) continue except: pass try: item.value = frame.read_var(name) #warn("READ 2: %s" % item.value) if not item.value.is_optimized_out: #warn("ITEM 2: %s" % item.value) items.append(item) continue 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() pass try: #warn("READ 3: %s %s" % (name, item.value)) item.value = gdb.parse_and_eval(name) #warn("ITEM 3: %s" % item.value) items.append(item) except: # Can happen in inlined code (see last line of # RowPainter::paintChars(): "RuntimeError: # No symbol \"__val\" in current context.\n" pass # 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 = LocalItem() item.iname = "local." + name item.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' 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 ####################################################################### # # Types # ####################################################################### PointerCode = gdb.TYPE_CODE_PTR ArrayCode = gdb.TYPE_CODE_ARRAY StructCode = gdb.TYPE_CODE_STRUCT UnionCode = gdb.TYPE_CODE_UNION EnumCode = gdb.TYPE_CODE_ENUM FlagsCode = gdb.TYPE_CODE_FLAGS FunctionCode = gdb.TYPE_CODE_FUNC IntCode = gdb.TYPE_CODE_INT FloatCode = gdb.TYPE_CODE_FLT # Parts of GDB assume that this means complex. VoidCode = gdb.TYPE_CODE_VOID #SetCode = gdb.TYPE_CODE_SET RangeCode = gdb.TYPE_CODE_RANGE StringCode = gdb.TYPE_CODE_STRING #BitStringCode = gdb.TYPE_CODE_BITSTRING #ErrorTypeCode = gdb.TYPE_CODE_ERROR MethodCode = gdb.TYPE_CODE_METHOD #MethodPointerCode = gdb.TYPE_CODE_METHODPTR #MemberPointerCode = gdb.TYPE_CODE_MEMBERPTR ReferenceCode = gdb.TYPE_CODE_REF CharCode = gdb.TYPE_CODE_CHAR BoolCode = gdb.TYPE_CODE_BOOL ComplexCode = gdb.TYPE_CODE_COMPLEX # Fortran ? TypedefCode = gdb.TYPE_CODE_TYPEDEF NamespaceCode = gdb.TYPE_CODE_NAMESPACE #Code = gdb.TYPE_CODE_DECFLOAT # Decimal floating point. #Code = gdb.TYPE_CODE_MODULE # Fortran #Code = gdb.TYPE_CODE_INTERNAL_FUNCTION ####################################################################### # # Step Command # ####################################################################### def sal(args): (cmd, addr) = args.split(",") lines = catchCliOutput("info line *" + addr) fromAddr = "0x0" toAddr = "0x0" for line in lines: pos0from = line.find(" starts at address") + 19 pos1from = line.find(" ", pos0from) pos0to = line.find(" ends at", pos1from) + 9 pos1to = line.find(" ", pos0to) if pos1to > 0: fromAddr = line[pos0from : pos1from] toAddr = line[pos0to : pos1to] gdb.execute("maint packet sal%s,%s,%s" % (cmd,fromAddr, toAddr)) registerCommand("sal", sal) ####################################################################### # # Convenience # ####################################################################### # Just convienience for 'python print ...' class PPCommand(gdb.Command): def __init__(self): super(PPCommand, self).__init__("pp", gdb.COMMAND_OBSCURE) def invoke(self, args, from_tty): print(eval(args)) registerCommand("pp", pp) # Just convienience for 'python print gdb.parse_and_eval(...)' class PPPCommand(gdb.Command): def __init__(self): super(PPPCommand, self).__init__("ppp", gdb.COMMAND_OBSCURE) def invoke(self, args, from_tty): print(gdb.parse_and_eval(args)) PPPCommand() except: pass