def root_documents(): gdb.newest_frame().older().select() # Have gdb.Value live_instances = gdb.parse_and_eval('g_liveInstances') print live_instances document = gdb.lookup_type('WebCore::Document') print document for field in document.fields(): if field.name.find('dump') >= 0: print ' ' + field.name #symbol = gdb.lookup_global_symbol('listLiveInstances') #print symbol dumper = gdb.parse_and_eval('listLiveInstances') print type_code[dumper.type.code] print live_instances begin = live_instances['begin'] print begin print type_code[begin.type.code] print begin.type print begin.dynamic_type # result = begin () print '---' print live_instances['m_impl'] print live_instances['m_impl']['m_table'] print live_instances.type for field in live_instances.type.fields(): print field.name for field2 in live_instances[field.name].type.fields(): print ' ' + field2.name print live_instances.address
def invoke(self, arg='', from_tty=False, sig=0): gdb.newest_frame().select() regs = [0] * 19 # parse_and_eval seems to be the only way to access target registers for i in range(16): regs[i] = int(gdb.parse_and_eval("(unsigned long)$r%d" % i)) regs[16] = int(gdb.parse_and_eval("(unsigned long)$xpsr")) # Don't know how to include other registers in core dump prstatus = ARM_prstatus() prstatus.pr_cursig = sig # Is it possible to include a target register description? notes = note_desc("CORE", 1, prstatus.dumps() + struct.pack("<19L", *regs)) inf = gdb.selected_inferior() # How do we query the memory map from GDB? # TODO: Use 'info mem' ram = inf.read_memory(0x20000000, 128*1024) ccmram = inf.read_memory(0x10000000, 64*1024) scs = inf.read_memory(0xE000ED00, 0x40) core = CoreFile() core.set_type(Elf32_Ehdr.ET_CORE) core.set_machine(0x28) #ARM core.add_program(Elf32_Phdr.PT_NOTE, 0, notes) core.add_program(Elf32_Phdr.PT_LOAD, 0x10000000, ccmram) core.add_program(Elf32_Phdr.PT_LOAD, 0x20000000, ram) core.add_program(Elf32_Phdr.PT_LOAD, 0xE000ED00, scs) fn = arg if arg else gcore_file_name.value fn += "-" + time.strftime("%y%m%d-%H%M%S") core.dump(open(fn, "w")) print "(core dumped to %r)" % fn
def get_cpu_regs(): """Return the current state of general purpose registers""" gdb.newest_frame().select() regs = [0] * 19 for i in range(16): regs[i] = int(gdb.parse_and_eval("(unsigned long)$r%d" % i)) regs[16] = int(gdb.parse_and_eval("(unsigned long)$xpsr")) return regs
def __init__(self, f=None): if f is None: self._frame = Frame(gdb.newest_frame()) elif isinstance(f, gdb.Frame): self._frame = Frame(f) elif isinstance(f, str): self._frame = Frame.knownFrames.get(f, Frame(gdb.newest_frame())) else: print("Frame param of invalid type!") raise ValueError("frame param of invalid type: " + str(type(f)))
def getVariableValue(name): frame = gdb.newest_frame() if not frame.is_valid(): print("frame not valid") return try: frame = gdb.newest_frame() value = frame.read_var(name) return value except Exception as e: print(e)
def invoke (self, arg, from_tty): i = 0 count = 0 filter = True mode = MODE_NORMAL fancyDetails = True for word in arg.split (" "): if word == '': continue elif word == 'raw': filter = False elif word == 'full': mode = MODE_FULL elif word == 'terse': mode = MODE_TERSE fancyDetails = False elif word == 'paste': mode = MODE_PASTE fancyDetails = False else: count = int (word) # FIXME: provide option to start at selected frame # However, should still number as if starting from newest context = ContextHelper(fancyDetails=fancyDetails) frames = [] iterFrames = None if filter: iterFrames = gdb.frames.execute_frame_filters(gdb.newest_frame(), 0, -1) if not iterFrames: iterFrames = FrameIterator(gdb.newest_frame()) # Now wrap in an iterator that numbers the frames. iterFrames = zip(itertools.count (0), iterFrames) for iFrame, gdbFrameDecorator in iterFrames: gdbFrame = gdbFrameDecorator.inferior_frame() frames.append(ColorFrameWrapper(gdbFrame, context, iFrame)) context.process() # Extract sub-range user wants. iterFrames = zip(itertools.count (0), iter(frames)) if count < 0: iterFrames = self.final_n (iterFrames, count) elif count > 0: iterFrames = itertools.islice (iterFrames, 0, count) # zero it... pout.i(-100) for pair in iterFrames: pair[1].describe (pair[0], mode)
def get_stacktrace(): def get_pc_line(frame): info = ' 0x%016x' % frame.pc() if frame.name(): frame_name = frame.name() try: # try to compute the offset relative to the current function value = gdb.parse_and_eval(frame.name()).address # it can be None even if it is part of the "stack" (C++) if value: func_start = value offset = frame.pc() - func_start frame_name += '+' + str(offset) except gdb.error: pass # e.g., @plt info += ' in {0} ()'.format(frame_name) sal = frame.find_sal() if sal.symtab: file_name = sal.symtab.filename file_line = str(sal.line) info += ' at {0}:{1}'.format(file_name, file_line) return info frame_id = 0 ret = [] frame = gdb.newest_frame() while frame: info = get_pc_line(frame) ret.append( '#{0} {1}'.format(frame_id, info) ) frame_id += 1 frame = frame.older() return str('\n'.join(ret))
def do_unwinder_test(): # The unwinder is disabled by default for the moment. Turn it on to check # that the unwinder works as expected. import gdb gdb.execute("enable unwinder .* SpiderMonkey") run_fragment('unwind.simple', 'Something') first = True # The unwinder is a bit flaky still but should at least be able to # recognize one set of entry and exit frames. This also tests to # make sure we didn't end up solely in the interpreter. found_entry = False found_exit = False found_main = False frames = list(gdb.frames.execute_frame_filters(gdb.newest_frame(), 0, -1)) for frame in frames: print("examining " + frame.function()) if first: assert_eq(frame.function().startswith("Something"), True) first = False elif frame.function() == "<<JitFrame_Exit>>": found_exit = True elif frame.function() == "<<JitFrame_Entry>>": found_entry = True elif frame.function() == "main": found_main = True # Had to have found a frame. assert_eq(first, False) # Had to have found main. assert_eq(found_main, True) # Had to have found the entry and exit frames. assert_eq(found_exit, True) assert_eq(found_entry, True)
def _map_symbols_on_current_thread(self, mapped_files): """Updates the symbols for the current thread using files from mapped_files. """ frame = gdb.newest_frame() while frame and frame.is_valid(): if frame.name() is None: m = self._find_mapping_for_address(mapped_files, frame.pc()) if m is not None and self._try_to_map(m): # Force gdb to recompute its frames. _gdb_execute("info threads") frame = gdb.newest_frame() assert frame.is_valid() if frame.older() is not None and frame.older().is_valid() and frame.older().pc() != frame.pc(): frame = frame.older() else: frame = None
def invoke(self, arg, from_tty): argv = gdb.string_to_argv(arg) state.restore() #gdb.execute("thread 15", False, True) #cur_os_thread = gdb.selected_thread().num frame = gdb.newest_frame() handle_attach = False count = 0 while True: function = frame.function() if function and function.name == "hpx::util::command_line_handling::handle_attach_debugger()": handle_attach = True break frame = frame.older() if not frame or count > 5: break count = count + 1 if handle_attach: frame.select() gdb.execute("set var i = 1", True) #gdb.execute("thread %d" % cur_os_thread, False, True) if len(argv) == 0: print "Continuing..." gdb.execute("continue") else: if argv[0] != "hook": print "wrong argument ..."
def update(): m = sys.modules[__name__] # GDB 7.7 (Ubuntu Trusty) does not like selected_frame() when EBP/RBP # is not mapped / pounts to an invalid address. # # As a work-around for Trusty users, handle the exception and bail. # This may lead to inaccurate results, but there's not much to be done. try: m.current = fix_arch(gdb.newest_frame().architecture().name()) except Exception: return 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 get_current_frames(): frames = [] current_frame = gdb.newest_frame() while current_frame: if current_frame.name(): frames.append( Frame( name=current_frame.name(), \ variables=get_frame_variables(current_frame, current_frame.block() ) ) ) current_frame = current_frame.older() #Set breakpoint on all functions called in main and not main #because an exception is thrown if I set finish breakpoint on main.. I think #Investigate further. newest_frame = gdb.newest_frame() if newest_frame.name() != "main" and CustomFinishBreakpoint.frame_has_finish_bp(newest_frame): CustomFinishBreakpoint(current_frame) #set breakpoint on current frame return frames
def invoke (self, args, from_tty): argv = gdb.string_to_argv(args) newestFrame = gdb.newest_frame() print ("the newest frame is : " + newestFrame.name()) architecture = newestFrame.architecture() print ("this architecture is : " + architecture.name())
def __init__(self, gdbframe=None): if (gdbframe == None): gdbframe = gdb.newest_frame() self._frames = [] while (None != gdbframe): self._frames.append(weenix.stack.Frame(gdbframe)) gdbframe = gdbframe.older()
def callstack_depth(): depth = 1 frame = gdb.newest_frame() while frame is not None: frame = frame.older() depth += 1 return depth
def __init__(self, tpe): self.tpe = tpe self.lines = [] self.shared_ptr_address_str = None self.shared_ptr_function_str = None frame = gdb.newest_frame() while frame is not None: function_str = str(frame.function()) sal = frame.find_sal() if sal.symtab is None: location_str = "???" else: filename = sal.symtab.filename line = sal.line location_str = filename + ":" + str(line) self.lines.append(function_str + " at " + location_str) if self.shared_ptr_address_str is None: if Backtrace.SHARED_PTR_REGEX.match(function_str): self.shared_ptr_address_str = str(frame.read_var("this")) self.shared_ptr_function_str = function_str frame = frame.older() if self.shared_ptr_address_str is None: raise RuntimeError( "Cannot derive shared_ptr instance from backtrace\n" + str(self))
def dump_all_vars(skip_libc_symbols=True): # gdb calls the source of its debug info an 'objfile' # libc_objfile_name. e.g. '/usr/lib/debug/lib64/libc-2.16.so.debug' libc_objfile_name_pattern = r'libc.*\.so' frame = gdb.newest_frame() while frame: symtab = frame.find_sal().symtab if symtab is not None: objfile_name = symtab.objfile.filename else: objfile_name = '' logging.debug('F: %s, %s' % (frame, objfile_name)) if skip_libc_symbols and re.match(r'libc.*\.so', os.path.basename(objfile_name)): return try: block = frame.block() except RuntimeError: block = None while block: logging.debug('B: %s, %s' % (block, block.function)) for symbol in block: try: value = frame.read_var(symbol, block) except gdb.error: # typedefs etc don't have a value pass else: sys.stdout.write('%s: %s\n' % (symbol, value)) block = block.superblock frame = frame.newer()
def get_fragment_instances(): # Walk the threadlist to find fragment instance ids. Assumes IMPALA-6416, so # this will not work with releases older than Impala 2.12. It may be possible # to search for FragmentInstanceState::Exec() in the older releases to get # to the FInstIDs. Returns a dictionary of FInstID->[gdb thread ID]. # Note that multiple threads might be doing tasks for the same FInstID. fragment_instances = defaultdict(list) for thread in gdb.selected_inferior().threads(): thread.switch() f = gdb.newest_frame() while f: # Skip unresolved frame if gdb.Frame.name(f) is None: f = gdb.Frame.older(f) continue if 'impala::Thread::SuperviseThread' in gdb.Frame.name(f): gdb.Frame.select(f) block = gdb.Frame.block(f) gdb.lookup_symbol('thread_debug_info', block) tdi = f.read_var('thread_debug_info') # No valid thread_debug_info if not tdi: break hi = long(tdi['instance_id_']['hi']) lo = long(tdi['instance_id_']['lo']) fi = "%lx:%lx" % (hi, lo) if fi != "0:0": fragment_instances[fi.strip('"')].append(thread.num) break f = gdb.Frame.older(f) return fragment_instances
def to_string(self): if self.nti: arg0 = self.val arg1 = self.nti.value(gdb.newest_frame()) return reprEnum(arg0, arg1) else: return self.typeNimName + "(" + str(int(self.val)) + ")"
def invoke (self, arg, from_tty): thread = gdb.selected_thread() if thread == None: print 'No thread selected.' return for thread in gdb.inferiors(): frame = gdb.newest_frame() while frame: # if that matches our regexp, select that. try: match = re.match(arg, frame.name(), flags=re.IGNORECASE) except Exception, e: print "Error: invalid regex: %s" % str(e) return if match: sal = frame.find_sal() print "Found: %s, thread %s, file %s:%s, in function %s" % (frame.name(), thread.num,sal.symtab.filename, sal.line, frame.function()) frame.select() return frame = frame.older() if not frame: return
def invoke(self, num): num = int(num) if not -1 <= num <= 6: raise gdb.GdbError("Invalid syscall argument index") arch = gdb.newest_frame().architecture().name() if arch not in SYSCALL_REGS: raise gdb.GdbError("Unimplemented syscallarg for {}".format(arch)) return gdb.parse_and_eval('$' + SYSCALL_REGS[arch][num])
def _slab_alloc_callback(self, args): addr = args["addr"] stack = weenix.stack.Stack(gdb.newest_frame().older()) allocator = weenix.kmem.SlabAllocator(gdb.Value(string.atol(args["allocator"], 16)).cast(gdb.lookup_type("void").pointer())) self._slab_allocated[addr] = SlabAllocation(addr, stack, allocator, not self._initialized) if (self._initialized): self._slab_alloc_count += 1 return False
def _page_alloc_callback(self, args): addr = args["addr"] stack = weenix.stack.Stack(gdb.newest_frame().older()) slabdata = stack.contains("_slab_allocator_grow") self._page_allocated[addr] = PageAllocation(addr, stack, string.atoi(args["npages"]), slabdata, not self._initialized) if (self._initialized and not slabdata): self._page_alloc_count += 1 return False
def _page_free_callback(self, args): if (not args["addr"] in self._page_allocated): self._page_invalid_free += 1 print("Invalid free of address " + args["addr"] + ":") print(weenix.stack.Stack(gdb.newest_frame().older())) elif (self._page_allocated[args["addr"]].npages != string.atoi(args["npages"])): self._page_invalid_free += 1 print("Address " + args["addr"] + " allocated for " + str(self._page_allocated[args["addr"]].npages) + " pages:") print(self._page_allocated[args["addr"]].stack) print("but freed with " + args["npages"] + " pages:") print(weenix.stack.Stack(gdb.newest_frame().older())) del(self._page_allocated[args["addr"]]) else: if (not self._page_allocated[args["addr"]].initialization and not self._page_allocated[args["addr"]].slabdata): self._page_free_count += 1 del(self._page_allocated[args["addr"]]) return False
def newest_first_order(self, args, from_tty): frame = gdb.newest_frame() index = 0 while frame: frame.select() self.print_stackframe(frame, index) index += 1 frame = frame.older()
def get_call_chain(): function_names = [] frame = gdb.newest_frame() while frame is not None: function_names.append(frame.name()) frame = frame.older() return tuple(function_names)
def is_target_arch(arch): if hasattr(gdb.Frame, 'architecture'): return arch in gdb.newest_frame().architecture().name() else: global target_arch if target_arch is None: target_arch = gdb.execute("show architecture", to_string=True) return arch in target_arch
def load(self, cpu_thread): self.cpu_thread = cpu_thread self.id = cpu_thread.num - 1 cur = gdb.selected_thread() try: self.cpu_thread.switch() old = gdb.selected_frame() try: gdb.newest_frame().select() self.rsp = ulong(gdb.parse_and_eval('$rsp')) self.rbp = ulong(gdb.parse_and_eval('$rbp')) self.rip = ulong(gdb.parse_and_eval('$rip')) finally: old.select() finally: cur.switch() g_cpus = gdb.parse_and_eval('sched::cpus._M_impl._M_start') self.obj = g_cpus + self.id
def invoke(self, args, from_tty): args = args.split() args = self.parser.parse_args(args=args) fullname = args.fullname try: frm = gdb.newest_frame() except Exception, e: return
def invoke(self, args, from_tty): _args = args.split(None, 1) num = int(_args[0]) if not -1 <= num <= 6: raise gdb.GdbError("Invalid syscall argument index") arch = gdb.newest_frame().architecture().name() if arch not in SYSCALL_REGS: raise gdb.GdbError("Unimplemented syscallarg for {}".format(arch)) gdb.execute('set ${} = {}'.format(SYSCALL_REGS[arch][num], _args[1]))
def find_frame(function_name_pattern): """Find frame.""" frame = gdb.newest_frame() while frame: block = None try: block = frame.block() except RuntimeError as err: if err.args[0] != "Cannot locate block for frame.": raise block = find_func_block(block) if block and re.match(function_name_pattern, block.function.name): return frame try: frame = frame.older() except gdb.error as err: print("Ignoring GDB error '%s' in find_frame" % str(err)) break return None
def __init__(self, gdb_thread, skip_frames, frame_limit, ignore_pc, show_source): if not gdb_thread.is_valid(): raise RuntimeError("Invalid thread object") self.gdb_thread_id = gdb_thread.num (self.pid, self.lwpid, self.tid) = gdb_thread.ptid # Preserve previous selected thread (may be None) orig_thread = gdb.selected_thread() try: # Switch to current thread gdb_thread.switch() # Get the backtrace in its entirety self.frames = self.accumulate_backtrace(gdb.newest_frame(), skip_frames, frame_limit, ignore_pc, show_source) finally: if orig_thread: orig_thread.switch()
def stop(self): self.count += 1 frame = gdb.newest_frame() block = frame.block() sym_and_line = frame.find_sal() framename = frame.name() filename = sym_and_line.symtab.filename line = sym_and_line.line # show tracepoint info print("{0} @ {1}:{2}".format(framename, filename, line)) # show args and vars for s in block: if not s.is_argument and not s.is_variable: continue typ = s.type val = s.value(frame) size = typ.sizeof name = s.name print("\t{0}({1}: {2}) [{3}]".format(name, typ, val, size)) # do not stop at tracepoint return False
def print_best_frame(self, tid): frame = gdb.newest_frame() i = 0 while not frame is None: pc = frame.pc() solib = gdb.solib_name(pc) #if pc >= 0x400000 and pc <= 0x42b000: if solib is None: sal = frame.find_sal() symtab = sal.symtab func = frame.function() print("{: <4} {:<3} {:<30} {}:{}".format( tid, i, color(COL_YELLOW, func) + "()", symtab.filename, color(COL_GREEN, sal.line), )) break frame = frame.older() i+=1
def _process_thread_stack(arg, stacks, thread): """Process the thread stack.""" thread_info = {} # thread dict to hold per thread data thread_info['pthread'] = get_thread_id() thread_info['gdb_thread_num'] = thread.num thread_info['lwpid'] = thread.ptid[1] thread_info['name'] = get_current_thread_name() if sys.platform.startswith("linux"): header_format = "Thread {gdb_thread_num}: {name} (Thread 0x{pthread:x} (LWP {lwpid}))" elif sys.platform.startswith("sunos"): (_, _, thread_tid) = thread.ptid if thread_tid != 0 and thread_info['lwpid'] != 0: header_format = "Thread {gdb_thread_num}: {name} (Thread {pthread} (LWP {lwpid}))" elif thread_info['lwpid'] != 0: header_format = "Thread {gdb_thread_num}: {name} (LWP {lwpid})" else: header_format = "Thread {gdb_thread_num}: {name} (Thread {pthread})" else: raise ValueError("Unsupported platform: {}".format(sys.platform)) thread_info['header'] = header_format.format(**thread_info) addrs = [] # list of return addresses from frames frame = gdb.newest_frame() while frame: addrs.append(frame.pc()) try: frame = frame.older() except gdb.error as err: print("{} {}".format(thread_info['header'], err)) break addrs_tuple = tuple(addrs) # tuples are hashable, lists aren't. unique = stacks.setdefault(addrs_tuple, {'threads': []}) unique['threads'].append(thread_info) if 'output' not in unique: try: unique['output'] = gdb.execute(arg, to_string=True).rstrip() except gdb.error as err: print("{} {}".format(thread_info['header'], err))
def get(self, expression, way=None): # print("get()") # print("expression = '%s'" % (expression,) ) # print("way = '%s'" % (way,) ) if (expression[-2] == "/"): way = expression[-1] expression = expression[:-2] if (way is None): way = "v" ret = None if (expression == "$ret"): return None if (way == "x"): #gdb.execute => gdb.Value ret = gdb.execute(expression, False, True) elif (way == "X"): #gdb.execute => gdb parse_and_eval($) gdb.execute(expression, False, True) ret = gdb.parse_and_eval("$") elif (way == "E"): #python.run() => python result ex = expression if (ex.find("$(") != -1): ex = ex.replace("$(", "gdb.parse_and_eval(") ret = eval(ex, globals()) elif (way == "v"): # frame.value() => gdb.value frame = gdb.newest_frame( ) # maybe get the frame from the breakpoint object? # print("frame = '%s'" % (frame,) ) ret = frame.read_var(expression) elif (way == "p"): # gdb.parse-and_eval() => gdb.value ret = gdb.parse_and_eval(expression) else: raise Exception("Unknown type to get result: %s" % way) return ret
def update(): m = sys.modules[__name__] # GDB 7.7 (Ubuntu Trusty) does not like selected_frame() when EBP/RBP # is not mapped / pounts to an invalid address. # # As a work-around for Trusty users, handle the exception and bail. # This may lead to inaccurate results, but there's not much to be done. try: m.current = fix_arch(gdb.newest_frame().architecture().name()) except Exception: return m.ptrsize = pwndbg.typeinfo.ptrsize m.ptrmask = (1 << 8 * pwndbg.typeinfo.ptrsize) - 1 if 'little' in gdb.execute('show endian', to_string=True).lower(): 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)) # Work around Python 2.7.6 struct.pack / unicode incompatibility # See https://github.com/pwndbg/pwndbg/pull/336 for more information. m.fmt = str(m.fmt) # 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 print_context(): gdb.write("#" * 80 + "\n") gdb.execute("backtrace") gdb.write("-" * 80 + "\n") show_lines(gdb.newest_frame().find_sal()) gdb.write("-" * 80 + "\n") s = gdb.execute("info source", False, True) if (s[s.index(source) + len(source):].startswith('asm')): gdb.execute("info registers") try: gdb.execute("x/10gx $rsp") except: gdb.write("\n") else: gdb.execute("info args") gdb.execute("info locals") gdb.write("-" * 80 + "\n") gdb.write(colorize('col_var', "esecuzione: ") + show_list(gdb.parse_and_eval("esecuzione"), 'puntatore', nmax=1) + "\n") gdb.write(colorize('col_var', "pronti: ") + show_list(gdb.parse_and_eval("pronti"), 'puntatore') + "\n") gdb.execute("semaphore waiting") gdb.write(colorize('col_var', "p_sospesi: ") + show_list(gdb.parse_and_eval("p_sospesi"), 'p_rich') + "\n") gdb.write("-" * 80 + "\n")
def crash_handler(event): """ Handles the event """ reason = event.stop_signal backtrace = [] try: frame = gdb.newest_frame() backtrace = backtracer(frame) except gdb.error: return # testcase is defined as a global by the invoker result = { 'testcase': testcase, 'size': os.path.getsize(testcase), 'reason': reason, 'backtrace': backtrace } f = open('{}.analysis'.format(os.path.basename(testcase)), 'w') f.write(json.dumps(result)) f.close()
def _get_arch(): not_exactly_arch = False if pwndbg.proc.alive: arch = gdb.newest_frame().architecture().name() else: arch = gdb.execute("show architecture", to_string=True).strip() not_exactly_arch = True # Below, we fix the fetched architecture for match in ('x86-64', 'i386', 'aarch64', 'mips', 'powerpc', 'sparc'): if match in arch: return match # Distinguish between Cortex-M and other ARM if 'arm' in arch: return 'armcm' if '-m' in arch else 'arm' if not_exactly_arch: raise RuntimeError("Could not deduce architecture from: %s" % arch) return arch
def _get_arch(): not_exactly_arch = False if pwndbg.proc.alive: arch = gdb.newest_frame().architecture().name() else: arch = gdb.execute("show architecture", to_string=True).strip() not_exactly_arch = True # Below, we fix the fetched architecture for match in ("x86-64", "i386", "aarch64", "mips", "powerpc", "sparc"): if match in arch: return match # Distinguish between Cortex-M and other ARM if "arm" in arch: return "armcm" if "-m" in arch else "arm" if not_exactly_arch: raise RuntimeError("Could not deduce architecture from: %s" % arch) return arch
def retaddr(): sp = pwndbg.regs.sp stack = pwndbg.vmmap.find(sp) # Enumerate all return addresses frame = gdb.newest_frame() addresses = [] while frame: addresses.append(frame.pc()) frame = frame.older() # Find all of them on the stack start = stack.vaddr stop = start + stack.memsz while addresses and start < sp < stop: value = pwndbg.memory.u(sp) if value in addresses: index = addresses.index(value) del addresses[:index] print(pwndbg.chain.format(sp)) sp += pwndbg.arch.ptrsize
def stop(self): symbols = EfiSymbols() # Emulator adds SizeOfHeaders so we need file alignment to search symbols.configure_search(0x20) frame = gdb.newest_frame() try: # gdb was looking at spill address, pre spill :( LoadAddress = frame.read_register('rdx') AddSymbolFlag = frame.read_register('rcx') except gdb.error: LoadAddress = frame.read_var('LoadAddress') AddSymbolFlag = frame.read_var('AddSymbolFlag') if AddSymbolFlag == 1: res = symbols.address_to_symbols(LoadAddress) else: res = symbols.unload_symbols(LoadAddress) print(res) # keep running return False
def invoke(arg, from_tty): """ arg is: <start_bbcount> <end_bbcount> <bbcount_interval> E.g. 0 1000 1 means sample every basic block from 1 to 1000. """ with udb.time.auto_reverting(): functions = defaultdict(lambda: 0) args = gdb.string_to_argv(arg) start_bbcount = int(args[0]) end_bbcount = int(args[1]) interval = int(args[2]) with debugger_utils.temporary_parameter("print address", False): for current_bbcount in range(start_bbcount, end_bbcount + 1, interval): udb.time.goto(current_bbcount) frame = gdb.newest_frame() # Create list of functions in the backtrace trace_functions = [] while frame is not None: if frame.name() is not None: trace_functions.append(frame.name()) else: # If no symbol for function use pc trace_functions.append(str(frame.pc())) frame = frame.older() # Concatenate functions in backtrace to create key key = "->".join(reversed(trace_functions)) functions[key] += 1 # Now print what we've found... for function in functions: print("{} {}".format(function, str(functions[function])))
def get_frames_info(self): frames_info = [] selected_frame = gdb.selected_frame() frame = gdb.newest_frame() nframe = 0 while frame: func_name = get_frame_funcname(frame) file_name, file_line = get_frame_fileline(frame) func_args = get_frame_func_args(frame) selected = (frame == selected_frame) and (frame.pc() == selected_frame.pc()) if selected: self.selected_nframe = nframe frames_info.append({ 'nframe': nframe, 'selected': selected, 'func_name': func_name, 'file_name': file_name, 'file_line': file_line, 'func_args': func_args, }) frame = frame.older() nframe += 1 return frames_info
def dmdprof_get_stack(): oldloc = () stack = [] frame = gdb.newest_frame() last_frame = frame while frame: try: block = frame.block() except RuntimeError: block = None while block: if not block.is_global: for symbol in block: if symbol.is_argument: loc = dmdprof_get_loc(symbol.value(frame)) if loc is not None and loc != oldloc: stack.append(loc) oldloc = loc last_frame = frame break # Consider just the first argument with a Loc block = block.superblock frame = frame.older() frame = last_frame while frame: name = frame.name() name = re.sub(r"\(.*", "", name) if name == "Module::accept" or name == "dmd.mars.tryMain": pass elif name == "D main": stack.append((name, -2, -2)) else: stack.append((name, -1, -1)) frame = frame.older() return tuple(stack)
def get_disassembler(pc): if pwndbg.arch.current == 'armcm': extra = (CS_MODE_MCLASS | CS_MODE_THUMB) if (pwndbg.regs.xpsr & (1 << 24)) else CS_MODE_MCLASS elif pwndbg.arch.current in ('arm', 'aarch64'): extra = CS_MODE_THUMB if (pwndbg.regs.cpsr & (1 << 5)) else CS_MODE_ARM elif pwndbg.arch.current == 'sparc': if 'v9' in gdb.newest_frame().architecture().name(): extra = CS_MODE_V9 else: # The ptrsize base modes cause capstone.CsError: Invalid mode (CS_ERR_MODE) extra = 0 elif pwndbg.arch.current == 'i8086': extra = CS_MODE_16 else: extra = None return get_disassembler_cached(pwndbg.arch.current, pwndbg.arch.ptrsize, pwndbg.arch.endian, extra)
def arch(): try: return gdb.newest_frame().architecture().name() except: return None
def __init__(self,arg): gdb.FinishBreakpoint.__init__(self,gdb.newest_frame(),internal=True) self.silent = True self.arg = arg
def describe_current_position(): frame = gdb.newest_frame() func = frame.function() sal = frame.find_sal() line = "%s:%s" % (sal.filename, sal.line) return "%s %s" % (func, line)
class ShorternBacktraceCommand(gdb.Command): '''Show a backtrace without argument info in each frame.''' def __init__(self): super(ShorternBacktraceCommand, self).__init__("bt", gdb.COMMAND_SUPPORT, gdb.COMPLETE_NONE) def invoke(self, arg, from_tty): # Parse arguments. show_source = False num = 0 args = arg.split() for s in args: if s == '-s': show_source = True else: try: num = int(s) except Exception, e: pass # Extract frame info. frames = [] f = gdb.newest_frame() fn = 0 while f is not None: symtab_and_line = gdb.Frame.find_sal(f) frame_name = gdb.Frame.name(f) if frame_name: filename = None if symtab_and_line.symtab: filename = symtab_and_line.symtab.filename outs = ( fn, frame_name, filename if filename else '??', symtab_and_line.line, ) else: outs = (fn, '??', 'unknown', 0) head = '#%-2d %s at %s:%s' % outs codes = None if show_source and frame_name and filename: codes = read_source_code(symtab_and_line.symtab.fullname(), symtab_and_line.line, 10) frames.append((head, codes)) f = gdb.Frame.older(f) fn += 1 # Hold the subset. if num > 0: frames = frames[:num] elif num < 0: frames = frames[len(frames) + num:] # Print the result. for head, codes in frames: print head if codes: for line in codes: print line print
def gdb79_get_register(name): return gdb.newest_frame().read_register(name)
def local_var(name): return gdb.newest_frame().read_var(name)
def invoke(self, args, from_tty): argv = gdb.string_to_argv(args) tp = gdb.lookup_type(argv[0], gdb.newest_frame().block()) for item in tp.items(): print item
def restore_regs(self, values): gdb.newest_frame().select() for reg, value in values.items(): gdb.execute('set $%s = %s' % (reg, value))
def is_in_vm(): frame_name = gdb.newest_frame().name() return frame_name.startswith('lj_BC_')
def __init__(self, thread_data_base): self.base_type = gdb.lookup_type("hpx::threads::thread_data_base") if thread_data_base.type != self.base_type.pointer(): if thread_data_base.type == self.base_type: thread_data_base = thread_data_base.address() else: thread_data_base = thread_data_base.reinterpret_cast( self.base_type.pointer()) self.thread_data = thread_data_base.cast( thread_data_base.dynamic_type).dereference() context_impl = self.thread_data['coroutine_']['m_pimpl']['px'] self.stack_end = context_impl['m_stack'] + context_impl['m_stack_size'] self.stack_start = context_impl['m_stack'] self.m_sp = context_impl['m_sp'] assert thread_data_base == context_impl['m_thread_id'] self.id = thread_data_base #context_impl['m_thread_id'] self.parent_id = self.thread_data['parent_thread_id_'] self.description = self.thread_data['description_'] self.lco_description = self.thread_data['lco_description_'] current_state = self.thread_data['current_state_'] tagged_state_type = current_state.type.template_argument(0) state_enum_type = tagged_state_type.template_argument(0) self.state = current_state['m_storage'] >> 24 self.state = self.state.cast(state_enum_type) current_state_ex = self.thread_data['current_state_ex_'] tagged_state_ex_type = current_state_ex.type.template_argument(0) state_ex_enum_type = tagged_state_ex_type.template_argument(0) self.state_ex = current_state_ex['m_storage'] >> 24 self.state_ex = self.state_ex.cast(state_ex_enum_type) self.size_t = gdb.lookup_type("std::size_t") stack = self.m_sp.reinterpret_cast(self.size_t) self.context = self.Context() self.context.pc = self.deref_stack(stack + (64)) self.context.r15 = self.deref_stack(stack + (8 * 0)) self.context.r14 = self.deref_stack(stack + (8 * 1)) self.context.r13 = self.deref_stack(stack + (8 * 2)) self.context.r12 = self.deref_stack(stack + (8 * 3)) self.context.rdx = self.deref_stack(stack + (8 * 4)) self.context.rax = self.deref_stack(stack + (8 * 5)) self.context.rbx = self.deref_stack(stack + (8 * 6)) self.context.rbp = self.deref_stack(stack + (8 * 7)) self.context.sp = stack + (8 * 8) prev_context = self.context.switch() frame = gdb.newest_frame() function_name = frame.name() p = re.compile("^hpx::util::coroutines.*$") try: while p.match(function_name): if frame.older() is None: break frame = frame.older() function_name = frame.name() if not frame.older() is None: frame = frame.older() function_name = frame.name() line = frame.function().line filename = frame.find_sal().symtab.filename self.pc_string = "0x%x in " % frame.pc( ) + "%s at " % function_name + "%s:" % filename + "%d" % line except: self.pc_string = "0x%x in " % frame.pc() + "<unknown>" self.frame = frame prev_context.switch()
def invoke(self, args, from_tty): argv = parse_argv(args) if len(argv) > 1: print('Usage: walkstk [fp]') return # Set fp = $rbp. fp_type = T('uintptr_t').pointer() fp = gdb.parse_and_eval('$rbp').cast(fp_type) if len(argv) == 1: fp = argv[0].cast(fp_type)[0] # Set rip = $rip. rip_type = T('uintptr_t') rip = gdb.parse_and_eval('$rip').cast(rip_type) if len(argv) == 1: rip = argv[0].cast(fp_type)[1] # Find the starting 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 None: if len(argv) == 0: print('walkstk: Unknown error: corrupt stack?') else: print('walkstk: Invalid frame pointer') return # Get the address and value of `mcg', the global MCGenerator pointer. # For some reason, gdb doesn't have debug info about the symbol, so we # can't use V(); probably this is because we declare it extern "C" (and # maybe also because we do so in a namespace). mcg_type = T('HPHP::jit::MCGenerator').pointer() mcg_addr = gdb.parse_and_eval('&::mcg').cast(mcg_type.pointer()) mcg = mcg_addr.dereference() # Set the bounds of the TC. try: tc_base = mcg['code']['m_base'] tc_end = tc_base + mcg['code']['m_codeSize'] except: # We can't access `mcg' for whatever reason. Assume that the TC is # above the data section, but restricted to low memory. tc_base = mcg_addr.cast(T('uintptr_t')) tc_end = 0x100000000 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) in_tc = rip >= tc_base and rip < tc_end # Try to get the PHP function name from the ActRec at %fp if we're # executing in the TC. if in_tc: ar_type = T('HPHP::ActRec').pointer() try: print( frame.stringify( frame.create_php(idx=i + 1, ar=fp.cast(ar_type), rip=rip))) except gdb.MemoryError: print( frame.stringify( frame.create_native(idx=i + 1, fp=fp, rip=rip, native_frame=native_frame))) # Pop native frames until we hit our caller's rip. else: frames = [] while (native_frame is not None and fp[1] != native_frame.pc()): frames.append( frame.create_native(idx=i, fp='{inline frame}', rip=rip, native_frame=native_frame)) i += 1 native_frame = native_frame.older() if frames: # Associate the frame pointer with the un-inlined frame. frames[-1]['fp'] = str(fp) for f in frames: print(frame.stringify(f))
def invoke(self, argument, from_tty): self.dont_repeat() period = 0.1 args = gdb.string_to_argv(argument) if len(args) > 0: try: period = int(args[0]) except ValueError: print("Invalid number \"%s\"." % args[0]) return def breaking_continue_handler(event): sleep(period) os.kill(gdb.selected_inferior().pid, signal.SIGINT) # call_chain_frequencies = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) top = Function("Top", 2) sleeps = 0 threads = {} for i in range(0, 200): gdb.events.cont.connect(breaking_continue_handler) gdb.execute("continue", to_string=True) gdb.events.cont.disconnect(breaking_continue_handler) for inf in gdb.inferiors(): inum = inf.num for th in inf.threads(): thn = th.num th.switch() # call_chain_frequencies[inum][thn][get_call_chain()] += 1 frame = gdb.newest_frame() while (frame.older() != None): frame = frame.older() # top.inverse_add_frame(frame); # top.add_frame(gdb.newest_frame()) if thn not in threads: threads[thn] = Function(str(thn), 2) threads[thn].inverse_add_frame(frame) sleeps += 1 gdb.write(".") gdb.flush(gdb.STDOUT) print("") for thn, function in sorted(threads.items()): print("") print("Thread: %s" % thn) print("") function.print_percent("", function.get_samples()) # top.print_percent("", top.get_samples()) # print("\nProfiling complete with %d samples." % sleeps) # for inum, i_chain_frequencies in sorted(call_chain_frequencies.iteritems()): # print "" # print "INFERIOR NUM: %s" % inum # print "" # for thn, t_chain_frequencies in sorted (i_chain_frequencies.iteritems()): # print "" # print "THREAD NUM: %s" % thn # print "" # # for call_chain, frequency in sorted(t_chain_frequencies.iteritems(), key=lambda x: x[1], reverse=True): # print("%d\t%s" % (frequency, '->'.join(str(i) for i in call_chain))) # # for call_chain, frequency in sorted(call_chain_frequencies.iteritems(), key=lambda x: x[1], reverse=True): # print("%d\t%s" % (frequency, '->'.join(str(i) for i in call_chain))) pid = gdb.selected_inferior().pid os.kill(pid, signal.SIGSTOP) # Make sure the process does nothing until # it's reattached. gdb.execute("detach", to_string=True) gdb.execute("attach %d" % pid, to_string=True) os.kill(pid, signal.SIGCONT) gdb.execute("continue", to_string=True)
def invoke(self, name, nframes = 1): frame = gdb.newest_frame () while nframes > 0: frame = frame.older () nframes = nframes - 1 return frame.name () == name.string ()