def invoke(self, args, from_tty): ms = glibc_arenas.get_ms() chunks_by_size = {} num_chunks = 0 total_size = 0 try: for chunk in ms.iter_chunks(): if not chunk.is_inuse(): continue size = int(chunk.chunksize()) num_chunks += 1 total_size += size if size in chunks_by_size: chunks_by_size[size] += 1 else: chunks_by_size[size] = 1 except KeyboardInterrupt: pass # FIXME t = Table(['Chunk size', 'Num chunks', 'Allocated size']) for size in sorted(chunks_by_size.keys(), lambda s1, s2: chunks_by_size[s2] * s2 - chunks_by_size[s1] * s1): t.add_row([fmt_size(size), chunks_by_size[size], fmt_size(chunks_by_size[size] * size)]) t.add_row(['TOTALS', num_chunks, fmt_size(total_size)]) t.write(sys.stdout) print()
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 invoke(self, args, from_tty): args = args.split() filename = args[0] start = int(args[1]) end = int(args[2]) step = int(args[3]) from heap.visualize import gen_mem_usage_image ms = glibc_arenas.get_ms() im = gen_mem_usage_image(ms.iter_chunks(), start, end, step, 1024) im.save(filename)
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 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 iter_usage(): # Iterate through glibc, and within that, within Python arena blocks, as appropriate from heap.glibc import glibc_arenas ms = glibc_arenas.get_ms() cached_state = CachedInferiorState() from heap.cpython import ArenaDetection as CPythonArenaDetection, PyArenaPtr, ArenaObject try: cpython_arenas = CPythonArenaDetection() cached_state.add_arena_detector(cpython_arenas) except WrongInferiorProcess: pass from heap.pypy import ArenaDetection as PyPyArenaDetection try: pypy_arenas = PyPyArenaDetection() cached_state.add_arena_detector(pypy_arenas) except WrongInferiorProcess: pass for i, chunk in enumerate(ms.iter_mmap_chunks()): mem_ptr = chunk.as_mem() chunksize = chunk.chunksize() arena = cached_state.detect_arena(mem_ptr, chunksize) if arena: for u in arena.iter_usage(): yield u else: yield Usage(int(mem_ptr), chunksize) for chunk in ms.iter_sbrk_chunks(): mem_ptr = chunk.as_mem() chunk_ptr = chunk.as_address() chunksize = chunk.chunksize() if chunk.is_inuse(): arena = cached_state.detect_arena(mem_ptr, chunksize) if arena: for u in arena.iter_usage(): yield u else: yield Usage(int(chunk_ptr), chunksize)
def iter_usage(): # Iterate through glibc, and within that, within Python arena blocks, as appropriate from heap.glibc import glibc_arenas ms = glibc_arenas.get_ms() cached_state = CachedInferiorState() from heap.cpython import ArenaDetection as CPythonArenaDetection, PyArenaPtr, ArenaObject try: cpython_arenas = CPythonArenaDetection() cached_state.add_arena_detector(cpython_arenas) except WrongInferiorProcess: pass from heap.pypy import ArenaDetection as PyPyArenaDetection try: pypy_arenas = PyPyArenaDetection() cached_state.add_arena_detector(pypy_arenas) except WrongInferiorProcess: pass for i, chunk in enumerate(ms.iter_mmap_chunks()): mem_ptr = chunk.as_mem() chunksize = chunk.chunksize() arena = cached_state.detect_arena(mem_ptr, chunksize) if arena: for u in arena.iter_usage(): yield u else: yield Usage(to_int(mem_ptr), chunksize) for chunk in ms.iter_sbrk_chunks(): mem_ptr = chunk.as_mem() chunksize = chunk.chunksize() if chunk.is_inuse(): arena = cached_state.detect_arena(mem_ptr, chunksize) if arena: for u in arena.iter_usage(): yield u else: yield Usage(to_int(mem_ptr), chunksize)
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): 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