def wrapper(*args, **kwargs): try: gdb.selected_frame() except RuntimeError: raise gdb.GdbError("No frame is currently selected.") return function(*args, **kwargs)
def invoke (self, arg, from_tty): # Get to the call resolve function. i = 0 while not symbol_equal_to_string(gdb.selected_frame().function(), self.START_FUNC): if symbol_equal_to_string(gdb.selected_frame().function(), self.SKIP_FUNC): gdb.execute("finish", False, to_string=True) if i > Eo_step.STEP_LIMIT: break else: i += 1 gdb.execute("step", False, to_string=True) # If we found the function, return from it, otherwise, fail. if symbol_equal_to_string(gdb.selected_frame().function(), self.START_FUNC): gdb.execute("finish", False, to_string=True) else: print("Search limit reached, you tried calling eo_step too far from an eo_do.") return # Step until we move to a different function. FIXME: The hook can confuse us, needs to be solved. cur_func = gdb.selected_frame().function() while gdb.selected_frame().function() == cur_func: gdb.execute("stepi", False, to_string=True) # One last call to skip into the implementation gdb.execute("step", True)
def invoke(self, arg, from_tty): args = arg.split() max = 0 if len(args) >= 1: max = int(args[0]) events = collections.defaultdict(list) frequency = float(gdb.selected_frame().read_var("ftracer_frequency")) thr_max = 0 for i in gdb.inferiors(): for t in i.threads(): gdb.execute("thread %d" % (t.num,)) ftracer_len = gdb.selected_frame().read_var("ftracer_size") x = gdb.selected_frame().read_var("ftracer_tbuf") for j in range(0, ftracer_len-1): v = x[j] tstamp = int(v["tstamp"]) if tstamp: o = (t.num, v["func"], v["arg1"], v["arg2"], v["arg3"], v["rsp"]) events[tstamp].append(o) if int(t.num) > thr_max: thr_max = int(t.num) print ("%*s %*s %3s %-*s %s" % (TSTAMP_WIDTH, "TIME", TSTAMP_WIDTH, "DELTA", "THR", THR_WIDTH * thr_max, "FUNC", "ARGS")) prev = 0 delta = 0 start = 0 threads = collections.defaultdict(Thr) k = sorted(events.keys()) if max: k = collections.deque(k, max) for t in k: if prev: delta = t - prev if start == 0: start = t for e in events[t]: tnum = e[0] thr = threads[tnum] thr.update(int(e[5])) if thr_max >= 8: func = "<%d> " % (tnum) width = 30 else: func = " " * (THR_WIDTH * (tnum-1)) width = THR_WIDTH * thr_max, func += " " * (thr.level() * 2) func += resolve(int(e[1])) print "%*.2f %*.2f %3d %-*s %x %x %x" % ( TSTAMP_WIDTH, (t - start) / frequency, TSTAMP_WIDTH, delta / frequency, tnum, width, func, int(e[2]), int(e[3]), int(e[4])) prev = t
def getinsn(): length = gdb.selected_frame().architecture().disassemble(gdb.selected_frame().pc())[0]['length'] CODE = gdb.selected_inferior().read_memory(gdb.selected_frame().pc(), length).tobytes() md = Cs(CS_ARCH_X86, CS_MODE_64) md.detail = True insns = list(md.disasm(CODE, 0x1000)) assert(len(insns) == 1) return insns[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 []
def setloc(): global loc try: # loc = "%i:%s"%(gdb.newest_frame().find_sal().line, gdb.newest_frame().find_sal().symtab.filename) loc = "%i:%s"%(gdb.selected_frame().find_sal().line, gdb.selected_frame().find_sal().symtab.filename) # print(loc) except gdb.error: pass
def disassemble_block(block=None): global _arch if block is None: _block = gdb.selected_frame().block() else: _block = block if _arch is None: _arch = gdb.selected_frame().architecture() return _arch.disassemble(_block.start, _block.end)
def invoke (self, arg, from_tty): # While libeo is not reached, we step into while gdb.solib_name(gdb.selected_frame().pc()).find("libeo.so") == -1: # step by one assembly instruction, no print gdb.execute("stepi", False, to_string=True) # While we are in libeo or in an unknown function, we step into while (gdb.selected_frame().function() == None) or (gdb.solib_name(gdb.selected_frame().pc()).find("libeo.so") != -1): # step by one assembly instruction, no print gdb.execute("stepi", False, to_string=True) print "Stopped at file " + gdb.selected_frame().find_sal().symtab.filename+ " line " + str(gdb.selected_frame().find_sal().line) + " function " + str(gdb.selected_frame().function())
def send_expr(self): try: if self.last_frame != gdb.selected_frame(): print('new frame') self.refresh_expr = True self.last_frame = gdb.selected_frame() except: pass if self.expr is not None and self.refresh_expr: self.refresh_expr = False self.vim(op='refresh', expr=self.expr)
def invoke(self, *args): try: gdb.execute(self._command, to_string=True) while not self.is_relevant_function(gdb.selected_frame()): gdb.execute(self._command, to_string=True) except RuntimeError as e: raise gdb.GdbError(*e.args) frame = gdb.selected_frame() index = 0 while frame: frame = frame.older() index += 1 self.print_stackframe(index=index - 1)
def update_observable_suggestions(): frame = gdb.selected_frame() block = frame.block() observable_symbols = list() while not block is None: for symbol in block: if (symbol.is_argument or symbol.is_variable): name = symbol.name # Get struct/class fields if name == 'this': # The GDB API is a bit convoluted, so I have to do some contortion in order # to get the class type from the this object so I can iterate over its fields this_type = gdb.parse_and_eval(symbol.name).dereference().type for field_name, field_val in this_type.iteritems(): if (not field_name in observable_symbols) and (gdbiwtype.is_symbol_observable(field_val)): observable_symbols.append(field_name) elif (not name in observable_symbols) and (gdbiwtype.is_symbol_observable(symbol)): observable_symbols.append(name) pass pass pass block = block.superblock pass if lib.is_running(): lib.update_available_variables(observable_symbols) pass
def __init__(self, handle): self.handle = long(handle) if ObjectHandle.eg is None: ObjectHandle.eg = gdb.selected_frame().read_var('executor_globals') self.store = self.eg['objects_store']
def invoke(self, arg, from_tty): tc = gdb.selected_frame().read_var(arg if arg else "tc") if not str(tc.type).startswith("MVMThreadContext"): raise ValueError("Please invoke the heap analyzer command on a MVMThreadContext, usually tc.") # find out the GC generation we're in (just a number increasing by 1 every time we GC) instance = tc['instance'] generation = instance['gc_seq_number'] nursery = NurseryData(generation, tc['nursery_tospace'], tc['nursery_alloc_limit'], tc['nursery_alloc']) nursery.analyze(tc) nursery_memory.append(nursery) print("the current generation of the gc is", generation) sizeclass_data = [] for sizeclass in range(MVM_GEN2_BINS): g2sc = Gen2Data(generation, tc['gen2']['size_classes'][sizeclass], sizeclass) sizeclass_data.append(g2sc) g2sc.analyze(tc) overflowdata = OverflowData(generation) overflowdata.analyze(tc) for g2sc in sizeclass_data: g2sc.summarize() nursery.summarize() overflowdata.summarize()
def bt(demangle=True): # Find the newest frame. frame = gdb.selected_frame() while True: next = frame.newer() if not next: break frame = next if demangle: pipe = os.popen('c++filt', 'w') else: pipe = sys.stdout i = 0 while frame: s = gdb.execute('p dumpSymbol((void*)0x%x)' % frame.pc(), to_string=True) m = re.match(r'.*"(.*)"$', s) if m: pipe.write("#%-2d %s\n" % (i, m.group(1))) else: sal = frame.find_sal() lineno = '' if sal.symtab: lineno = ' at %s:%d' % (sal.symtab, sal.line) pipe.write("#%-2d 0x%x %s%s\n" % (i, frame.pc(), frame.name(), lineno)) frame = frame.older() i += 1 pipe.close()
def __init__(self, thread_ctx): self.thread_ctx = thread_ctx self.old_frame = gdb.selected_frame() self.old_regs = self.save_regs() self.old_gdb_thread = gdb.selected_thread() self.gdb_thread = get_thread_owning_memory(thread_ctx.address) self.new_regs = None
def invoke(self, arg, for_tty): thread_nr = 0 exit_thread_context() state = vmstate() for t in state.thread_list: with thread_context(t, state): cpu = thread_cpu(t) tid = t["_id"] name = t["_attr"]["_name"]["_M_elems"].string() newest_frame = gdb.selected_frame() # Non-running threads have always, by definition, just called # a reschedule, and the stack trace is filled with reschedule # related functions (switch_to, schedule, wait_until, etc.). # Here we try to skip such functions and instead show a more # interesting caller which initiated the wait. file_blacklist = [ "arch-switch.hh", "sched.cc", "sched.hh", "mutex.hh", "mutex.cc", "mutex.c", "mutex.h", ] # Functions from blacklisted files which are interesting sched_thread_join = "sched::thread::join()" function_whitelist = [sched_thread_join] def is_interesting(resolved_frame): is_whitelisted = resolved_frame.func_name in function_whitelist is_blacklisted = os.path.basename(resolved_frame.file_name) in file_blacklist return is_whitelisted or not is_blacklisted fr = find_or_give_last(is_interesting, traverse_resolved_frames(newest_frame)) if fr: location = "%s at %s:%s" % (fr.func_name, strip_dotdot(fr.file_name), fr.line) else: location = "??" gdb.write( "%4d (0x%x) %-15s cpu%s %-10s %s vruntime %12g\n" % ( tid, ulong(t), name, cpu["arch"]["acpi_id"] if cpu != 0 else "?", thread_status(t), location, t["_runtime"]["_Rtt"], ) ) if fr and fr.func_name == sched_thread_join: gdb.write("\tjoining on %s\n" % fr.frame.read_var("this")) show_thread_timers(t) thread_nr += 1 gdb.write("Number of threads: %d\n" % thread_nr)
def get_frame(self): try: frame = gdb.selected_frame() except gdb.error: raise NoFrame("no frame is selected") return frame
def invoke(self, args, from_tty): # get the first frame selected_frame = frame = gdb.selected_frame() while frame.older(): frame = frame.older() print_all = args == '-a' index = 0 while frame: is_c = False is_relevant = False try: is_relevant = self.is_relevant_function(frame) except CyGDBError: pass if print_all or is_relevant: self.print_stackframe(frame, index) index += 1 frame = frame.newer() selected_frame.select()
def invoke(self, arg, from_tty): frame = gdb.selected_frame() val = frame.read_var(arg) if str(val.type.strip_typedefs()) == 'SkBitmap': pixels = val['fPixels'] row_bytes = val['fRowBytes'] info = val['fInfo'] width = info['fWidth'] height = info['fHeight'] color_type = info['fColorType'] alpha_type = info['fAlphaType'] process = gdb.selected_inferior() memory_data = process.read_memory(pixels, row_bytes * height) size = (width, height) image = None # See Unpack.c for the values understood after the "raw" parameter. if color_type == ColorType.bgra_8888.value: if alpha_type == AlphaType.unpremul.value: image = Image.frombytes("RGBA", size, memory_data.tobytes(), "raw", "BGRA", row_bytes, 1) elif alpha_type == AlphaType.premul.value: # RGBA instead of RGBa, because Image.show() doesn't work with RGBa. image = Image.frombytes("RGBA", size, memory_data.tobytes(), "raw", "BGRa", row_bytes, 1) if image: # Fails on premultiplied alpha, it cannot convert to RGB. image.show() else: print ("Need to add support for %s %s." % ( str(ColorType(int(color_type))), str(AlphaType(int(alpha_type))) ))
def stop(self): frame = gdb.selected_frame().older() for spec in self._backtrace_specs: if not (frame and spec.matches(frame)): return False frame = frame.older() return True
def invoke (self, arg, from_tty): self.dont_repeat() num = arg and int(arg) or 100 self.setup() try: while num > 0: num -= 1 gdb.execute('continue') frame = gdb.selected_frame() if frame.pc() != self.func: raise KeyboardInterrupt node = gdb.parse_and_eval('(NODE*) $rsi') file = node['nd_file'].string() line = gdb.parse_and_eval('nd_line(%s)' % node) method = gdb.parse_and_eval('rb_id2name($rcx)') method = method > 0 and method.string() or '(unknown)' print "%s in %s:%d" % (method,file,line) self.teardown() except KeyboardInterrupt: self.teardown() except RuntimeError, text: self.teardown() if not re.search('signaled while in a function called from GDB', text): raise
def break_handler(event): pp = pprint.PrettyPrinter(2) while (gdb.selected_frame().name() != 'rb_eval'): gdb.execute('up') node = gdb.parse_and_eval('node') pp.pprint(inspect_node(node)) gdb.execute('continue')
def invoke(self, arg, from_tty): # delete all breakpoints gdb.execute("d") gdb.execute("break free") # loop iterations only in free() gdb.execute("continue") max = 1 << 24 i = 0 initial = self.memory() for i in range(max): try: mem = gdb.selected_frame().read_var("mem") current = self.mallocUsableSize(mem) except gdb.error: break bt = gdb.execute("bt", False, True) # 5 % if (current > initial*0.05): gdb.write("Current: %lu bytes, initial %lu bytes (%i iteration)\n" % (current, initial, i)) gdb.write("Backtrace before current free():\n%s\n" % (bt)) return if ((i % 100000) == 0): gdb.write("Iteration %i backtrace:\n%s\n" % (i, bt)) gdb.execute("continue", False, True) gdb.write("Finished with %i iterations\n" % (i)) gdb.write("Last backtrace:\n%s\n" % (bt))
def invoke(self, *args): try: gdb.execute(self._command, to_string=True) while not self.is_relevant_function(gdb.selected_frame()): gdb.execute(self._command, to_string=True) except RuntimeError, e: raise gdb.GdbError(*e.args)
def print_stackframe(self, frame, index, is_c=False): """ Print a C, Cython or Python stack frame and the line of source code if available. """ # do this to prevent the require_cython_frame decorator from # raising GdbError when calling self.cy.cy_cvalue.invoke() selected_frame = gdb.selected_frame() frame.select() try: source_desc, lineno = self.get_source_desc(frame) except NoFunctionNameInFrameError: print('#%-2d Unknown Frame (compile with -g)' % index) return if not is_c and self.is_python_function(frame): pyframe = libpython.Frame(frame).get_pyop() if pyframe is None or pyframe.is_optimized_out(): # print this python function as a C function return self.print_stackframe(frame, index, is_c=True) func_name = pyframe.co_name func_cname = 'PyEval_EvalFrameEx' func_args = [] elif self.is_cython_function(frame): cyfunc = self.get_cython_function(frame) f = lambda arg: self.cy.cy_cvalue.invoke(arg, frame=frame) func_name = cyfunc.name func_cname = cyfunc.cname func_args = [] # [(arg, f(arg)) for arg in cyfunc.arguments] else: source_desc, lineno = self.get_source_desc(frame) func_name = frame.name() func_cname = func_name func_args = [] try: gdb_value = gdb.parse_and_eval(func_cname) except RuntimeError: func_address = 0 else: # Seriously? Why is the address not an int? func_address = int(str(gdb_value.address).split()[0], 0) a = ', '.join('%s=%s' % (name, val) for name, val in func_args) sys.stdout.write('#%-2d 0x%016x in %s(%s)' % (index, func_address, func_name, a)) if source_desc.filename is not None: sys.stdout.write(' at %s:%s' % (source_desc.filename, lineno)) sys.stdout.write('\n') try: sys.stdout.write(' ' + source_desc.get_source(lineno)) except gdb.GdbError: pass selected_frame.select()
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 invoke(self, n = 1): for frame in FrameIterator(gdb.selected_frame()): if n <= 0: frame.select() break n = n - 1 return 1
def update(): m = sys.modules[__name__] m.current = fix_arch(gdb.selected_frame().architecture().name()) m.ptrsize = pwndbg.typeinfo.ptrsize m.ptrmask = (1 << 8*pwndbg.typeinfo.ptrsize)-1 if 'little' in gdb.execute('show endian', to_string=True): m.endian = 'little' else: m.endian = 'big' m.fmt = { (4, 'little'): '<I', (4, 'big'): '>I', (8, 'little'): '<Q', (8, 'big'): '>Q', }.get((m.ptrsize, m.endian)) # Attempt to detect the qemu-user binary name if m.current == 'arm' and m.endian == 'big': m.qemu = 'armeb' elif m.current == 'mips' and m.endian == 'little': m.qemu = 'mipsel' else: m.qemu = m.current
def goto_selected_frame(self): try: frame = gdb.selected_frame() except gdb.error: return # no frame selected filename, line = self.to_loc(frame.find_sal()) self.goto_file(filename, line)
def invoke(self, arg, from_tty): element_type = gdb.lookup_type('WebCore::Element') node_type = gdb.lookup_type('WebCore::Node') frame = gdb.selected_frame() try: val = gdb.Frame.read_var(frame, arg) except: print "No such variable, or invalid type" return target_type = str(val.type.target().strip_typedefs()) if target_type == str(node_type): stack = [] while val: stack.append([val, val.cast(element_type.pointer()).dereference()['m_tagName']]) val = val.dereference()['m_parent'] padding = '' while len(stack) > 0: pair = stack.pop() print padding, pair[1], pair[0] padding = padding + ' ' else: print 'Sorry: I don\'t know how to deal with %s yet.' % target_type
def deduce_L(): L = gdb.lookup_symbol('L')[0] if L: return L.value(gdb.selected_frame())
def cur_depth(): global GLOBAL_INDENT GLOBAL_INDENT = framedepth(gdb.selected_frame()) - break_depth return GLOBAL_INDENT
def find_helper(self): arch = gdb.selected_frame().architecture().name() for cls in GDBHelper.__inheritors__: if hasattr(cls, 'archs') and arch in cls.archs: return cls() raise LookupError('No helper found for arch {}'.format(arch))
def wrapper(self, *args, **kwargs): frame = kwargs.get('frame') or gdb.selected_frame() if not self.is_cython_function(frame): raise gdb.GdbError('Selected frame does not correspond with a ' 'Cython function we know about.') return function(self, *args, **kwargs)
def TL(name): try: return gdb.lookup_symbol(name)[0].value() except gdb.error: return gdb.lookup_symbol(name)[0].value(gdb.selected_frame())
def run_test(): test_result = {} test_port = test_params["test_port"] rom_start = test_params['rom_start'] ram_start = test_params['ram_start'] ram_length = test_params['ram_length'] invalid_addr = test_params["invalid_start"] error_on_invalid_access = test_params["expect_error_on_invalid_access"] ignore_hw_bkpt_result = test_params["ignore_hw_bkpt_result"] target_test_elf = test_params["test_elf"] assert ram_length >= MAX_TEST_SIZE stack_addr = ram_start + STACK_OFFSET test_ram_addr = ram_start + TEST_RAM_OFFSET fail_count = 0 try: # Turn off confirmations that would block the script gdb_execute("set pagination off") gdb_execute("set confirm off") # Allow GDB to access even unmapped regions gdb_execute("set mem inaccessible-by-default off") # Set raw logging gdb_execute("set remotelogfile gdb_test_raw%d.txt" % testn) # Connect to server gdb_execute("target remote localhost:%d" % test_port) # Show memory regions, useful for debug and verification. gdb_execute("info mem") # Possibly useful other commands for reference: # info breakpoints # info mem # show code-cache # show stack-cache # show dcache # show mem inaccessible-by-default # show can-use-hw-watchpoints # info all-registers # set logging file gdb.txt # set logging on # Test running the monitor commands for command in monitor_commands: gdb_execute("mon %s" % command) # Load target-specific test program into flash. gdb_execute("load %s" % target_test_elf) # Reset the target and let it run so it has # a chance to disable the watchdog gdb_execute("mon reset halt") gdb_execute("c&") event = yield (0.1) if not is_event_signal(event, "SIGINT"): fail_count += 1 print("Error - target not interrupted as expected") # Load test program and symbols test_binary = "../src/gdb_test_program/gdb_test.bin" test_elf = "../src/gdb_test_program/gdb_test.elf" gdb_execute("restore %s binary 0x%x" % (test_binary, ram_start)) gdb_execute("add-symbol-file %s 0x%x" % (test_elf, ram_start)) # Set pc to the test program. Make sure # interrupts are disabled to prevent # other code from running. gdb_execute("set $primask = 1") gdb_execute("set $sp = 0x%x" % stack_addr) gdb_execute("b main") breakpoint = gdb.Breakpoint("main") gdb_execute("set $pc = main") gdb_execute("c&") event = yield (DEFAULT_TIMEOUT) if not is_event_breakpoint(event, breakpoint): fail_count += 1 print("Error - could not set pc to function") breakpoint.delete() ## Stepping removed as a workaround for a GDB bug. Launchpad issue tracking this is here: ## https://bugs.launchpad.net/gcc-arm-embedded/+bug/1700595 # # # Test the speed of the different step types # test_result["step_time_si"] = test_step_type("si") # test_result["step_time_s"] = test_step_type("s") # test_result["step_time_n"] = test_step_type("n") test_result["step_time_si"] = -1 test_result["step_time_s"] = -1 test_result["step_time_n"] = -1 # TODO,c1728p9 - test speed getting stack trace # TODO,c1728p9 - test speed with cache turned on # TODO,c1728p9 - check speed vs breakpoints # Let target run to initialize variables gdb_execute("c&") event = yield (0.1) if not is_event_signal(event, "SIGINT"): fail_count += 1 print("Error - target not interrupted as expected") # Check number of supported breakpoints, along # with graceful handling of a request using # more than the supported number of breakpoints break_list = [] for i in range(MAX_BKPT): addr = rom_start + i * 4 breakpoint = gdb.Breakpoint("*0x%x" % addr) break_list.append(breakpoint) while True: try: gdb_execute("c&") yield (0.1) break except gdb.error: bkpt = break_list.pop() bkpt.delete() test_result["breakpoint_count"] = len(break_list) for bkpt in break_list: bkpt.delete() # Check number of supported watchpoints, along # with graceful handling of a request using # more than the supported number of watchpoints watch_list = [] for i in range(MAX_BKPT): addr = rom_start + i * 4 breakpoint = gdb.Breakpoint("*0x%x" % addr, gdb.BP_WATCHPOINT, gdb.WP_ACCESS) watch_list.append(breakpoint) while True: try: gdb_execute("c&") yield (0.1) break except gdb.error: bkpt = watch_list.pop() bkpt.delete() test_result["watchpoint_count"] = len(watch_list) for bkpt in watch_list: bkpt.delete() # Make sure breakpoint is hit as expected rmt_func = "breakpoint_test" gdb_execute("set var run_breakpoint_test = 1") breakpoint = gdb.Breakpoint(rmt_func) gdb_execute("c&") event = yield (DEFAULT_TIMEOUT) if not is_event_breakpoint(event, breakpoint): fail_count += 1 print("Error - breakpoint 1 test failed") func_name = gdb.selected_frame().function().name if rmt_func != func_name: fail_count += 1 print("ERROR - break occurred at wrong function %s" % func_name) breakpoint.delete() gdb_execute("set var run_breakpoint_test = 0") # Let target run, make sure breakpoint isn't hit gdb_execute("set var run_breakpoint_test = 1") gdb_execute("c&") event = yield (0.1) if not is_event_signal(event, "SIGINT"): fail_count += 1 print("Error - target not interrupted as expected") gdb_execute("set var run_breakpoint_test = 0") # Make sure hardware breakpoint is hit as expected rmt_func = "breakpoint_test" gdb_execute("set var run_breakpoint_test = 1") gdb_execute("hbreak %s" % rmt_func) gdb_execute("c&") event = yield (DEFAULT_TIMEOUT) # TODO, c1728p9 - determine why there isn't a breakpoint event returned # if not is_event_breakpoint(event): # fail_count += 1 # print("Error - breakpoint 2 test failed") func_name = gdb.selected_frame().function().name if rmt_func != func_name and not ignore_hw_bkpt_result: fail_count += 1 print("ERROR - break occurred at wrong function %s" % func_name) gdb_execute("clear %s" % rmt_func) gdb_execute("set var run_breakpoint_test = 0") # Test valid memory write addr_value_list = [(test_ram_addr + i * 4, randrange(1, 50)) for i in range(4)] for addr, value in addr_value_list: gdb_execute("set *((int *) 0x%x) = 0x%x" % (addr, value)) # Test invalid memory write invalid_addr_list = [invalid_addr + i * 4 for i in range(4)] for addr in invalid_addr_list: try: gdb_execute("set *((int *) 0x%x) = 0x%x" % (addr, randrange(1, 50))) if error_on_invalid_access: fail_count += 1 print("Error - invalid memory write did not fault @ 0x%x" % addr) except gdb.MemoryError: pass # Test valid memory read for addr, value in addr_value_list: val_read = gdb.parse_and_eval("*((int *) 0x%x)" % addr) val_read = int(val_read) assert value == val_read # Test invalid memory read for addr in invalid_addr_list: try: gdb_execute("x 0x%x" % addr) if error_on_invalid_access: fail_count += 1 print("Error - invalid memory read did not fault @ 0x%x" % addr) except gdb.MemoryError: pass # Test watchpoints access_addr = long(gdb.parse_and_eval("&watchpoint_write_buffer[1]")) bkpt_sizes = [1, 2, 4] bkpt_accesses = ["read", "write", "read_write"] # use "range(-4, 8, 1)" for extended testing bkpt_addresses = [access_addr + offset for offset in range(0, 4, 1)] sizes = [1, 2, 4] accesses = ["read", "write", "read_write"] addresses = [access_addr] generator = product(bkpt_sizes, bkpt_accesses, bkpt_addresses, sizes, accesses, addresses) for bkpt_size, bkpt_access, bkpt_addr, size, access, addr in generator: gdb_size = size_to_type(bkpt_size) gdb_access = to_gdb_access(bkpt_access) gdb_execute("set var watchpoint_write = %i" % (1 if has_write(access) else 0)) gdb_execute("set var watchpoint_read = %i" % (1 if has_read(access) else 0)) gdb_execute("set var watchpoint_size = %i" % size) gdb_execute("set var write_address = %i" % addr) breakpoint = gdb.Breakpoint("*(%s)0x%x" % (gdb_size, bkpt_addr), gdb.BP_WATCHPOINT, gdb_access) # Run until breakpoint is hit gdb_execute("c&") event = yield (0.1) bkpt_hit = not is_event_signal(event, "SIGINT") # Compare against expected result should_break = should_trigger_break(bkpt_size, bkpt_access, bkpt_addr, size, access, addr) valid = valid_watchpoint(bkpt_size, bkpt_access, bkpt_addr) if valid and bkpt_hit != should_break: fail_count += 1 print("Error - watchpoint problem:") print(" Watchpoint was hit %s" % bkpt_hit) print(" Watchpoint should be hit %s" % should_break) print(" bkpt_size %s, bkpt_access %s, bkpt_address 0x%x, " "size %s, access %s, addr 0x%x" % (bkpt_size, bkpt_access, bkpt_addr, size, access, addr)) print() breakpoint.delete() # TODO,c1728p9 - test reading/writing registers # TODO,c1728p9 - test stepping into interrupts # TODO,c1728p9 - test vector catch # -test hard fault handling # -test reset catch # TODO,c1728p9 - test signals/hard fault if fail_count: print("Test completed with %i errors" % fail_count) else: print("Test completed successfully") except: print("Main Error:") traceback.print_exc() fail_count += 1 finally: test_result["fail_count"] = fail_count test_result_filename = "test_results%d.txt" % testn with open(test_result_filename, "wb") as f: f.write(json.dumps(test_result)) gdb_execute("detach") gdb_execute("quit %i" % fail_count)
def invoke(self, arg, from_tty): "Usage can be obtained via heap -h" if SIZE_SZ == 0: retrieve_sizesz() inferior = get_inferior() if arg.find("-h") != -1: print_title("Heap Dump Help") print("") print_header("Options:") print("\n") print_header("{:<12}".format("-a 0x1234")) print("Specify an arena address") print_header("{:<12}".format("-b")) print("Print compact bin listing (only free chunks)") print_header("{:<12}".format("-c")) print("Print compact arena listing (all chunks)") print_header("{:<12}".format("-l")) print("Print a flat listing of all chunks in an arena") print_header("{:<12}".format("-f [#]")) print("Print all fast bins, or only a single fast bin") print_header("{:<12}".format("-s [#]")) print("Print all small bins, or only a single small bin") return a_found = f_found = s_found = p_fb = p_sb = p_b = p_l = p_c = 0 for item in arg.split(): if a_found == 1: arena_address = int(item, 16) a_found = 0 continue if f_found == 1: f_found = 0 try: fb_number = int(item) except: pass continue if s_found == 1: s_found = 0 try: sb_number = int(item) except: pass continue if item.find("-a") != -1: a_found = 1 if item.find("f") != -1: f_found = 1 fb_number = None p_fb = 1 if item.find("s") != -1: s_found = 1 sb_number = None p_sb = 1 if item.find("b") != -1: p_b = 1 if item.find("l") != -1: p_l = 1 if item.find("c") != -1: p_c = 1 if arg.find("-a") == -1: try: main_arena = gdb.selected_frame().read_var('main_arena') arena_address = main_arena.address except RuntimeError: print_error("No gdb frame is currently selected.") return except ValueError: try: res = gdb.execute('x/x &main_arena', to_string=True) arena_address = int(res.strip().split()[0], 16) except gdb.error: print_error("Debug glibc was not found.") print_error( "Guessing main_arena address via offset from libc.") #find heap by offset from end of libc in /proc libc_end, heap_begin = read_proc_maps(inferior.pid) if SIZE_SZ == 4: #__malloc_initialize_hook + 0x20 #offset seems to be +0x380 on debug glibc, #+0x3a0 otherwise arena_address = libc_end + 0x3a0 elif SIZE_SZ == 8: #offset seems to be +0xe80 on debug glibc, #+0xea0 otherwise arena_address = libc_end + 0xea0 if libc_end == -1: print_error("Invalid address read via /proc") return if arena_address == 0: print_error("Invalid arena address (0)") return ar_ptr = malloc_state(arena_address) if len(arg) == 0: if ar_ptr.next == 0: print_error("No arenas could be correctly guessed.") print_error("Nothing was found at {0:#x}".format( ar_ptr.address)) return print_title("Heap Dump") print_header("\nArena(s) found:\n") try: #arena address obtained via read_var print("\t arena @ {:#x}".format( int(ar_ptr.address.cast( gdb.lookup_type("unsigned long"))))) except: #arena address obtained via -a print("\t arena @ {:#x}".format(int(ar_ptr.address))) if ar_ptr.address != ar_ptr.next: #we have more than one arena curr_arena = malloc_state(ar_ptr.next) while (ar_ptr.address != curr_arena.address): print("\t arena @ {:#x}".format(int(curr_arena.address))) curr_arena = malloc_state(curr_arena.next) if curr_arena.address == 0: print_error("No arenas could be correctly found.") break #breaking infinite loop print("") return try: fb_base = ar_ptr.address.cast(gdb.lookup_type("unsigned long")) + 8 except: fb_base = ar_ptr.address + 8 if SIZE_SZ == 4: try: sb_base = ar_ptr.address.cast( gdb.lookup_type("unsigned long")) + 56 except: sb_base = ar_ptr.address + 56 elif SIZE_SZ == 8: try: sb_base = ar_ptr.address.cast(gdb.lookup_type("unsigned long"))\ + 104 except: sb_base = ar_ptr.address + 104 try: mp_ = gdb.selected_frame().read_var('mp_') mp_address = mp_.address except RuntimeError: print_error("No gdb frame is currently selected.") return except ValueError: try: res = gdb.execute('x/x &mp_', to_string=True) mp_address = int(res.strip().split()[0], 16) except gdb.error: print_error("Debug glibc could not be found.") print_error("Guessing mp_ address via offset from main_arena.") if SIZE_SZ == 4: try: mp_address = ar_ptr.address.cast( gdb.lookup_type("unsigned long")) + 0x460 except: mp_address = ar_ptr.address + 0x460 elif SIZE_SZ == 8: #offset 0x880 untested on 64bit try: mp_address = ar_ptr.address.cast( gdb.lookup_type("unsigned long")) + 0x880 except: mp_address = ar_ptr.address + 0x460 sbrk_base = malloc_par(mp_address).sbrk_base if p_fb: print_fastbins(inferior, fb_base, fb_number) print("") if p_sb: print_smallbins(inferior, sb_base, sb_number) print("") if p_b: print_bins(inferior, fb_base, sb_base) print("") if p_l: print_flat_listing(ar_ptr, sbrk_base) print("") if p_c: print_compact_listing(ar_ptr, sbrk_base) print("")
def lineno_equals(self, source_line=None, lineno=None): if source_line is not None: lineno = test_libcython.source_to_lineno[source_line] frame = gdb.selected_frame() self.assertEqual(libcython.cython_info.lineno(frame), lineno)
def test_c_step(self): self.break_and_run('some_c_function()') gdb.execute('cy step', to_string=True) self.assertEqual(gdb.selected_frame().name(), 'some_c_function')
def invoke(self, argument, from_tty): gdb.write(gdb.selected_frame().find_sal().symtab.fullname() + os.linesep)
def cur_fn(): return gdb.selected_frame().name()
def invoke(self, arg, from_tty): "Specify an optional arena addr: print_bin_layout main_arena=0x12345" if SIZE_SZ == 0: retrieve_sizesz() if len(arg) == 0: print_error("Please specify the free bin to dump") return try: if arg.find("main_arena") == -1: main_arena = gdb.selected_frame().read_var('main_arena') main_arena_address = main_arena.address else: arg = arg.split() for item in arg: if item.find("main_arena") != -1: if len(item) < 12: print_error("Malformed main_arena parameter") return else: main_arena_address = int(item[11:], 16) except RuntimeError: print_error("No frame is currently selected.") return except ValueError: print_error("Debug glibc was not found.") return if main_arena_address == 0: print_error("Invalid main_arena address (0)") return ar_ptr = malloc_state(main_arena_address) mutex_lock(ar_ptr) print_title("Bin Layout") b = bin_at(ar_ptr, int(arg)) p = malloc_chunk(first(malloc_chunk(b, inuse=False)), inuse=False) print_once = True print_str = "" count = 0 while p.address != int(b): if print_once: print_once = False print_str += "--> " print_str += color_value("[bin {}]".format(int(arg))) count += 1 print_str += " <--> " print_str += color_value("{:#x}".format(int(p.address))) count += 1 p = malloc_chunk(first(p), inuse=False) if len(print_str) != 0: print_str += " <--" print(print_str) print("|{}|".format(" " * (len(print_str) - 2 - count * 12))) print("{}".format("-" * (len(print_str) - count * 12))) else: print("Bin {} empty.".format(int(arg))) mutex_unlock(ar_ptr)
def invoke(self, arg, from_tty): "Specify an optional arena addr: print_mstats main_arena=0x12345" if SIZE_SZ == 0: retrieve_sizesz() try: mp = gdb.selected_frame().read_var('mp_') if arg.find("main_arena") == -1: main_arena = gdb.selected_frame().read_var('main_arena') main_arena_address = main_arena.address else: arg = arg.split() for item in arg: if item.find("main_arena") != -1: if len(item) < 12: print_error("Malformed main_arena parameter") return else: main_arena_address = int(item[11:], 16) except RuntimeError: print_error("No frame is currently selected.") return except ValueError: print_error("Debug glibc was not found.") return if main_arena_address == 0: print_error("Invalid main_arena address (0)") return in_use_b = mp['mmapped_mem'] system_b = in_use_b print_title("Malloc Stats") arena = 0 ar_ptr = malloc_state(main_arena_address) while (1): mutex_lock(ar_ptr) # account for top avail = chunksize(malloc_chunk(top(ar_ptr), inuse=True, \ read_data=False)) nblocks = 1 nfastblocks = 0 fastavail = 0 # traverse fastbins for i in range(NFASTBINS): p = fastbin(ar_ptr, i) while p != 0: p = malloc_chunk(p, inuse=False) nfastblocks += 1 fastavail += chunksize(p) p = p.fd avail += fastavail # traverse regular bins for i in range(1, NBINS): b = bin_at(ar_ptr, i) p = malloc_chunk(first(malloc_chunk(b, inuse=False)), inuse=False) while p.address != int(b): nblocks += 1 avail += chunksize(p) p = malloc_chunk(first(p), inuse=False) print_header("Arena {}:\n".format(arena)) print("{:16} = ".format("system bytes"), end='') print_value("{}".format(ar_ptr.max_system_mem), end='\n') print("{:16} = ".format("in use bytes"), end='') print_value("{}".format(ar_ptr.max_system_mem - avail), end='\n') system_b += ar_ptr.max_system_mem in_use_b += (ar_ptr.max_system_mem - avail) mutex_unlock(ar_ptr) if ar_ptr.next == main_arena_address: break else: ar_ptr = malloc_state(ar_ptr.next) arena += 1 print_header("Total (including mmap):\n") print("{:16} = ".format("system bytes"), end='') print_value("{}".format(system_b), end='\n') print("{:16} = ".format("in use bytes"), end='') print_value("{}".format(in_use_b), end='\n') print("{:16} = ".format("max system bytes"), end='') print_value("{}".format(mp['max_total_mem']), end='\n') print("{:16} = ".format("max mmap regions"), end='') print_value("{}".format(mp['max_n_mmaps']), end='\n') print("{:16} = ".format("max mmap bytes"), end='') print_value("{}".format(mp['max_mmapped_mem']), end='\n')
import sys import gdb import traceback from subprocess import call #ulong_ptr_type = gdb.lookup_type("unsigned long int").pointer() #thread_id_addr = gdb.Value(0x7effec60) #thread_id_ptr = thread_id_addr.cast(ulong_ptr_type) #thread_id_raw = long(thread_id_ptr.dereference()) #thread_id_hex = str(hex(thread_id_raw)).rstrip("L\n") #print thread_id_hex newest_thread_number = 2 gdb.execute("up 9999") ulong_ptr_type = gdb.lookup_type("unsigned long int").pointer() gdb.execute("down 9999") thread_id_addr = gdb.selected_frame().read_var("newthread") thread_id_ptr = thread_id_addr.cast(ulong_ptr_type) gdb.execute("fin") thread_id = long(thread_id_ptr.dereference()) gdb.execute("thread " + str(newest_thread_number)) tfunc = gdb.selected_frame().function().print_name.rstrip() client_threads[thread_id] = (tfunc, newest_thread_number) gdb_threads[newest_thread_number] = (tfunc, thread_id) print("New thread: id == " + str(thread_id) + ", number == " + str(newest_thread_number) + ", tfunc == " + tfunc) if tfunc == "request_thread_function(void*)": print("It works! My time machine works!") else: pass
def context_ghidra(func=None, target=sys.stdout, with_banner=True, width=None, force_show=False): banner = [pwndbg.ui.banner("ghidra decompile", target=target, width=width)] if config_context_ghidra == "never" and not force_show: return [] elif config_context_ghidra == "if-no-source" and not force_show: try: with open(gdb.selected_frame().find_sal().symtab.fullname()) as _: pass except: # a lot can go wrong in search of source code. return [ ] # we don't care what, just that it did not work out well... filename = gdb.current_progspace().filename try: r2 = init_radare2(filename) # LD list supported decompilers (e cmd.pdc=?) # Outputs for example:: pdc\npdg if not "pdg" in r2.cmd("LD").split("\n"): return banner + [ "radare2 plugin r2ghidra-dec must be installed and available from r2" ] except ImportError: # no r2pipe present return banner + [ "r2pipe not available, but required for r2->ghidra-bridge" ] if func is None: try: func = hex(pwndbg.regs[pwndbg.regs.current.pc]) except: func = "main" src = r2.cmdj("pdgj @" + func) source = src.get("code", "") curline = None try: cur = pwndbg.regs[pwndbg.regs.current.pc] except AttributeError: cur = None # If not running there is no current.pc if cur is not None: closest = 0 for off in (a.get("offset", 0) for a in src.get("annotations", [])): if abs(cur - closest) > abs(cur - off): closest = off pos_annotations = sorted([ a for a in src.get("annotations", []) if a.get("offset") == closest ], key=lambda a: a["start"]) if pos_annotations: curline = source.count("\n", 0, pos_annotations[0]["start"]) source = source.split("\n") # Append --> for the current line if possible if curline is not None: line = source[curline] if line.startswith(' '): line = line[4:] source[curline] = '--> ' + line # Join the source for highlighting source = "\n".join(source) if pwndbg.config.syntax_highlight: # highlighting depends on the file extension to guess the language, so try to get one... try: # try to read the source filename from debug information src_filename = gdb.selected_frame().find_sal().symtab.fullname() except: # if non, take the original filename and maybe append .c (just assuming is was c) src_filename = filename + ".c" if os.path.basename(filename).find( ".") < 0 else filename source = H.syntax_highlight(source, src_filename) source = source.split("\n") return banner + source if with_banner else source
def stop(self): connection_id = str(gdb.selected_frame().read_var('connection')) self.plugin.close_connection(connection_id) return False
def print_stackframe(self, frame, index, is_c=False): """ Print a C, Cython or Python stack frame and the line of source code if available. """ # do this to prevent the require_cython_frame decorator from # raising GdbError when calling self.cy.cy_cvalue.invoke() selected_frame = gdb.selected_frame() frame.select() try: source_desc, lineno = self.get_source_desc(frame) except NoFunctionNameInFrameError: print('#%-2d Unknown Frame (compile with -g)' % index) return if not is_c and self.is_python_function(frame): pyframe = libpython.Frame(frame).get_pyop() if pyframe is None or pyframe.is_optimized_out(): # print this python function as a C function return self.print_stackframe(frame, index, is_c=True) func_name = pyframe.co_name func_cname = 'PyEval_EvalFrameEx' func_args = [] elif self.is_cython_function(frame): cyfunc = self.get_cython_function(frame) f = lambda arg: self.cy.cy_cvalue.invoke(arg, frame=frame) func_name = cyfunc.name func_cname = cyfunc.cname func_args = [] # [(arg, f(arg)) for arg in cyfunc.arguments] else: source_desc, lineno = self.get_source_desc(frame) func_name = frame.name() func_cname = func_name func_args = [] try: gdb_value = gdb.parse_and_eval(func_cname) except RuntimeError: func_address = 0 else: func_address = gdb_value.address if not isinstance(func_address, int): # Seriously? Why is the address not an int? if not isinstance(func_address, (str, bytes)): func_address = str(func_address) func_address = int(func_address.split()[0], 0) a = ', '.join('%s=%s' % (name, val) for name, val in func_args) sys.stdout.write('#%-2d 0x%016x in %s(%s)' % (index, func_address, func_name, a)) if source_desc.filename is not None: sys.stdout.write(' at %s:%s' % (source_desc.filename, lineno)) sys.stdout.write('\n') try: sys.stdout.write(' ' + source_desc.get_source(lineno)) except gdb.GdbError: pass selected_frame.select()
def __init__(self, plugin): super().__init__(gdb.selected_frame(), internal=True) self.plugin = plugin
def gdb79_get_register(name): return gdb.selected_frame().read_register(name)
def invoke(self, arg, from_tty): arch = gdb.selected_frame().architecture().name() eip_str = "$eip" if "x86-64" in arch: eip_str = "$rip" eip = int(gdb.parse_and_eval(eip_str)) if eip < 0x10000: eip += 0xffff0000 curr = eip & 0xfffffffc back = curr - 0x40000 step = 4 found = False while curr > back: val = self.ord4(curr) if val == 0x00005a4d: # PE image pe_image_base = curr pe00_base = pe_image_base + self.ord4(curr + 0x3c) pe_sig = self.ord4(pe00_base) if pe_sig == 0x4550: found = True elif val == 0x014C5A56: # TE image found = True if found == True: break curr -= step if not found: print("ERROR: could not locate PE/TE header !") return if val == 0x00005a4d: pe_coff_hdr = pe00_base + 4 pe_num_sections = self.ord2(pe_coff_hdr + 2) pe_opt_hdr_base = pe_coff_hdr + 0x14 pe_opt_hdr_size = self.ord2(pe_coff_hdr + 0x10) if pe_opt_hdr_size == 0: print("ERROR: optional header size is zero.") return pe_sig = self.ord2(pe_opt_hdr_base) if (pe_sig != 0x010B) and (pe_sig != 0x020B): print("ERROR: bad magic number") return code_off = self.ord4(pe_opt_hdr_base + 0x14) pe_num_rva_offs = 0 pe_data_dir_offs = 0 if pe_sig == 0x010b: # PE32 executable pe_num_rva_offs = 0x5c pe_data_dir_offs = 0x60 else: # PE32+ executable pe_num_rva_offs = 0x6c pe_data_dir_offs = 0x70 num_rva = self.ord4(pe_opt_hdr_base + pe_num_rva_offs) if self.ord4(pe_opt_hdr_base + pe_num_rva_offs) < 7: print("ERROR: number of RVA < 7") return pe_debug_dir_entry_offs = self.ord4(pe_opt_hdr_base + pe_data_dir_offs + 6 * 8) else: te_header = curr print('TE image base at 0x%08X' % te_header) te_header_size = 0xa * 0x4 stripped_size = self.ord2(te_header + 6) code_off = self.ord4(te_header + 0xc) pe_start_of_file = te_header + te_header_size - stripped_size pe_image_base = pe_start_of_file pe_debug_dir_entry_offs = self.ord4(te_header + (0x8 * 0x4)) if self.ord2(pe_image_base + pe_debug_dir_entry_offs + 0xc) != 0x2: print('ERROR: no debug info !') return val = self.ord4(pe_image_base + pe_debug_dir_entry_offs + 0x14) if val: baseptr = pe_image_base + val else: baseptr = pe_image_base + self.ord4(pe_image_base + pe_debug_dir_entry_offs + 0x18) sig = self.ord4(baseptr) if sig == 0x3031424e: baseptr += 0x10 print("NB10 signature at 0x%X" % baseptr) elif sig == 0x53445352: baseptr += 0x18 print("RSDS signature at 0x%X" % baseptr) else: print("Unknown debug signature") return text_base = pe_image_base + code_off dbgpath = self.gets(baseptr)[0:-3] + 'debug' print("Loading symbol %s at 0x%x" % (dbgpath, pe_image_base)) gdb.execute("symbol-file") gdb.execute("add-symbol-file %s 0x%08x" % (dbgpath, text_base))
def __enter__(self): self.oldFrame = gdb.selected_frame() self.frame.select() return self
def _get_frame(self, gdbFrame=None): return gdbFrame if gdbFrame is not None else gdb.selected_frame()
def get_current_hightlight_source(): sal = gdb.selected_frame().find_sal() filename = sal.symtab.fullname() codes = get_hightlight_source(filename) return codes
def next(): # dbug_print("# before next : {} {}".format(cur_fn(), _line()), file=log) execute("next") # dbug_print("# after next : {} {}".format(cur_fn(), _line()), file=log) def step(): # dbug_print("# before step : {} {}".format(cur_fn(), _line()), file=log) execute("step") # dbug_print("# after step : {} {}".format(cur_fn(), _line()), file=log) # print("ENTER : ", end='', file=log) # print(cur_fn(), file=log) execute("set pagination off") break_fn = gdb.selected_frame().function() outfile = input("\nEnter desired output file name (leave blank for default): ") if not outfile: outfile = "linetrace_{}_{}.log".format( break_fn.name.split('(')[0], int(time())) log = open(outfile, 'w') print("\nLogging to {}\n".format(outfile)) # Read list of functions and prepare a regex to match any of them with open("stack.txt") as f: break_fn_list = [line.rstrip() for line in f] break_fn_regex = "(" + "|".join(break_fn_list) + ")\("
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 get_selected_frame(cls): _gdbframe = gdb.selected_frame() if _gdbframe: return Frame(_gdbframe) return None
outputs = [ 'meTwo', '""', '"meTwo"', '{meOne, meThree}', 'MyOtherEnum(1)', '5', 'array = {1, 2, 3, 4, 5}', 'seq(0, 0)', 'seq(0, 10)', 'array = {"one", "two"}', 'seq(3, 3) = {1, 2, 3}', 'seq(3, 3) = {"one", "two", "three"}', 'Table(3, 64) = {[4] = "four", [5] = "five", [6] = "six"}', 'Table(3, 8) = {["two"] = 2, ["three"] = 3, ["one"] = 1}', '{a = 1, b = "some string"}' ] for i, expected in enumerate(outputs): gdb.write(f"{i+1}) expecting: {expected}: ", gdb.STDLOG) gdb.flush() functionSymbol = gdb.selected_frame().block().function assert functionSymbol.line == 41, str(functionSymbol.line) if i == 6: # myArray is passed as pointer to int to myDebug. I look up myArray up in the stack gdb.execute("up") raw = gdb.parse_and_eval("myArray") elif i == 9: # myOtherArray is passed as pointer to int to myDebug. I look up myOtherArray up in the stack gdb.execute("up") raw = gdb.parse_and_eval("myOtherArray") else: raw = gdb.parse_and_eval("arg") output = str(raw)
def read_global_var(symname): return gdb.selected_frame().read_var(symname)
def context_code(): try: # Compute the closest pc and line number symtab = gdb.selected_frame().find_sal().symtab linetable = symtab.linetable() closest_pc = -1 closest_line = -1 for line in linetable: real_address = ctypes.c_uint64(line.pc).value # print("line is %d, address is %s" % (line.line, hex(real_address))) if closest_pc < real_address <= pwndbg.regs.pc: closest_line = line.line closest_pc = real_address if closest_line < 0: return [] # Get the full source code filename = symtab.fullname() source = get_highlight_source(filename) # If it starts on line 1, it's not really using the # correct source code. if not source or closest_line <= 1: return [] n = int(source_code_lines) # Compute the line range start = max(closest_line - 1 - n // 2, 0) end = min(closest_line - 1 + n // 2 + 1, len(source)) num_width = len(str(end)) # split the code source = source[start:end] # Compute the prefix_sign length prefix_sign = pwndbg.config.code_prefix prefix_width = len(prefix_sign) # Format the output formatted_source = [] for line_number, code in enumerate(source, start=start + 1): fmt = ' {prefix_sign:{prefix_width}} {line_number:>{num_width}} {code}' if pwndbg.config.highlight_source and line_number == closest_line: fmt = C.highlight(fmt) line = fmt.format(prefix_sign=C.prefix(prefix_sign) if line_number == closest_line else '', prefix_width=prefix_width, line_number=line_number, num_width=num_width, code=code) formatted_source.append(line) banner = [pwndbg.ui.banner("Source (code)"), 'In file: %s' % filename] banner.extend(formatted_source) return banner except: pass if not pwndbg.ida.available(): return [] # May be None when decompilation failed or user loaded wrong binary in IDA n = int(int(int(source_code_lines) / 2)) # int twice to make it a real int instead of inthook code = pwndbg.ida.decompile_context(pwndbg.regs.pc, n) if code: return [pwndbg.ui.banner("Hexrays pseudocode")] + code.splitlines() else: return []
def symval(self, s): return s.value(gdb.selected_frame()) if s.needs_frame else s.value() def value(self):