def invoke(self, argument, from_tty): args = gdb.string_to_argv(argument) expr = args[0] List_t = gdb.parse_and_eval(expr) #print List_t TCB_t_p = gdb.lookup_type("TCB_t").pointer() #TCB_t * uint32_p = gdb.lookup_type("uint32_t").pointer() #uint32_t * if len(args) == 2: max_iter = int(args[1]) else: max_iter = self.MAX_ITER pxCurrentTCB = gdb.parse_and_eval("pxCurrentTCB") uxNumberOfItems = List_t["uxNumberOfItems"] #this is the our sentinel to iterate the list (marker called in FreeRTOS) xListEnd = List_t["xListEnd"] item = xListEnd["pxNext"] #print xListEnd.address #print xListEnd["pxNext"] i = 1 # print "pxCurrentTCB %s" % (pxCurrentTCB.dereference()) while xListEnd.address != item: print "node@%s: %s #%d" % (item, item.dereference(), i) if (uxNumberOfItems == 0): print "List corruption: Iterated %d times uxNumberOfItems %d" % ( i, uxNumberOfItems) break if (i == max_iter): print "Max iterations %d reached % (i)" break #print the owner of the list casted as TCB_t tcb = item["pvOwner"].cast(TCB_t_p).dereference() pxTopOfStack = tcb["pxTopOfStack"] pc = int( (pxTopOfStack + self.regs_stack_to_index('pc')).cast(uint32_p).dereference()) lr = int( (pxTopOfStack + self.regs_stack_to_index('lr')).cast(uint32_p).dereference()) print "pvOwner@%s: %s" % (item["pvOwner"], tcb) print "PC @ 0x%x ---> %s" % (pc, gdb.find_pc_line(pc)) print "LR @ 0x%x ---> %s" % (lr, gdb.find_pc_line(lr)) print "--------------------------------------------------------------------" uxNumberOfItems -= 1 item = item["pxNext"] i += 1 #at this point the list has been iterated so there must be 0 items left if (uxNumberOfItems): print "List corruption: Iterated %d times uxNumberOfItems %d" % ( i, uxNumberOfItems)
def invoke(self, argument, from_tty): args = gdb.string_to_argv(argument) expr = args[0] List_t = gdb.parse_and_eval(expr) #print List_t TCB_t_p = gdb.lookup_type("TCB_t").pointer() #TCB_t * uint32_p = gdb.lookup_type("uint32_t").pointer() #uint32_t * if len(args) == 2: max_iter = int(args[1]) else: max_iter = self.MAX_ITER pxCurrentTCB = gdb.parse_and_eval("pxCurrentTCB") uxNumberOfItems = List_t["uxNumberOfItems"] #this is the our sentinel to iterate the list (marker called in FreeRTOS) xListEnd = List_t["xListEnd"] item = xListEnd["pxNext"] #print xListEnd.address #print xListEnd["pxNext"] i = 1 # print "pxCurrentTCB %s" % (pxCurrentTCB.dereference()) while xListEnd.address != item: print "node@%s: %s #%d" % (item, item.dereference(), i) if (uxNumberOfItems == 0): print "List corruption: Iterated %d times uxNumberOfItems %d" % (i, uxNumberOfItems) break if (i == max_iter): print "Max iterations %d reached % (i)" break #print the owner of the list casted as TCB_t tcb = item["pvOwner"].cast(TCB_t_p).dereference() pxTopOfStack = tcb["pxTopOfStack"] pc = int((pxTopOfStack + self.regs_stack_to_index('pc')).cast(uint32_p).dereference()) lr = int((pxTopOfStack + self.regs_stack_to_index('lr')).cast(uint32_p).dereference()) print "pvOwner@%s: %s" % (item["pvOwner"], tcb) print "PC @ 0x%x ---> %s" % (pc, gdb.find_pc_line(pc)) print "LR @ 0x%x ---> %s" % (lr, gdb.find_pc_line(lr)) print "--------------------------------------------------------------------" uxNumberOfItems -= 1 item = item["pxNext"] i += 1 #at this point the list has been iterated so there must be 0 items left if (uxNumberOfItems): print "List corruption: Iterated %d times uxNumberOfItems %d" % (i, uxNumberOfItems)
def process_dump(proc, indent=0, verbosity=3): write_key("type", "user" if proc['cpl'] == gdb.Value(3) else "system", indent) if (proc['cpl'] == gdb.Value(3) and verbosity > 2): write_key("kstack base", str(proc['punt_nucleo']), indent) vstack = toi(proc['contesto'][4]) stack = v2p(proc, vstack) if (verbosity > 2): gdb.write( colorize( 'col_proc_hdr', "-- top of kstack ({:016x} \u279e {:x}):\n".format( vstack, stack)), indent) rip = readfis(stack) write_key("rip", gdb.Value(rip).cast(void_ptr_type), indent) if (verbosity > 2): write_key("cs", dump_selector(readfis(stack + 8)), indent) write_key("rflags", dump_flags(readfis(stack + 16)), indent) write_key("rsp", hex(readfis(stack + 24)), indent) write_key("ss", dump_selector(readfis(stack + 32)), indent) gdb.write(colorize('col_proc_hdr', "-- saved registers:\n"), indent) for i, r in enumerate(registers): write_key(r, hex(toi(proc['contesto'][i])), indent) cr3 = toi(proc['cr3']) write_key("cr3", vm_faddr_to_str(cr3), indent) gdb.write(colorize('col_proc_hdr', "-- next instruction:\n"), indent) show_lines(gdb.find_pc_line(rip), indent) if len(toshow) > 0: if verbosity > 2: gdb.write("\x1b[33m-- special fields:\x1b[m\n", indent) for f in toshow: write_key(f.name, proc[f], indent)
def invoke(self, arg, _): self.dont_repeat() args = gdb.string_to_argv(arg) if len(args) > 2: raise ValueError( 'Usage: gohere [default | e | vnew | new] [address]') address = '$pc' if len(args) < 2 else args[1] open_method = 'default' if not args else args[0] pos = gdb.find_pc_line(eval_int(address)) if not pos.symtab: raise ValueError("Can't find address {}".format(address)) nvim = get_nvim_instance() if open_method == 'default': win = find_marked_window(nvim) if win: nvim.command('{} wincmd w'.format(win.number)) open_method = 'e' nvim.command('{} +{} {}'.format(open_method, pos.line, os.path.abspath(pos.symtab.filename))) nvim.command('silent! {}foldopen!'.format(pos.line))
def print_addr(ptr): ptr = ptr.cast(StgPtr) sym = gdb.find_pc_line(int(ptr.cast(StgWord))) if sym.symtab: return Text('%s (%s:%d)' % (ptr, sym.symtab.filename, sym.line)) else: return Text('%s' % (ptr))
def map_block(block=None): disas = disassemble_block(block) lineDict = dict() for entry in disas: sal = gdb.find_pc_line(entry["addr"]) if sal.line not in lineDict: lineDict[sal.line] = dict() lineDict[sal.line][sal.pc] = entry["asm"] return lineDict
def linespec_from_address(address): '''Take an address and return the pc_line from gdb.''' pos = gdb.find_pc_line( int( gdb.parse_and_eval(address).cast( gdb.lookup_type('char').pointer()))) if not pos.symtab: raise ValueError("Can't find address {}".format(address)) return pos
def invoke(self, arg, from_tty): bps = gdb.breakpoints() for bp in bps: s = gdb.decode_line(bp.location)[1][0] l = gdb.find_pc_line(s.pc) print l loc = '' print ("Breakpoint #%d - Location: %s Enabled: %s" % (bp.number, loc, bp.enabled))
def load_modules(self, verbose=False): print("Loading modules...", end='') sys.stdout.flush() failed = 0 loaded = 0 for module in self.for_each_module(): modname = "{}".format(module['name'].string()) modfname = "{}.ko".format(modname) found = False for path in self.searchpath: modpath = self.find_module_file(modfname, path) if not modpath: continue found = True if 'module_core' in module.type: addr = long(module['module_core']) else: addr = long(module['core_layout']['base']) if verbose: print("Loading {} at {:#x}".format(modname, addr)) sections = self.get_module_sections(module) gdb.execute("add-symbol-file {} {:#x} {}".format( modpath, addr, sections), to_string=True) sal = gdb.find_pc_line(addr) if sal.symtab is None: objfile = gdb.lookup_objfile(modpath) self.load_debuginfo(objfile, modpath) # We really should check the version, but GDB doesn't export # a way to lookup sections. break if not found: if failed == 0: print() print("Couldn't find module file for {}".format(modname)) failed += 1 else: loaded += 1 if (loaded + failed) % 10 == 10: print(".", end='') sys.stdout.flush() print(" done. ({} loaded".format(loaded), end='') if failed: print(", {} failed)".format(failed)) else: print(")") # We shouldn't need this again, so why keep it around? del self.findmap self.findmap = {}
def context_source(self): try: pc = pwngef.arch.CURRENT_ARCH.pc symtabline = gdb.find_pc_line(pc) symtab = symtabline.symtab line_num = symtabline.line - 1 # we substract one because line number returned by gdb start at 1 if not symtab.is_valid(): return None fpath = symtab.fullname() with open(fpath, "r") as f: lines = [l.rstrip() for l in f.readlines()] except Exception: return None nb_line = self.get_setting("nb_lines_code") fn = symtab.filename if len(fn) > 20: fn = "{}[...]{}".format(fn[:15], os.path.splitext(fn)[1]) title = "source:{}+{}".format(fn, line_num + 1) cur_line_color = pwngef.config.get("theme.source_current_line") self.context_title(title) for i in range(line_num - nb_line + 1, line_num + nb_line): if i < 0: continue if i < line_num: print( Color.grayify(" {:4d}\t {:s}".format( i + 1, lines[i], ))) if i == line_num: extra_info = self.get_pc_context_info(pc, lines[i]) prefix = "{}{:4d}\t ".format(config_arrow_right, i + 1) leading = len(lines[i]) - len(lines[i].lstrip()) if extra_info: print("{}{}".format(" " * (len(prefix) + leading), extra_info)) print( Color.colorify("{}{:s}".format(prefix, lines[i]), cur_line_color)) if i > line_num: try: print(" {:4d}\t {:s}".format( i + 1, lines[i], )) except IndexError: break return None
def invoke(self, argv, from_tty): global linked_pane, is_vim if linked_pane == None: return if not is_vim: is_vim = linked_pane.is_vim() if not is_vim: print "Not vim" return try: pc = gdb.selected_frame().pc() #print argv #print pc #print gdb.block_for_pc(pc).function fullname = gdb.find_pc_line(pc).symtab.fullname() #print fullname #print gdb.find_pc_line(pc).symtab.filename line = str(gdb.find_pc_line(pc).line) #print line except: return cmds = [":tabfirst"] #cmds = [] if self.current_file != fullname or argv != "": self.current_file = fullname #linked_pane.vim_exec(":view +" + line + " " + fullname) #linked_pane.vim_exec(":set cursorline") cmds.append(":view +" + line + " " + fullname) #cmds.append(":set cursorline") else: #linked_pane.vim_exec(":" + line) cmds.append(":" + line) #linked_pane.send_key("zzzv") #linked_pane.send_key("zz") linked_pane.vim_exec_cmds(cmds, "zzzv")
def on_stop_event(e): global temp_breakpoint_num if not isinstance(e, gdb.BreakpointEvent): return for bp in e.breakpoints: if bp.number == temp_breakpoint_num: bp.delete() gdb.events.stop.disconnect(on_stop_event) l = gdb.find_pc_line(long(gdb.parse_and_eval('$pc'))).line gdb.execute('list %d, %d' % (l, l)) break
def on_stop_event(e): global temp_breakpoint_num if not isinstance(e, gdb.BreakpointEvent): return for bp in e.breakpoints: if bp.number == temp_breakpoint_num: bp.delete() gdb.events.stop.disconnect(on_stop_event) l = gdb.find_pc_line(int(gdb.parse_and_eval('$pc'))).line gdb.execute('list %d, %d' % (l, l)) break
def load_modules(self, searchpath, verbose=False): print("Loading modules...", end='') sys.stdout.flush() failed = 0 loaded = 0 for module in for_each_module(): modname = "{}".format(module['name'].string()) modfname = "{}.ko".format(modname) found = False for path in searchpath: modpath = self.find_module_file(modfname, path) if not modpath: continue found = True if verbose: print("Loading {} at {}" .format(modname, module['module_core'])) sections = get_module_sections(module) gdb.execute("add-symbol-file {} {} {}" .format(modpath, module['module_core'], sections), to_string=True) sal = gdb.find_pc_line(long(module['module_core'])) if sal.symtab is None: objfile = gdb.lookup_objfile(modpath) load_debuginfo(searchpath, objfile, modpath) # We really should check the version, but GDB doesn't export # a way to lookup sections. break if not found: if failed == 0: print() print("Couldn't find module file for {}".format(modname)) failed += 1 else: loaded += 1 if (loaded + failed) % 10 == 10: print(".", end='') sys.stdout.flush() print(" done. ({} loaded".format(loaded), end='') if failed: print(", {} failed)".format(failed)) else: print(")") # We shouldn't need this again, so why keep it around? del self.findmap self.findmap = {}
def GetFrameLocation(self): """Get location of current line of execution from active frame.""" import gdb try: frame = gdb.selected_frame() pc = frame.pc() symbol_table_and_line = gdb.find_pc_line(pc) symbol_table = symbol_table_and_line.symtab fullsource = symbol_table.fullname() source = symbol_table.filename line = symbol_table_and_line.line return fullsource, source, line except: return None, None, None
def dump_blocks_from_deepest_out(): fr = gdb.selected_frame() if not fr: _common.die('No frame selected.') from _common import dump_Block b = fr.block() stal = fr.find_sal() # Surely correct for the *first* Block. i_block = 0 while b != None: if i_block > 0 and not b.is_static and not b.is_global: stalOther = gdb.find_pc_line(b.start) if stalOther != None: stal = stalOther dump_Block(b, stal) b = b.superblock if i_block >= MAX_NEST_DUMP_DEPTH.const: _common.die('Halt, max dump depth.') i_block += 1
def invoke(self, *_): pos = eval_int('$pc') line = gdb.find_pc_line(pos) if not line.symtab: return try: block = gdb.block_for_pc(pos) except RuntimeError as e: if e.args == ('Cannot locate object file for block.', ): return raise if block.function is None: print('First found block no function', pos) return while block.function.name is None: if block.superblock: block = block.superblock else: print('No superblock at', pos) return if block.function is None: print('Function iterated to None in', pos) return offset = pos - block.start offset_str = '+{}'.format(offset) if offset else '' entering = self.update_fp_stack() if entering: curindent = self.indent self.indent += 4 direction_string = '-->' else: self.indent -= 4 curindent = self.indent direction_string = '<--' print_str = '{}{}{}{} {}:{}'.format(' ' * curindent, direction_string, block.function.name, offset_str, line.symtab.filename, line.line) print(print_str)
def invoke (self, argv, from_tty): try: pc = gdb.selected_frame().pc() except: print "No code" return print argv print pc print gdb.block_for_pc(pc).function print gdb.find_pc_line(pc).symtab.fullname() print gdb.find_pc_line(pc).symtab.filename print gdb.find_pc_line(pc).line
def log(prefix, event): timestamp = datetime.now().isoformat() thread = event.ptid sal = gdb.find_pc_line(event.address) block = gdb.block_for_pc(event.address) while block and not block.function: block = block.superblock if block: function = block.function.print_name else: function = "unknown function at %x" % event.address if sal.symtab: line = "%s:%d" % (sal.symtab.fullname(), sal.line) else: line = "unknown source" self.output.write("[%s] %s %s %s %s" % (timestamp, thread, prefix, function, line))
def __call__(self, addr): if addr in syminfo_resolver.cache: return self.cache[addr] infosym = gdb.execute('info symbol 0x%x' % addr, False, True) func = infosym[:infosym.find(" + ")] sal = gdb.find_pc_line(addr) try : # prefer (filename:line), filename = sal.symtab.filename line = sal.line except : # but if can't get it, at least give the name of the object if not infosym.startswith("No symbol matches") : filename = infosym[infosym.rfind("/")+1:].rstrip() if filename and filename.startswith('../../'): filename = filename[6:] result = [debug.SourceAddress(addr, name=func, filename=filename, line=line)] syminfo_resolver.cache[addr] = result return result
def __init__(self, addr): if addr in syminfo.cache: cobj = syminfo.cache[addr] self.func = cobj.func self.source = cobj.source return infosym = gdb.execute('info symbol 0x%x' % addr, False, True) self.func = infosym[:infosym.find(" + ")] sal = gdb.find_pc_line(addr) try : # prefer (filename:line), self.source = '%s:%s' % (sal.symtab.filename, sal.line) except : # but if can't get it, at least give the name of the object if infosym.startswith("No symbol matches") : self.source = None else: self.source = infosym[infosym.rfind("/")+1:].rstrip() if self.source and self.source.startswith('../../'): self.source = self.source[6:] syminfo.cache[addr] = self
def backtrace_stack(): i = 0 frame = gdb.selected_frame() while frame != None and frame.is_valid() and frame.pc() > 0: pc = frame.pc() line = gdb.find_pc_line(pc) block = gdb.block_for_pc(pc) print("#{} 0x{:016x} in {}()+{} at {}:{}".format( i, pc, block.function, pc - block.start, line.symtab, line.line)) i += 1 frame = frame.older() if frame and frame.pc() > 0: print("Stopped because: {}".format(frame.unwind_stop_reason())) elif frame.pc() == 0: print("Stopped because pc = 0") elif frame == None: print("Stopped because frame = None") else: print("Stopped for unknown reason") print("")
def __init__(self, addr): if addr in syminfo.cache: cobj = syminfo.cache[addr] self.func = cobj.func self.source = cobj.source return infosym = gdb.execute('info symbol 0x%x' % addr, False, True) self.func = infosym[:infosym.find(" + ")] sal = gdb.find_pc_line(addr) try: # prefer (filename:line), self.source = '%s:%s' % (sal.symtab.filename, sal.line) except: # but if can't get it, at least give the name of the object if infosym.startswith("No symbol matches"): self.source = None else: self.source = infosym[infosym.rfind("/") + 1:].rstrip() if self.source and self.source.startswith('../../'): self.source = self.source[6:] syminfo.cache[addr] = self
def __call__(self, addr): if addr in syminfo_resolver.cache: return self.cache[addr] infosym = gdb.execute('info symbol 0x%x' % addr, False, True) func = infosym[:infosym.find(" + ")] sal = gdb.find_pc_line(addr) filename = None line = None try : # prefer (filename:line), filename = sal.symtab.filename line = sal.line except : # but if can't get it, at least give the name of the object if not infosym.startswith("No symbol matches") : filename = infosym[infosym.rfind("/")+1:].rstrip() if filename and filename.startswith('../../'): filename = filename[6:] result = [debug.SourceAddress(addr, name=func, filename=filename, line=line)] syminfo_resolver.cache[addr] = result return result
def show_leak(): tracker = gdb.parse_and_eval('memory::tracker') size_allocations = tracker['size_allocations'] allocations = tracker['allocations'] # Build a list of allocations to be sorted lexicographically by call chain # and summarize allocations with the same call chain: percent=' '; gdb.write('Fetching data from qemu/osv: %s' % percent); gdb.flush(); allocs = []; for i in range(size_allocations) : newpercent = '%2d%%' % round(100.0*i/(size_allocations-1)); if newpercent != percent : percent = newpercent; gdb.write('\b\b\b%s' % newpercent); gdb.flush(); a = allocations[i] addr = ulong(a['addr']) if addr == 0 : continue nbacktrace = a['nbacktrace'] backtrace = a['backtrace'] callchain = [] for j in range(nbacktrace) : callchain.append(ulong(backtrace[nbacktrace-1-j])) allocs.append((i, callchain)) gdb.write('\n'); gdb.write('Merging %d allocations by identical call chain... ' % len(allocs)) gdb.flush(); allocs.sort(key=lambda entry: entry[1]) import collections Record = collections.namedtuple('Record', ['bytes', 'allocations', 'minsize', 'maxsize', 'avgsize', 'minbirth', 'maxbirth', 'avgbirth', 'callchain']) records = []; total_size = 0 cur_n = 0 cur_total_size = 0 cur_total_seq = 0 cur_first_seq = -1 cur_last_seq = -1 cur_max_size = -1 cur_min_size = -1 for k, alloc in enumerate(allocs) : i = alloc[0] callchain = alloc[1] seq = ulong(allocations[i]['seq']) size = ulong(allocations[i]['size']) total_size += size cur_n += 1 cur_total_size += size cur_total_seq += seq if cur_first_seq<0 or seq<cur_first_seq : cur_first_seq = seq if cur_last_seq<0 or seq>cur_last_seq : cur_last_seq = seq if cur_min_size<0 or size<cur_min_size : cur_min_size = size if cur_max_size<0 or size>cur_max_size : cur_max_size = size # If the next entry has the same call chain, just continue summing if k!=len(allocs)-1 and callchain==allocs[k+1][1] : continue; # We're done with a bunch of allocations with same call chain: r = Record(bytes = cur_total_size, allocations = cur_n, minsize = cur_min_size, maxsize = cur_max_size, avgsize = cur_total_size/cur_n, minbirth = cur_first_seq, maxbirth = cur_last_seq, avgbirth = cur_total_seq/cur_n, callchain = callchain) records.append(r) cur_n = 0 cur_total_size = 0 cur_total_seq = 0 cur_first_seq = -1 cur_last_seq = -1 cur_max_size = -1 cur_min_size = -1 gdb.write('generated %d records.\n' % len(records)) # Now sort the records by total number of bytes records.sort(key=lambda r: r.bytes, reverse=True) gdb.write('\nAllocations still in memory at this time (seq=%d):\n\n' % tracker['current_seq']) for r in records : gdb.write('Found %d bytes in %d allocations [size ' % (r.bytes, r.allocations)) if r.minsize != r.maxsize : gdb.write('%d/%.1f/%d' % (r.minsize, r.avgsize, r.maxsize)) else : gdb.write('%d' % r.minsize) gdb.write(', birth ') if r.minbirth != r.maxbirth : gdb.write('%d/%.1f/%d' % (r.minbirth, r.avgbirth, r.maxbirth)) else : gdb.write('%d' % r.minbirth) gdb.write(']\nfrom:\n') for f in reversed(r.callchain) : infosym = gdb.execute('info symbol 0x%x' % f, False, True) func = infosym[:infosym.find(" + ")] sal = gdb.find_pc_line(f) try : # prefer (filename:line), source = ' (%s:%s)' % (sal.symtab.filename, sal.line) except : # but if can't get it, at least give the name of the object if infosym.startswith("No symbol matches") : source = '' else : source = ' (%s)' % infosym[infosym.rfind("/")+1:].rstrip() gdb.write('\t%s%s\n' % (func, source)); gdb.write('\n')
def gdb_address_to_function_file_line(address): function = gdb_address_to_function(address) sal = gdb.find_pc_line(address) line = "?" if sal.symtab is None else sal.line filename = "?" if sal.symtab is None else sal.symtab.filename return (filename, line, function)
def invoke(self, arg): pos = gdb.find_pc_line(int(helpers.as_uintptr(arg))) if not pos.symtab: return "\t\tUnknown" return pos.symtab.filename + ':' + str(pos.line)
def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) # if no max_depth given, use 0 if len(argv) > 0: max_depth = int(argv[0]) else: max_depth = 0 # calculate address of the next line in outer function frame = gdb.selected_frame() pc_older = frame.older().pc() symtabline = gdb.find_pc_line(pc_older) pc_older_next = symtabline.last + 1 depth = 0 stack = [] stack.append(frame) # get current 'pagination' if gdb.parameter('pagination') == True: pagination = 'on' else: pagination = 'off' gdb.execute('set pagination off') try: # while our addres not equal to the address of the next line in outer function while pc_older_next != gdb.selected_frame().pc(): pc = gdb.selected_frame().pc() if max_depth == 0: gdb.execute('next') elif max_depth == -1: # if unlimited depth defined gdb.execute('step') else: # if we still on the current frame, then do nothing if gdb.selected_frame() == stack[-1]: pass # if we frame up elif len(stack) > 1 and gdb.selected_frame() == stack[-2]: depth = depth - 1 stack.pop() # if we frame down else: depth = depth + 1 stack.append(gdb.selected_frame()) if depth < max_depth: gdb.execute('step') else: gdb.execute('next') except RuntimeError as e: error("%s" % e) #raise # restore 'pagination' gdb.execute('set pagination ' + pagination)
def current_line(): frame = gdb.selected_frame() symtab_line = gdb.find_pc_line(frame.pc()) line = symtab_line.line path = symtab_line.symtab.fullname() return path, line