def invoke(self, args, from_tty): args = args.split() if args: only_size = int(args[0]) only_cat = args[1] only_str = args[2] else: only_size = None only_cat = None only_str = None print('Used chunks of memory on heap') print('-----------------------------') ms = glibc_arenas.get_ms() for i, u in enumerate(lazily_get_usage_list()): # if not chunk.is_inuse(): # continue # size = chunk.chunksize() # mem = chunk.as_mem() # u = Usage(mem, size) size = u.size if only_size and size != only_size: continue category = categorize(u, None) if only_cat and category.kind != only_cat: continue hd = hexdump_as_bytes(u.start, min(size, 64)) if only_str and only_str not in hd: continue print ('%6i: %s -> %s %8i bytes %20s |%s' % (i, fmt_addr(u.start), fmt_addr(u.start + size), size, category, hd)) print()
def invoke(self, args, from_tty): print('C++ objects of memory on heap') print('-----------------------------') argv = args.split(' ') from heap.cplusplus import get_class_name ms = glibc_arenas.get_ms() for i, chunk in enumerate(ms.iter_chunks()): if not chunk.is_inuse(): continue mem = chunk.as_mem() size = chunk.chunksize() cpp_class = get_class_name(mem, size) if not cpp_class: continue if args and cpp_class.find(argv[0]) < 0: continue try: objsize = caching_lookup_type(cpp_class).sizeof if (size / objsize >= 2): cpp_class += "[%d]" % (size / objsize) except: objsize = "?" u = Usage(mem, size) #hd = hexdump_as_bytes(mem, 32) print('%6i: %s -> %s %8i bytes %100s | %s bytes/obj' % (i, fmt_addr(mem), fmt_addr(mem + size - 1), size, cpp_class, objsize)) print("\n")
def __str__(self): return ( 'PyArenaPtr([%s->%s], %i pools [%s->%s], excess: %i tracked by %s)' % (fmt_addr(self.as_address()), fmt_addr(self.as_address() + ARENA_SIZE - 1), self.num_pools, fmt_addr(self.initial_pool_addr), fmt_addr(self.initial_pool_addr + (self.num_pools * POOL_SIZE) - 1), self.excess, self.arenaobj))
def invoke(self, args, from_tty): t = Table(columnheadings=('struct arena_object*', '256KB buffer location', 'Free pools')) for arena in ArenaObject.iter_arenas(): t.add_row([fmt_addr(arena.as_address()), fmt_addr(arena.address), '%i / %i ' % (arena.field('nfreepools'), arena.field('ntotalpools')) ]) print 'Objects/obmalloc.c: %i arenas' % len(t.rows) t.write(sys.stdout) print
def invoke(self, args, from_tty): t = Table(columnheadings=('struct arena_object*', '256KB buffer location', 'Free pools')) for arena in ArenaObject.iter_arenas(): t.add_row([fmt_addr(arena.as_address()), fmt_addr(arena.address), '%i / %i ' % (arena.field('nfreepools'), arena.field('ntotalpools')) ]) print('Objects/obmalloc.c: %i arenas' % len(t.rows)) t.write(sys.stdout) print()
def chunk_report(self, title, snapshot, set_of_usage): result = '%s:\n' % title if len(set_of_usage) == 0: result += ' (none)\n' return result for usage in sorted(set_of_usage, key=lambda x: x.start): result += (' %s -> %s %8i bytes %20s |%s\n' % (fmt_addr(usage.start), fmt_addr(usage.start + usage.size-1), usage.size, usage.category, usage.hd)) return result
def __str__(self): return ('PyArenaPtr([%s->%s], %i pools [%s->%s], excess: %i tracked by %s)' % (fmt_addr(self.as_address()), fmt_addr(self.as_address() + ARENA_SIZE - 1), self.num_pools, fmt_addr(self.initial_pool_addr), fmt_addr(self.initial_pool_addr + (self.num_pools * POOL_SIZE) - 1), self.excess, self.arenaobj ) )
def chunk_report(self, title, snapshot, set_of_usage): result = '%s:\n' % title if len(set_of_usage) == 0: result += ' (none)\n' return result for usage in sorted(set_of_usage, lambda u1, u2: cmp(u1.start, u2.start)): result += ( ' %s -> %s %8i bytes %20s |%s\n' % (fmt_addr(usage.start), fmt_addr(usage.start + usage.size - 1), usage.size, usage.category, usage.hd)) return result
def invoke(self, args, from_tty): print('All chunks of memory on heap (both used and free)') print('-------------------------------------------------') ms = glibc_arenas.get_ms() for i, chunk in enumerate(ms.iter_chunks()): size = chunk.chunksize() if chunk.is_inuse(): kind = ' inuse' else: kind = ' free' print('%i: %s -> %s %s: %i bytes (%s)' % (i, fmt_addr(chunk.as_address()), fmt_addr(chunk.as_address() + size - 1), kind, size, chunk)) print()
def invoke(self, args, from_tty): print('Used chunks of memory on heap') print('-----------------------------') ms = glibc_arenas.get_ms() for i, chunk in enumerate(ms.iter_chunks()): if not chunk.is_inuse(): continue size = chunk.chunksize() mem = chunk.as_mem() u = Usage(mem, size) category = categorize(u, None) hd = hexdump_as_bytes(mem, 32) print('%6i: %s -> %s %8i bytes %20s |%s' % (i, fmt_addr(chunk.as_mem()), fmt_addr(chunk.as_mem() + size - 1), size, category, hd)) print()
def do_query(args): from heap import fmt_addr, Table from heap.parser import parse_query if args == '': # if no query supplied, select everything: filter_ = Constant(True) else: filter_ = parse_query(args) if False: print args print filter_ columns = [ Column('Start', lambda u: u.start, fmt_addr), Column('End', lambda u: u.start + u.size - 1, fmt_addr), Column('Domain', lambda u: u.category.domain, None), Column('Kind', lambda u: u.category.kind, None), Column('Detail', lambda u: u.category.detail, None), Column('Hexdump', lambda u: u.hexdump, None), ] t = Table([col.name for col in columns]) for u in Query(filter_): u.ensure_hexdump() u.ensure_category() if u.category: domain = u.category.domain kind = u.category.kind detail = u.category.detail if not detail: detail = '' else: domain = '' kind = '' detail = '' t.add_row([ fmt_addr(u.start), fmt_addr(u.start + u.size - 1), domain, kind, detail, u.hd ]) t.write(sys.stdout) print
def invoke(self, args, from_tty): print('All chunks of memory on heap (both used and free)') print('-------------------------------------------------') ms = glibc_arenas.get_ms() for i, chunk in enumerate(ms.iter_chunks()): size = chunk.chunksize() if chunk.is_inuse(): kind = ' inuse' else: kind = ' free' print ('%i: %s -> %s %s: %i bytes (%s)' % (i, fmt_addr(chunk.as_address()), fmt_addr(chunk.as_address()+size-1), kind, size, chunk)) print()
def invoke(self, args, from_tty): print 'Free chunks of memory on heap' print '-----------------------------' ms = glibc_arenas.get_ms() total_size = 0 for i, chunk in enumerate(ms.iter_free_chunks()): size = chunk.chunksize() total_size += size mem = chunk.as_mem() u = Usage(mem, size) category = categorize(u, None) hd = hexdump_as_bytes(mem, 32) print('%6i: %s -> %s %8i bytes %20s |%s' % (i, fmt_addr(chunk.as_mem()), fmt_addr(chunk.as_mem() + size - 1), size, category, hd)) print "Total size: %s" % total_size
def invoke(self, args, from_tty): print('Used chunks of memory on heap') print('-----------------------------') ms = glibc_arenas.get_ms() for i, chunk in enumerate(ms.iter_chunks()): if not chunk.is_inuse(): continue size = chunk.chunksize() mem = chunk.as_mem() u = Usage(mem, size) category = categorize(u, None) hd = hexdump_as_bytes(mem, 32) print ('%6i: %s -> %s %8i bytes %20s |%s' % (i, fmt_addr(chunk.as_mem()), fmt_addr(chunk.as_mem()+size-1), size, category, hd)) print()
def invoke(self, args, from_tty): print 'Free chunks of memory on heap' print '-----------------------------' ms = glibc_arenas.get_ms() total_size = 0 for i, chunk in enumerate(ms.iter_free_chunks()): size = chunk.chunksize() total_size += size mem = chunk.as_mem() u = Usage(mem, size) category = categorize(u, None) hd = hexdump_as_bytes(mem, 32) print ('%6i: %s -> %s %8i bytes %20s |%s' % (i, fmt_addr(chunk.as_mem()), fmt_addr(chunk.as_mem()+size-1), size, category, hd)) print "Total size: %s" % total_size
def invoke(self, args, from_tty): from heap.glibc import glibc_arenas print('All chunks of memory on heap (both used and free)') print('-------------------------------------------------') ms = glibc_arenas.get_ms() try: for i, chunk in enumerate(ms.iter_chunks()): size = chunk.chunksize() if chunk.is_inuse(): kind = ' inuse' else: kind = ' free' print ('%i: %s -> %s %s: %i bytes (%s)' % (i, fmt_addr(chunk.as_address()), fmt_addr(chunk.as_address()+size-1), kind, size, chunk)) except KeyboardInterrupt: print("...Stopping") return print()
def invoke(self, args, from_tty): print(repr(args)) arg_list = gdb.string_to_argv(args) chars_only = True if len(arg_list) == 2: addr_arg = arg_list[0] chars_only = True if args[1] == '-c' else False else: addr_arg = args if addr_arg.startswith('0x'): addr = int(addr_arg, 16) else: addr = int(addr_arg) # assume that paging will cut in and the user will quit at some point: size = 32 while True: hd = hexdump_as_bytes(addr, size, chars_only=chars_only) print ('%s -> %s %s' % (fmt_addr(addr), fmt_addr(addr + size -1), hd)) addr += size
def invoke(self, args, from_tty): print(repr(args)) arg_list = gdb.string_to_argv(args) chars_only = True if len(arg_list) == 2: addr_arg = arg_list[0] chars_only = True if args[1] == '-c' else False else: addr_arg = args if addr_arg.startswith('0x'): addr = int(addr_arg, 16) else: addr = int(addr_arg) # assume that paging will cut in and the user will quit at some point: size = 32 while True: hd = hexdump_as_bytes(addr, size, chars_only=chars_only) print ('%s -> %s %s' % (fmt_addr(addr), fmt_addr(addr + size -1), hd)) addr += size
def __str__(self): return ('PyPoolPtr([%s->%s: %d blocks of size %i bytes))' % (fmt_addr(self.as_address()), fmt_addr(self.as_address() + POOL_SIZE - 1), self.num_blocks(), self.block_size()))
def invoke(self, args, from_tty): from heap.glibc import glibc_arenas arg_list = gdb.string_to_argv(args) parser = argparse.ArgumentParser(add_help=True, usage="heap search [-a] [-b] <ADDR>") parser.add_argument('addr', metavar='ADDR', type=str, nargs=1, help="Target address") parser.add_argument('-b', dest='before', action="store_true", default=False, help="Show chunk before") parser.add_argument('-a', dest='after', action="store_true", default=False, help="Show chunk after") try: args_dict = parser.parse_args(args=arg_list) except: return addr_arg = args_dict.addr[0] if addr_arg.startswith("0x"): addr = int(addr_arg, 16) else: addr = int(addr_arg) try: print('search heap for address %s' % fmt_addr(addr)) print('-------------------------------------------------') ms = glibc_arenas.get_ms() output_str = "" corruptFlag = False for chunk in ms.iter_chunks(): try: size = chunk.chunksize() except gdb.MemoryError: print("Corrupt chunk found at %s" % fmt_addr(chunk.as_address())) corruptFlag = True continue if addr >= chunk.as_address() and addr < chunk.as_address() + size: if chunk.is_inuse(): kind = 'inuse' else: kind = 'free' output_str += 'BLOCK:\t%s -> %s %s: \n\t%i bytes (%s)\n' % ( fmt_addr(chunk.as_address()), fmt_addr(chunk.as_address()+size-1), kind, size, chunk) if args_dict.after: try: output_str += "NEXT:\t" chunk_after = chunk.next_chunk() start = chunk_after.as_address() output_str += fmt_addr(start) size = chunk_after.chunksize() output_str += " -> %s" % fmt_addr(start + size -1) if chunk_after.is_inuse(): kind = 'inuse' else: kind = 'free' output_str += " %s:\n\t%i bytes" % (kind, size) output_str += " %s\n" % chunk_after except gdb.MemoryError: output_str += " <INVALID>\n" corruptFlag = True continue if corruptFlag: print("WARNING: Heap is corrupted") print(output_str) except KeyboardInterrupt: print("Interrupt") return
def do_query(args): from heap import fmt_addr, Table from heap.parser import parse_query if args == '': # if no query supplied, select everything: filter_ = Constant(True) else: filter_ = parse_query(args) if False: print(args) print(filter_) columns = [Column('Start', lambda u: u.start, fmt_addr), Column('End', lambda u: u.start + u.size - 1, fmt_addr ), Column('Domain', lambda u: u.category.domain, None), Column('Kind', lambda u: u.category.kind, None), Column('Detail', lambda u: u.category.detail, None), Column('Hexdump', lambda u: u.hexdump, None), ] t = Table([col.name for col in columns]) for u in Query(filter_): u.ensure_hexdump() u.ensure_category() if u.category: domain = u.category.domain kind = u.category.kind detail = u.category.detail if not detail: detail = '' else: domain = '' kind = '' detail = '' t.add_row([fmt_addr(u.start), fmt_addr(u.start + u.size - 1), domain, kind, detail, u.hd]) t.write(sys.stdout) print()
def invoke(self, args, from_tty): from heap.glibc import iter_mappings,lookup_symbol from heap import WrappedPointer,caching_lookup_type SIZE_SZ = caching_lookup_type('size_t').sizeof type_size_t = gdb.lookup_type('size_t') type_size_t_ptr = type_size_t.pointer() arg_list = gdb.string_to_argv(args) parser = argparse.ArgumentParser(add_help=True, usage="objdump [-v][-s SIZE] <ADDR>") parser.add_argument('addr', metavar='ADDR', type=str, nargs=1, help="Target address") parser.add_argument('-s', dest='size', default=None, help='Total dump size') parser.add_argument('-v', dest='verbose', action="store_true", default=False, help='Verbose') try: args_dict = parser.parse_args(args=arg_list) except: return addr_arg = args_dict.addr[0] if addr_arg.startswith('0x'): addr = int(addr_arg, 16) else: addr = int(addr_arg) if args_dict.size: if args_dict.size.startswith('0x'): total_size = int(args_dict.size, 16) else: total_size = int(args_dict.size) else: total_size = 10 * SIZE_SZ if args_dict.verbose: print('Searching in the following object ranges') print('-------------------------------------------------') text = [] #list of tuples (start, end, pathname, ...) of a valid memory map #XXX why pid would be 0? for pid in [ o.pid for o in gdb.inferiors() if o.pid !=0 ]: for r in iter_mappings(pid): if args_dict.verbose: print("%s - %s : %s" % (hex(r[0]), hex(r[1]), r[2])) text.append((r[0], r[1], r[2])) print('\nDumping Object at address %s' % fmt_addr(addr)) print('-------------------------------------------------') for a in range(addr, addr + (total_size * SIZE_SZ), SIZE_SZ): ptr = WrappedPointer(gdb.Value(a).cast(type_size_t_ptr)) #dereference first, at the first access denied bail out, dont go further try: val = ptr.dereference() found = False val_int = int(str(val.cast(type_size_t))) #XXX Error occurred in Python command: invalid literal for int() with base 10: '0x418' pathname = "" for t in text: if val_int >= t[0] and val_int < t[1]: found = True pathname = t[2] if found: sym = lookup_symbol(val_int) if sym: out_line = "%s => %s (%s in %s)" % (fmt_addr(ptr.as_address()), fmt_addr(val_int), sym, pathname ) else: out_line = "%s => %s (%s)" % (fmt_addr(ptr.as_address()), fmt_addr(val_int), pathname ) else: out_line = "%s => %s" % (fmt_addr(ptr.as_address()), fmt_addr(val_int) ) #if it's not a symbol, try a string # try just a few chars #if not found: print(out_line) except gdb.MemoryError: print("Error accessing memory at %s" % fmt_addr(ptr.as_address())) return
def __str__(self): return ('PyPoolPtr([%s->%s: %d blocks of size %i bytes))' % (fmt_addr(self.as_address()), fmt_addr(self.as_address() + POOL_SIZE - 1), self.num_blocks(), self.block_size()))