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 reprG(ptr): if long(ptr) == 0: return "o G:null" obj = ptr.dereference() vp = gdb.lookup_type('void').pointer() pc = ptr['sched']['pc'].cast(vp) # python2 will not cast pc (type void*) to an int cleanly # instead python2 and python3 work with the hex string representation # of the void pointer which we can parse back into an int. # int(pc) will not work. try: #python3 / newer versions of gdb pc = int(pc) except gdb.error: pc = int(str(pc), 16) blk = gdb.block_for_pc(pc) attrs = { "flg": '*' if ptr['m'] else 'o', "goid": obj["goid"], "status": sts[int(obj["status"])], "func": blk.function, "m": reprM(obj["m"], short=True) } return "%(flg)s G:%(goid)s %(status)s %(func)s m=<%(m)s>" % attrs
def print_instruction_at(self,addr,stack_percentage): gdb.write(str(round(stack_percentage,2))+":") str_to_eval = "info line *"+hex(addr) #gdb.execute(str_to_eval) res = gdb.execute(str_to_eval,to_string = True) # get information from results string: words = res.split() valid = False if words[0] == 'No': #no line info... pass else: valid = True line = int(words[1]) idx = words[3].rfind("/"); #find first backslash if idx>0: name = words[3][idx+1:]; path = words[3][:idx]; else: name = words[3]; path = ""; block = gdb.block_for_pc(addr) func = block.function if str(func) == "None": func = block.superblock.function if valid: print("Line: ",line," in ",path,"/",name,"in ",func) return name,path,line,func
def setup(fn_name): fn_full_name = self.prefix + fn_name print 'setting up breakpoint for', fn_full_name on_enter_instance = on_enter(fn_name, fn_full_name) # free() does not need a finishing breakpoint, because it returns a void # without this the leak detector is unstable, because # on some systems je_free() has a bunch of cross jumps somewhere: # anight@dura3:~/projects/test> gdb --batch -ex 'disassemble je_free' ./a.out | grep jmpq | grep -v je_free # 0x000000000040554c <+428>: jmpq 0x42aaa0 <je_tcache_event_hard> # 0x00000000004055a3 <+515>: jmpq 0x40f0a0 <je_arena_dalloc_small> # 0x000000000040564e <+686>: jmpq 0x421240 <je_huge_dalloc> # 0x000000000040566a <+714>: jmpq 0x425aa0 <je_quarantine> # 0x00000000004056cb <+811>: jmpq 0x40f2b0 <je_arena_dalloc_large> # # Luckily, this does not apply to all other memory functions if fn_name == 'free': return arch = gdb.selected_frame().architecture() sym = gdb.lookup_global_symbol(fn_full_name, gdb.SYMBOL_FUNCTIONS_DOMAIN) block = gdb.block_for_pc(long(sym.value().address)) ptr = block.start while ptr < block.end: da = arch.disassemble(ptr)[0] if da['asm'].rstrip().endswith('retq'): print 'setting up finish breakpoint for', da on_result_ready_instance = on_result_ready(on_enter_instance, '*0x%lx' % da['addr']) ptr += da['length']
def __call__(self, pending_frame): pc_desc = pending_frame.architecture().registers().find("pc") pc = pending_frame.read_register(pc_desc) sp_desc = pending_frame.architecture().registers().find("sp") sp = pending_frame.read_register(sp_desc) block = gdb.block_for_pc(int(pc)) if block is None: return None func = block.function if func is None: return None if str(func) != "bar": return None fid = FrameId(pc, sp) unwinder = pending_frame.create_unwind_info(fid) if self._use_descriptors: unwinder.add_saved_register(pc_desc, pc) unwinder.add_saved_register(sp_desc, sp) else: unwinder.add_saved_register("pc", pc) unwinder.add_saved_register("sp", sp) return unwinder
def setup(fn_name): fn_full_name = self.prefix + fn_name print 'setting up breakpoint for', fn_full_name on_enter_instance = on_enter(fn_name, fn_full_name) # free() does not need a finishing breakpoint, because it returns a void # without this the leak detector is unstable, because # on some systems je_free() has a bunch of cross jumps somewhere: # anight@dura3:~/projects/test> gdb --batch -ex 'disassemble je_free' ./a.out | grep jmpq | grep -v je_free # 0x000000000040554c <+428>: jmpq 0x42aaa0 <je_tcache_event_hard> # 0x00000000004055a3 <+515>: jmpq 0x40f0a0 <je_arena_dalloc_small> # 0x000000000040564e <+686>: jmpq 0x421240 <je_huge_dalloc> # 0x000000000040566a <+714>: jmpq 0x425aa0 <je_quarantine> # 0x00000000004056cb <+811>: jmpq 0x40f2b0 <je_arena_dalloc_large> # # Luckily, this does not apply to all other memory functions if fn_name == 'free': return arch = gdb.selected_frame().architecture() sym = gdb.lookup_global_symbol(fn_full_name, gdb.SYMBOL_FUNCTIONS_DOMAIN) block = gdb.block_for_pc(long(sym.value().address)) ptr = block.start while ptr < block.end: da = arch.disassemble(ptr)[0] if da['asm'].rstrip().endswith('retq'): print 'setting up finish breakpoint for', da on_result_ready_instance = on_result_ready( on_enter_instance, '*0x%lx' % da['addr']) ptr += da['length']
def get_block_from_pc(pc): ''' :param pc: frame's resume address :type pc: gdb.Frame.pc() :returns: a gdb.Block object or None ''' return gdb.block_for_pc(pc)
def print_instruction_at(self, addr, stack_percentage): gdb.write(str(round(stack_percentage, 2)) + ":") str_to_eval = "info line *" + hex(addr) #gdb.execute(str_to_eval) res = gdb.execute(str_to_eval, to_string=True) # get information from results string: words = res.split() valid = False if words[0] == 'No': #no line info... pass else: valid = True line = int(words[1]) idx = words[3].rfind("/") #find first backslash if idx > 0: name = words[3][idx + 1:] path = words[3][:idx] else: name = words[3] path = "" block = gdb.block_for_pc(addr) func = block.function if str(func) == "None": func = block.superblock.function if valid: print("Line: ", line, " in ", path, "/", name, "in ", func) return name, path, line, func
def functionptr_to_chunks(self, value, name, path, **kwargs): chunks = [] type_code = value.type.strip_typedefs().code if type_code == gdb.TYPE_CODE_METHOD: #Workaround: get address of class method s = unicode(value) idx = re.search('0x[0-9A-Fa-f]+', s).regs[0] func_addr = long(s[int(idx[0]):int(idx[1])], 0) else: func_addr = self.ptrval_to_ulong(value) function = None try: block = gdb.block_for_pc(func_addr) except RuntimeError: block = None while block: if block.function: function = block.function break block = block.superblock if function: func_name = function.name else: func_name = 'unknown' chunks += self.chunks_type_name(value, name, **kwargs) valuetype = self.stringify_type(value.type) chunks += self.changable_strvalue_to_chunks(str(func_addr), path, valuetype, **kwargs) chunks.append({'str': ' '}) chunks.append({'str': '<{}>'.format(func_name)}) return chunks
def _search_frame(self, frame, vertex, enclosingFrame=None): sal = frame.find_sal() try: block = gdb.block_for_pc(sal.pc) except RuntimeError as e: return for symbol in block: self._enqueue(symbol, parentVertex=vertex, frame=frame)
def funcName(pc): try: return str(gdb.block_for_pc(pc).function) except RuntimeError: # block_for_pc is supposed to return None if it failed, # but actually throws RuntimeError("Cannot location object # file for block.") return "%#x" % pc
def trace_function(indent, annotation, data): fn, caller = data try: block = gdb.block_for_pc(long(fn)) fn_name = block.function.print_name except: fn_name = "???" out_func("0x%016x %2d %19s %s %s %s\n" % (thread, cpu, format_time(time), indent, annotation, fn_name))
def __get_current_block_start_address(): pc = int(pwngef.arch.CURRENT_ARCH.pc) try: block_start = gdb.block_for_pc(pc).start except RuntimeError: # if stripped, let's roll back 5 instructions block_start = disass.gdb_get_nth_previous_instruction_address( pc, 5) return block_start
def func_and_offset(addr): '''Return the function and offset into that function of `addr`. If failed to find the function at the given address, return (None, None). ''' # If given @plt addresses (or other problematic functions) just ignore # them and return an error message -- (better than raising an error?) try: block = gdb.block_for_pc(addr) except RuntimeError as e: # If this is an exception we don't know about, raise. if e.args != ('Cannot locate object file for block.',): raise # Attempt to work with symbols that don't have debugging information. retval = gdb.execute('info symbol {}'.format(addr), False, True) # Checking for section ".text" removes @plt stubs and variables. if 'in section .text' not in retval: print('{} is not a .text location'.format(addr)) return (None, None) # At the moment I believe that all awkward output (i.e. of the form # funcname(function, argument, types) in section .text of /home/matthew/temp_dir/gdb/gdb/gdb # are avoided because when there is debug info we've used the alternate # method. Hence, the output should be of the form # <funcname> + <offset> in section .text of <objfile> # If this isn't the case, alert user so I know there's a problem and # can investigate what I've missed. # # NOTE: I believe that digits are always printed in decimal -- can't # find any way to change this, so I believe there isn't one. # If this isn't the case, then I hopefully will notice the problem when # this function fails. sym_match = re.match('(\S+)( \+ (\d+))? in section .text', retval) if not sym_match: print('Cannot parse output from command `info symbol {}`.'.format( addr)) return (None, None) offset = int(sym_match.group(3)) if sym_match.group(3) else 0 return (sym_match.group(1), offset) while block.function is None: if block.superblock: block = block.superblock else: raise gdb.GdbError('Could not find enclosing function of ' '{} ({})'.format(addr, arg)) offset = addr - block.start return (block.function.name, offset)
def _update_frame(self): # We used to do set_cpu_regs() here and then get a gdb.Frame, but that's # really slow. We don't care too much about the detail here, so just # lookup the function name. try: self.block = gdb.block_for_pc(self.regs[15]) except: class FakeBlock(object): pass self.block = FakeBlock() self.block.function = "??" while self.block.function is None: self.block = self.block.superblock self.frame_str = "0x%X in %s ()" % (self.regs[15], self.block.function)
def resolve_file_line_func(self,addr,stack_percentage): gdb.write(str(round(stack_percentage,2))+":") str_to_eval = "info line *"+hex(addr) #gdb.execute(str_to_eval) res = gdb.execute(str_to_eval,to_string = True) # get information from results string: words = res.split() if words[0] != 'No': line = int(words[1]) block = gdb.block_for_pc(addr) func = block.function if str(func) == "None": func = block.superblock.function return words[3].strip('"'), line, func
def resolve_file_line_func(self, addr, stack_percentage): gdb.write(str(round(stack_percentage, 2)) + ":") str_to_eval = "info line *" + hex(addr) #gdb.execute(str_to_eval) res = gdb.execute(str_to_eval, to_string=True) # get information from results string: words = res.split() if words[0] != 'No': line = int(words[1]) block = gdb.block_for_pc(addr) func = block.function if str(func) == "None": func = block.superblock.function return words[3].strip('"'), line, func
def fileLine(pc): # UGH. Iterating over a line table crashes hard in GDB 7.9. try: block = gdb.block_for_pc(pc) except RuntimeError: return "%#x" % pc lt = block.function.symtab.linetable() pcent = None for ltent in lt: if ltent.pc > pc: break pcent = ltent if pcent == None: return "%#x" % pc return "%s:%d" % (block.function.symtab.filename, pcent.line)
def trace_function(indent, annotation, data): fn, caller = data try: block = gdb.block_for_pc(long(fn)) fn_name = block.function.print_name except: fn_name = '???' out_func('0x%016x %2d %19s %s %s %s\n' % ( thread, cpu, format_time(time), indent, annotation, fn_name, ))
def find_symbol(addr: Ptr) -> Optional[gdb.Symbol]: """ Find the top-level Symbol associated with an address. Due to limitations of the GDB Python bindings this will only find symbols with debug information (not what gdb calls "minimal symbols"). """ try: block = gdb.block_for_pc(addr.addr()) except RuntimeError: return None while block is not None and not block.function: block = block.superblock return block.function if block is not None else None
def trace_function(indent, annotation, data): fn, caller = data try: block = gdb.block_for_pc(to_int(fn)) fn_name = block.function.print_name except: fn_name = '???' out_func('0x%016x %2d %19s %s %s %s\n' % (thread, cpu, format_time(time), indent, annotation, fn_name, ))
def __call__(self, pending_frame): pc_desc = pending_frame.architecture().registers().find("pc") pc = pending_frame.read_register(pc_desc) block = gdb.block_for_pc(int(pc)) if block is None: return None func = block.function if func is None: return None print("Func %s, Level %d" % (str(func), pending_frame.level())) # This unwinder never claims any frames. return None
def invoke(self, _arg, _from_tty): # args = gdb.string_to_argv(arg) vp = gdb.lookup_type('void').pointer() for ptr in SliceValue(gdb.parse_and_eval("'runtime.allgs'")): if ptr['atomicstatus'] == G_DEAD: continue s = ' ' if ptr['m']: s = '*' pc = ptr['sched']['pc'].cast(vp) pc = pc_to_int(pc) blk = gdb.block_for_pc(pc) status = int(ptr['atomicstatus']) st = sts.get(status, "unknown(%d)" % status) print(s, ptr['goid'], "{0:8s}".format(st), blk.function)
def get_symbol_name(addr): try: block = gdb.block_for_pc(int(addr)) except: try: return gdb.execute('info symbol ' + hex(addr), False, True).split(' ')[0] except: return '<unknown>' while block and not block.function: block = block.superblock if block is None: return '<unknown>' return block.function.print_name
def trace_function(indent, annotation, data): fn, caller = data try: block = gdb.block_for_pc(long(fn)) fn_name = block.function.print_name except: fn_name = '???' out_func('0x%016x %2d %12d.%06d %s %s %s\n' % (thread, cpu, time / 1000000000, (time % 1000000000) / 1000, indent, annotation, fn_name, ))
def _func_get_address_range(self, gdbsym_specified): """ gdb.Symbol が表す symbol の専有アドレス範囲を返す 不明な gdb.Symbol が指定された場合は、(None, None) を返す """ tpl_range = (None, None) if (gdbsym_specified.is_variable or # variable gdbsym_specified.is_argument or # 引数 gdbsym_specified.is_constant ): gdbval_specified = gdbsym_specified.value(gdb.selected_frame()) int_first_address = int(gdbval_specified.address.cast(self._gdbtyp_address_length_uint)) int_last_address = int_first_address + gdbval_specified.type.sizeof - 1 tpl_range = (int_first_address, int_last_address) elif (gdbsym_specified.is_function): # function gdbval_func_adr = gdbsym_specified.value(gdb.selected_frame()) int_func_adr = int(gdbval_func_adr.cast(self._gdbtyp_address_length_uint)) # function を表す symbol の場合は、 # .value() で返ってくる gdb.Value に対して # 直接 int へ cast できない。(理由は不明) # gdbblk_target = gdb.block_for_pc(int_func_adr) # 関数が配置されている アドレスの block を取得 gdbblk_target = gdb.block_for_pc(int_func_adr) int_first_address = gdbblk_target.start int_last_address = gdbblk_target.end tpl_range = (int_first_address, int_last_address) else: # unkown なシンボルの場合 insobj_curframe_b_back = inspect.currentframe().f_back sys.stderr.write( "[error] Cannot calculate address range Because of" + "\n" + "[error] specified gdb.Symbol object has unkown type." + "\n" + "[error] Which is not variable, argment, constant, nor function." + "\n" + "[error] str(gdb.Symbol):" + str(gdbsym_specified) + "\n" + "[error] The corresponding code part is" + "\n" + "[error] File:" + insobj_curframe_b_back.f_code.co_filename + "\n" + "[error] Function:" + insobj_curframe_b_back.f_code.co_name + "\n" + "[error] Line no:" + str(insobj_curframe_b_back.f_lineno) + "\n" ) return tpl_range
def __call__(self, pending_frame): pc_desc = pending_frame.architecture().registers().find("pc") pc = pending_frame.read_register(pc_desc) sp_desc = pending_frame.architecture().registers().find("sp") sp = pending_frame.read_register(sp_desc) block = gdb.block_for_pc(int(pc)) if block == None: return None func = block.function if func == None: return None if str(func) != "break_bt_here": return None fid = FrameId(pc, sp) return pending_frame.create_unwind_info(fid)
def show_lines(sal, indent=0): curline = sal.line fname = sal.symtab.filename function = gdb.block_for_pc(sal.pc).function gdb.write("file: {} function: {}\n".format( colorize('col_file', fname), colorize('col_function', function))) lines = gdb.execute("list {}:{}".format(fname, curline), False, True) found = False for l in lines.splitlines(): if not found: w = l.split() if len(w) > 0 and int(w[0]) == curline: gdb.write(" " * indent + colorize('col_curline', l.expandtabs()) + "\n") found = True continue gdb.write(" " * indent + l + "\n")
def _update_frame(self): # We don't care too much about the detail here, so just # lookup the function name. #print("r13 %08x lr %08x pc %08x" % (self.regs[13], self.regs[14], self.regs[15])) try: self.block = gdb.block_for_pc(int(self.regs[15])) except Exception as e: class FakeBlock(object): pass self.block = FakeBlock() self.block.function = "??" print(e) while self.block.function is None: self.block = self.block.superblock self.frame_str = "0x%x in %s ()" % (self.regs[15], self.block.function)
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 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 get_function_block(addr): '''Does gdb.block_for_pc(addr) but raises the same exception if object file can't be found as if the block found is None, static, or global. This is just for convenience. ''' func_block = gdb.block_for_pc(addr) # Want the same thing to happen when gdb can't find the object file (and # hence raises an exception itself) as when it just can't find the block, # or found a static / global (i.e. file-sized) block instead of a function # block. # I've seen getting a static block when asking for the block at a # function address happen with je_extent_tree_szad_new() function when # debugging neovim. if func_block is None or func_block.is_static or func_block.is_global: raise RuntimeError('Cannot locate object file for block.') return func_block
def lookup_pcs(inpath): inbase, inext = os.path.splitext(inpath) outpath = inbase + '-mapped' + inext fin = open(inpath, 'rt') pc_list = json.load(fin) fin.close() pc_map = {} for pc in pc_list: block = gdb.block_for_pc(pc) if block is None: continue func = block.function if block.function is None: continue pc_map[hex(pc)] = [func.symtab.filename, func.name] fout = open(outpath, 'wt') json.dump(pc_map, fout, indent=2) fout.close()
def get_func_name(self): if self.pc is not None: try: block = gdb.block_for_pc(self.pc) if block is not None: if block.function is not None: return block.function.name if block.superblock is not None and block.superblock.function is not None: return block.superblock.function.name except RuntimeError: pass if self.is_js_frame(): js_function_addr = self.topy(self.CALLEE) to_call = self.get_name_str % (self.addr, js_function_addr) #print "about to call " + to_call val = gdb.parse_and_eval(to_call) return "js: " + wtf_string_to_utf8(val) return "<unknown native func>"
def get_func_name(self): if self.pc is not None: try: block = gdb.block_for_pc(self.pc) if block is not None: if block.function is not None: return block.function.name if block.superblock is not None and block.superblock.function is not None: return block.superblock.function.name except RuntimeError: pass if self.is_js_frame(): js_function_addr = self.topy(self.CALLEE) to_call = self.get_name_str % (self.addr, js_function_addr) #print "about to call " + to_call val = gdb.parse_and_eval(to_call) return "js: "+wtf_string_to_utf8(val) return "<unknown native func>"
def __str__(self): # adjust pc according to ARM/THUMB mode pc = self.pc & (~1) if self.is_thumb else self.pc & (~3) try: block = gdb.block_for_pc(pc) except RuntimeError: block = None if block and block.is_valid() and block.function: func = block.function.print_name else: func = gdb.execute('info symbol ' + hex(pc), True, True).strip() if func.startswith('No symbol'): func = '??' for sep in ['(', '+', 'in section']: if sep in func: func = func[:func.find(sep)].strip() break lib = gdb.solib_name(pc) lib = os.path.basename(lib) if lib else '??' return 'frame {0:#08x} in function {1} ({2:#08x}) from {3}'.format( self.sp, func, pc, lib)
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 __str__(self): # adjust pc according to ARM/THUMB mode pc = self.pc & (~1) if self.is_thumb else self.pc & (~3) try: block = gdb.block_for_pc(pc) except RuntimeError: block = None if block and block.is_valid() and block.function: func = block.function.print_name else: func = gdb.execute('info symbol ' + hex(pc), True, True).strip() if func.startswith('No symbol'): func = '??' for sep in ['(', '+', 'in section']: if sep in func: func = func[: func.find(sep)].strip() break lib = gdb.solib_name(pc) lib = os.path.basename(lib) if lib else '??' return 'frame {0:#08x} in function {1} ({2:#08x}) from {3}'.format( self.sp, func, pc, lib)
def functionptr_to_chunks_argtypes(self, value, name, path, **kwargs): arg_types = [ field.type for field in value.dereference().type.strip_typedefs().fields() ] return_type = value.dereference().type.strip_typedefs().target() func_addr = self.ptrval_to_ulong(value) func_name = 'unknown' try: block = gdb.block_for_pc(func_addr) except RuntimeError: block = None while block: if block.function: func_name = block.function.name break block = block.superblock chunks = [] chunks.append({'str': '{'}) chunks.append({'str': str(return_type), 'name': 'datatype'}) chunks.append({'str': ' '}) chunks.append({'str': '('}) arg_chunks = [{ 'str': str(arg_type), 'name': 'datatype' } for arg_type in arg_types] if len(arg_chunks) > 0: arg_chunks_commas = [] arg_chunks_commas.append(arg_chunks[0]) for arg_chunk in arg_chunks[1:]: arg_chunks_commas.append({'str': ','}) arg_chunks_commas.append(arg_chunk) chunks += arg_chunks_commas chunks.append({'str': ')'}) chunks.append({'str': '}'}) chunks.append({'str': ' '}) chunks.append({'str': hex(func_addr)[:-1]}) chunks.append({'str': ' '}) chunks.append({'str': '<{}>'.format(func_name)}) return chunks
def get_pc_context_info(self, pc, line): try: current_block = gdb.block_for_pc(pc) if not current_block.is_valid(): return "" m = collections.OrderedDict() while current_block and not current_block.is_static: for sym in current_block: symbol = sym.name if not sym.is_function and re.search( r"\W{}\W".format(symbol), line): val = gdb.parse_and_eval(symbol) if val.type.code in (gdb.TYPE_CODE_PTR, gdb.TYPE_CODE_ARRAY): addr = int(val.address) addrs = pwngef.chain.examine_mem_value(addr) if len(addrs) > 2: addrs = [addrs[0], "[...]", addrs[-1]] f = " {:s} ".format(config_arrow_right) val = f.join(addrs) elif val.type.code == gdb.TYPE_CODE_INT: val = hex(int(val)) else: continue if symbol not in m: m[symbol] = val current_block = current_block.superblock if m: return "// " + ", ".join([ "{}={}".format(Color.yellowify(a), b) for a, b in m.items() ]) except Exception: pass return ""
def invoke(self, arg, from_tty): args = gdb.string_to_argv(arg) frame = "$rbp" if len(args) > 0: frame = args[0] depth = 30 if len(args) > 1: depth = int(args[1]) for i in range(depth-1, -1, -1): ret = gdb.parse_and_eval(f"*(uint64_t*)({frame} + 8)") frame = gdb.parse_and_eval(f"*(uint64_t*)({frame})") name = "" block = gdb.block_for_pc(int(ret)) if block: name = block.function or "" print("{:016x} {}".format(int(ret), name)) if frame == 0 or ret == 0: return
def register_journal_buffer_io_sync(cls, sym): # ext3/ext4 and jbd/jbd2 share names but not implementations b = gdb.block_for_pc(long(sym.value().address)) sym = get_symbol_value('journal_end_buffer_io_sync', b) register_buffer_head_decoder(sym, cls.decode_journal_buffer_io_sync)
def invoke(self, args, from_tty): argv = parse_argv(args) if len(argv) > 1: print('Usage: walkstk [fp]') return # Bail early if the custom unwinder has not been set up. if not unwind.try_unwinder_init(): print('walkstk: Could not initialize the HHVM unwinder.') # Find the starting native frame. native_frame = gdb.newest_frame() if native_frame is None: print('walkstk: Cannot find any frames: corrupt stack?') return # Set fp = $rbp, rip = $rip. fp_type = T('uintptr_t').pointer() fp = native_frame.read_register('rbp').cast(fp_type) rip = native_frame.pc() if len(argv) == 1: # Start walking the stack from the user-provided `fp'. fp = argv[0].cast(fp_type)[0] rip = argv[0].cast(fp_type)[1] # Try to find a corresponding native frame. while (native_frame is not None and rip != native_frame.pc()): native_frame = native_frame.older() i = 0 # Make a fake frame for our `fp' and `rip'. This lets us pop a frame # at the top of the loop, which makes it easier to include the final # frame. fp = (fp, rip) while fp: rip = fp[1] fp = fp[0].cast(fp_type) # Try to get the PHP function name from the ActRec at `fp' if we're # executing in the TC. if frame.is_jitted(fp, rip): ar_type = T('HPHP::ActRec').pointer() try: print( frame.stringify( frame.create_php(idx=i, ar=fp.cast(ar_type), rip=rip))) except gdb.MemoryError: print( frame.stringify( frame.create_native(idx=i, fp=fp, rip=rip, native_frame=native_frame))) if native_frame is not None: native_frame = native_frame.older() i += 1 else: if native_frame is None: # If we couldn't find a native frame, then `walkstk' was # invoked with a non-native `fp' argument. Now that we # don't seem to be in the TC, try to find the corresponding # native frame. native_frame = gdb.newest_frame() while (native_frame is not None and rip != native_frame.pc()): native_frame = native_frame.older() if native_frame is not None: # Pop native frames until we hit our caller's rip. frames = [] while (native_frame is not None and (fp == 0x0 or fp[1] != native_frame.pc())): frames.append( frame.create_native(idx=i, fp='{inline frame}', rip=native_frame.pc(), native_frame=native_frame)) native_frame = native_frame.older() i += 1 if frames: # Associate the frame pointer with the un-inlined frame. frames[-1]['fp'] = str(fp) for f in frames: print(frame.stringify(f)) else: # We only hit this case if gdb undercounted the TC's # frames---which shouldn't happen unless the custom # unwinder (or gdb's unwinder API) is malfunctioning. # # Just guess that the name of the frame is the same as the # name of the block we're in. try: block = gdb.block_for_pc(int(rip)) name = block.function.name print( frame.stringify( frame.create_native(idx=i, fp=fp, rip=rip, name='? ' + name))) except: print( frame.stringify( frame.create_native(idx=i, fp=fp, rip=rip, native_frame=None))) i += 1
def get_func_block(funcName): # this is a completely and utterly ridiculous thing to have to do... pc = gdb.decode_line(funcName)[1][0].pc return gdb.block_for_pc(pc)
def invoke(self, args, from_tty): argv = parse_argv(args) if len(argv) > 1: print('Usage: walkstk [fp]') return # Bail early if the custom unwinder has not been set up. if not unwind.try_unwinder_init(): print('walkstk: Could not initialize the HHVM unwinder.') # Find the starting native frame. native_frame = gdb.newest_frame() if native_frame is None: print('walkstk: Cannot find any frames: corrupt stack?') return # Set fp = $rbp, rip = $rip. fp_type = T('uintptr_t').pointer() fp = native_frame.read_register('rbp').cast(fp_type) rip = native_frame.pc() if len(argv) == 1: # Start walking the stack from the user-provided `fp'. fp = argv[0].cast(fp_type)[0] rip = argv[0].cast(fp_type)[1] # Try to find a corresponding native frame. while (native_frame is not None and rip != native_frame.pc()): native_frame = native_frame.older() i = 0 # Make a fake frame for our `fp' and `rip'. This lets us pop a frame # at the top of the loop, which makes it easier to include the final # frame. fp = (fp, rip) while fp: rip = fp[1] fp = fp[0].cast(fp_type) # Try to get the PHP function name from the ActRec at `fp' if we're # executing in the TC. if frame.is_jitted(fp, rip): ar_type = T('HPHP::ActRec').pointer() try: print(frame.stringify(frame.create_php( idx=i, ar=fp.cast(ar_type), rip=rip))) except gdb.MemoryError: print(frame.stringify(frame.create_native( idx=i, fp=fp, rip=rip, native_frame=native_frame))) if native_frame is not None: native_frame = native_frame.older() i += 1 else: if native_frame is None: # If we couldn't find a native frame, then `walkstk' was # invoked with a non-native `fp' argument. Now that we # don't seem to be in the TC, try to find the corresponding # native frame. native_frame = gdb.newest_frame() while (native_frame is not None and rip != native_frame.pc()): native_frame = native_frame.older() if native_frame is not None: # Pop native frames until we hit our caller's rip. frames = [] while (native_frame is not None and (fp == 0x0 or fp[1] != native_frame.pc())): frames.append(frame.create_native( idx=i, fp='{inline frame}', rip=native_frame.pc(), native_frame=native_frame)) native_frame = native_frame.older() i += 1 if frames: # Associate the frame pointer with the un-inlined frame. frames[-1]['fp'] = str(fp) for f in frames: print(frame.stringify(f)) else: # We only hit this case if gdb undercounted the TC's # frames---which shouldn't happen unless the custom # unwinder (or gdb's unwinder API) is malfunctioning. # # Just guess that the name of the frame is the same as the # name of the block we're in. try: block = gdb.block_for_pc(int(rip)) name = block.function.name print(frame.stringify(frame.create_native( idx=i, fp=fp, rip=rip, name='? ' + name))) except: print(frame.stringify(frame.create_native( idx=i, fp=fp, rip=rip, native_frame=None))) i += 1
def get_all_functions_from_pc(pc): block = gdb.block_for_pc(pc) for symb in block.global_block: if not symb.is_function: continue yield symb
def _extract_all_blocks(self): for entry in self._linetable: block = gdb.block_for_pc(entry.pc) self._add_block_to_graph(block)