def invoke(self, arg, from_tty): """Inspired by jp's phrack print""" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") arena_addr = self.dbg.format_address(main_arena.address) ar_ptr = malloc_state(arena_addr, debugger=self.dbg, version=self.version) # XXX: add mp_ address guessing via offset without symbols mp_ = self.dbg.read_variable("mp_") mp_address = mp_.address mp = malloc_par(mp_address, debugger=self.dbg, version=self.version) start, end = self.dbg.get_heap_address(mp) sbrk_base = start print_title("compact arena layout") p = malloc_chunk(sbrk_base, inuse=True, read_data=False, debugger=self.dbg) while(1): if p.address == ptm.top(ar_ptr): print("|T|", end="") break if ptm.inuse(p): print("|A|", end="") else: p = malloc_chunk(p.address, inuse=False, debugger=self.dbg) if ((p.fd == ar_ptr.last_remainder) and (p.bk == ar_ptr.last_remainder) and (ar_ptr.last_remainder != 0)): print("|L|", end="") else: print("|%d|" % ptm.bin_index(p.size), end="") p = malloc_chunk(ptm.next_chunk(p), inuse=True, read_data=False, debugger=self.dbg) print("")
def invoke(self, arg, from_tty): """Inspired by jp's phrack print and arena.c""" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") main_arena_address = self.dbg.format_address(main_arena.address) thread_arena = self.dbg.read_variable("thread_arena") if thread_arena is not None: thread_arena_address = self.dbg.format_address(thread_arena) else: thread_arena_address = main_arena_address argv = self.dbg.string_to_argv(arg) if len(argv) == 1: arena_address = int(argv[0], 16) elif len(argv): print_error('Too many arguments') return else: arena_address = thread_arena_address ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # XXX: add mp_ address guessing via offset without symbols mp_ = self.dbg.read_variable("mp_") mp_address = mp_.address mp = malloc_par(mp_address, debugger=self.dbg, version=self.version) if arena_address == main_arena_address: start, _ = self.dbg.get_heap_address(mp) else: # XXX: start offset start = arena_address + ar_ptr.size sbrk_base = start # print("{:>19}".format("arena @ "), end="") # print_value("{:#x}".format(arena_address), end="\n\n") # print_title("{:>15}".format("flat heap listing"), end="\n") print_title("{:>15}{:>17}{:>18}".format("ADDR", "SIZE", "STATUS"), end="\n") print("{:11}".format("sbrk_base"), end="") print_value("{:#x}".format(int(sbrk_base)), end="\n") p = malloc_chunk(sbrk_base, inuse=True, read_data=False, debugger=self.dbg) while (1): print("{:11}".format("chunk"), end="") print_value("{: <#17x}".format(int(p.address)), end="") print("{: <#16x}".format(int(ptm.chunksize(p))), end="") if p.address == ptm.top(ar_ptr): print("(top)") break elif p.size == (0 | ptm.PREV_INUSE): print("(fence)") break if ptm.inuse(p): print("(inuse)") else: p = malloc_chunk(p.address, inuse=False, debugger=self.dbg) print("(F) FD ", end="") print_value("{:#x} ".format(int(p.fd))) print("BK ", end="") print_value("{:#x} ".format(int(p.bk))) if ((p.fd == ar_ptr.last_remainder) and (p.bk == ar_ptr.last_remainder) and (ar_ptr.last_remainder != 0)): print("(LR)") elif ((p.fd == p.bk) & ~ptm.inuse(p)): print("(LC)") else: print("") p = malloc_chunk(ptm.next_chunk(p), inuse=True, read_data=False, debugger=self.dbg) sbrk_end = int(sbrk_base + ar_ptr.max_system_mem) print("{:11}".format("sbrk_end"), end="") print_value("{:#x}".format(sbrk_end), end="") print("")
def invoke(self, arg, from_tty): ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() if ptm.SIZE_SZ == 4: pad_width = 27 elif ptm.SIZE_SZ == 8: pad_width = 31 # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") arena_address = self.dbg.format_address(main_arena.address) ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # mchunkptr bins in struct malloc_state if ptm.SIZE_SZ == 4: bins_offset = 4 + 4 + 40 + 4 + 4 # 56 sb_base = int(ar_ptr.address) + bins_offset elif ptm.SIZE_SZ == 8: bins_offset = 4 + 4 + 80 + 8 + 8 # 104 sb_base = int(ar_ptr.address) + bins_offset if len(arg) == 0: sb_num = None else: sb_num = int(arg.split(" ")[0]) if (sb_num * 2) > ptm.NBINS: print_error("Invalid smallbin number") return print_title("smallbins", end="") for sb in range(2, ptm.NBINS + 2, 2): if sb_num is not None and sb_num != 0: sb = sb_num*2 offset = sb_base + (sb - 2) * ptm.SIZE_SZ try: mem = self.dbg.read_memory(offset, 2 * ptm.SIZE_SZ) if ptm.SIZE_SZ == 4: fd, bk = struct.unpack("<II", mem) elif ptm.SIZE_SZ == 8: fd, bk = struct.unpack("<QQ", mem) except RuntimeError: print_error("Invalid smallbin addr {0:#x}".format(offset)) return print("") print("[ sb {:02} ] ".format(int(sb / 2)), end="") print("{:#x}{:>{width}}".format(int(offset), "-> ", width=5), end="") if fd == (offset - 2 * ptm.SIZE_SZ): print("[ {:#x} | {:#x} ] ".format(int(fd), int(bk)), end="") else: print_value("[ {:#x} | {:#x} ] ".format(int(fd), int(bk))) while (1): if fd == (offset - 2 * ptm.SIZE_SZ): break chunk = malloc_chunk(fd, inuse=False, debugger=self.dbg) print("") print_value("{:>{width}}{:#x} | {:#x} ] ".format("[ ", int(chunk.fd), int(chunk.bk), width=pad_width)) print("({})".format(int(ptm.chunksize(chunk))), end="") fd = chunk.fd if sb_num is not None: # only print one smallbin break print("")
def invoke(self, arg, from_tty): if arg.find("-h") != -1: # print_header("heap ", end="") # print("Options:", end="\n\n") # print_header("{:<15}".format("-a 0x1234")) # print("Specify an arena address") print_header("{:<15}".format("heapls")) print("Print a flat listing of all chunks in an arena") print_header("{:<15}".format("fastbins [#]")) print("Print all fast bins, or only a single fast bin") print_header("{:<15}".format("smallbins [#]")) print("Print all small bins, or only a single small bin") print_header("{:<15}".format("freebins")) print("Print compact bin listing (only free chunks)") print_header("{:<15}".format("heaplsc")) print("Print compact arena listing (all chunks)") print_header("{:<15}".format("mstats"), end="") print("Print memory alloc statistics similar to malloc_stats(3)") # print_header("{:<22}".format("print_bin_layout [#]"), end="") # print("Print the layout of a particular free bin") return ptm = ptmalloc(self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") # XXX: add arena address guessing via offset without symbols arena_address = self.dbg.format_address(main_arena.address) ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # XXX: add arena address passing via arg (-a) if (len(arg) == 0) and (ar_ptr.next == 0): # struct malloc_state may be invalid size (wrong glibc version) print_error("No arenas could be found at {:#x}".format( ar_ptr.address)) return print("Arena(s) found:", end="\n") print(" arena @ ", end="") print_header("{:#x}".format(int(ar_ptr.address)), end="\n") if ar_ptr.address != ar_ptr.next: # we have more than one arena curr_arena = malloc_state(ar_ptr.next, debugger=self.dbg, version=self.version) while (ar_ptr.address != curr_arena.address): print(" arena @ ", end="") print_header("{:#x}".format(int(curr_arena.address)), end="\n") curr_arena = malloc_state(curr_arena.next, debugger=self.dbg, version=self.version) if curr_arena.address == 0: print_error("No arenas could be correctly found.") break # breaking infinite loop
def invoke(self, arg, from_tty): ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() if ptm.SIZE_SZ == 4: pad_width = 27 elif ptm.SIZE_SZ == 8: pad_width = 31 # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") arena_address = self.dbg.format_address(main_arena.address) ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # mchunkptr bins in struct malloc_state sb_base = int(ar_ptr.address) + ar_ptr.bins_offset if len(arg) == 0: sb_num = None else: sb_num = int(arg.split(" ")[0]) if (sb_num * 2) > ptm.NBINS: print_error("Invalid smallbin number") return print_title("smallbins", end="") for sb in range(2, ptm.NBINS + 2, 2): if sb_num is not None and sb_num != 0: sb = sb_num*2 offset = sb_base + (sb - 2) * ptm.SIZE_SZ try: mem = self.dbg.read_memory(offset, 2 * ptm.SIZE_SZ) if ptm.SIZE_SZ == 4: fd, bk = struct.unpack("<II", mem) elif ptm.SIZE_SZ == 8: fd, bk = struct.unpack("<QQ", mem) except RuntimeError: print_error("Invalid smallbin addr {0:#x}".format(offset)) return print("") print("[ sb {:02} ] ".format(int(sb / 2)), end="") print("{:#x}{:>{width}}".format(int(offset), "-> ", width=5), end="") if fd == (offset - 2 * ptm.SIZE_SZ): print("[ {:#x} | {:#x} ] ".format(int(fd), int(bk)), end="") else: print_value("[ {:#x} | {:#x} ] ".format(int(fd), int(bk))) while (1): if fd == (offset - 2 * ptm.SIZE_SZ): break chunk = malloc_chunk(fd, inuse=False, debugger=self.dbg) print("") print_value("{:>{width}}{:#x} | {:#x} ] ".format("[ ", int(chunk.fd), int(chunk.bk), width=pad_width)) print("({})".format(int(ptm.chunksize(chunk))), end="") fd = chunk.fd if sb_num is not None: # only print one smallbin break print("")
def invoke(self, arg, from_tty): "Specify an optional arena addr: print_mstats main_arena=0x12345" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() try: # XXX: add mp_ address guessing via offset without symbols mp = self.dbg.read_variable("mp_") if arg.find("main_arena") == -1: main_arena = self.dbg.read_variable("main_arena") main_arena_address = self.dbg.format_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("Malloc Stats", end="\n\n") arena = 0 ar_ptr = malloc_state(main_arena_address, debugger=self.dbg, version=self.version) while (1): ptm.mutex_lock(ar_ptr) # account for top avail = ptm.chunksize( malloc_chunk(ptm.top(ar_ptr), inuse=True, read_data=False, debugger=self.dbg)) nblocks = 1 nfastblocks = 0 fastavail = 0 # traverse fastbins for i in range(ptm.NFASTBINS): p = ptm.fastbin(ar_ptr, i) while p != 0: p = malloc_chunk(p, inuse=False, debugger=self.dbg) nfastblocks += 1 fastavail += ptm.chunksize(p) p = p.fd avail += fastavail # traverse regular bins for i in range(1, ptm.NBINS): b = ptm.bin_at(ar_ptr, i) first = malloc_chunk(b, inuse=False, debugger=self.dbg) first = ptm.first(first) p = malloc_chunk(first, inuse=False, debugger=self.dbg) while p.address != int(b): nblocks += 1 avail += ptm.chunksize(p) p = malloc_chunk(ptm.first(p), inuse=False, debugger=self.dbg) print_header("Arena {}:".format(arena), end="\n") 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) ptm.mutex_unlock(ar_ptr) if ar_ptr.next == main_arena_address: break else: next_addr = self.dbg.format_address(ar_ptr.next) ar_ptr = malloc_state(next_addr, debugger=self.dbg, version=self.version) arena += 1 print_header("\nTotal (including mmap):", end="\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') # XXX: max_total_mem removed in 2.24 try: # catch the error before we print anything print_value("{}".format(mp['max_total_mem']), end='\n') print("{:16} = ".format("max system bytes"), end='') except gdb.error: pass 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')
def invoke(self, arg, from_tty): """Inspired by jp's phrack print and arena.c""" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") main_arena_address = self.dbg.format_address(main_arena.address) thread_arena = self.dbg.read_variable("thread_arena") if thread_arena is not None: thread_arena_address = self.dbg.format_address(thread_arena) else: thread_arena_address = main_arena_address argv = self.dbg.string_to_argv(arg) if len(argv) == 1: arena_address = int(argv[0], 16) elif len(argv): print_error('Too many arguments') return else: arena_address = thread_arena_address ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # XXX: add mp_ address guessing via offset without symbols mp_ = self.dbg.read_variable("mp_") mp_address = mp_.address mp = malloc_par(mp_address, debugger=self.dbg, version=self.version) if arena_address == main_arena_address: start, _ = self.dbg.get_heap_address(mp) else: # XXX: start offset start = arena_address + ar_ptr.size sbrk_base = start # print("{:>19}".format("arena @ "), end="") # print_value("{:#x}".format(arena_address), end="\n\n") # print_title("{:>15}".format("flat heap listing"), end="\n") print_title("{:>15}{:>17}{:>18}".format("ADDR", "SIZE", "STATUS"), end="\n") print("{:11}".format("sbrk_base"), end="") print_value("{:#x}".format(int(sbrk_base)), end="\n") p = malloc_chunk(sbrk_base, inuse=True, read_data=False, debugger=self.dbg) while(1): print("{:11}".format("chunk"), end="") print_value("{: <#17x}".format(int(p.address)), end="") print("{: <#16x}".format(int(ptm.chunksize(p))), end="") if p.address == ptm.top(ar_ptr): print("(top)") break elif p.size == (0 | ptm.PREV_INUSE): print("(fence)") break if ptm.inuse(p): print("(inuse)") else: p = malloc_chunk(p.address, inuse=False, debugger=self.dbg) print("(F) FD ", end="") print_value("{:#x} ".format(int(p.fd))) print("BK ", end="") print_value("{:#x} ".format(int(p.bk))) if ((p.fd == ar_ptr.last_remainder) and (p.bk == ar_ptr.last_remainder) and (ar_ptr.last_remainder != 0)): print("(LR)") elif ((p.fd == p.bk) & ~ptm.inuse(p)): print("(LC)") else: print("") p = malloc_chunk(ptm.next_chunk(p), inuse=True, read_data=False, debugger=self.dbg) sbrk_end = int(sbrk_base + ar_ptr.max_system_mem) print("{:11}".format("sbrk_end"), end="") print_value("{:#x}".format(sbrk_end), end="") print("")
def invoke(self, arg, from_tty): "modified from jp's phrack printing" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") arena_address = self.dbg.format_address(main_arena.address) ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # 8 bytes into struct malloc_state on both 32/64bit # XXX: fixme for glibc <= 2.19 with THREAD_STATS fastbinsY = int(ar_ptr.address) + 8 fb_base = fastbinsY # mchunkptr bins in struct malloc_state if ptm.SIZE_SZ == 4: bins_offset = 4 + 4 + 40 + 4 + 4 # 56 sb_base = int(ar_ptr.address) + bins_offset elif ptm.SIZE_SZ == 8: bins_offset = 4 + 4 + 80 + 8 + 8 # 104 sb_base = int(ar_ptr.address) + bins_offset # print_title("Heap Dump") for fb in range(0, ptm.NFASTBINS): print_once = True p = malloc_chunk(fb_base - (2 * ptm.SIZE_SZ) + fb * ptm.SIZE_SZ, inuse=False, debugger=self.dbg) while (p.fd != 0): if p.fd is None: break if print_once: print_once = False if fb > 0: print("") print_header("fast bin {}".format(fb), end="") print(" @ ", end="") print_value("{:#x}".format(p.fd), end="") print("\n\tfree chunk @ ", end="") print_value("{:#x} ".format(int(p.fd))) print("- size ", end="") p = malloc_chunk(p.fd, inuse=False, debugger=self.dbg) print("{:#x}".format(int(ptm.chunksize(p))), end="") for i in range(1, ptm.NBINS): print_once = True b = sb_base + i * 2 * ptm.SIZE_SZ - 4 * ptm.SIZE_SZ first = ptm.first(malloc_chunk(b, inuse=False, debugger=self.dbg)) p = malloc_chunk(first, inuse=False, debugger=self.dbg) while p.address != int(b): if print_once: print("") print_once = False if i == 1: print_header("unsorted bin", end="") else: print_header("small bin {}".format(i)) print(" @ ", end="") print_value("{:#x}".format(int(b) + 2 * ptm.SIZE_SZ), end="") print("\n\tfree chunk @ ", end="") print_value("{:#x} ".format(int(p.address))) print("- size ", end="") print("{:#x}".format(int(ptm.chunksize(p))), end="") p = malloc_chunk(ptm.first(p), inuse=False, debugger=self.dbg) print("")
def invoke(self, arg, from_tty): ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() if ptm.SIZE_SZ == 4: pad_width = 25 elif ptm.SIZE_SZ == 8: pad_width = 29 # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") arena_address = self.dbg.format_address(main_arena.address) thread_arena = self.dbg.read_variable("thread_arena") if thread_arena is not None: thread_arena_address = self.dbg.format_address(thread_arena) else: thread_arena_address = arena_address argv = self.dbg.string_to_argv(arg) if len(argv) == 1: arena_address = int(argv[0], 16) elif len(argv): print_error('Too many arguments') return else: arena_address = thread_arena_address ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # 8 bytes into struct malloc_state on both 32/64bit # XXX: fixme for glibc <= 2.19 with THREAD_STATS fastbinsY = int(ar_ptr.address) + 8 fb_base = fastbinsY print_title("fastbins", end="") for fb in range(0, ptm.NFASTBINS): offset = int(fb_base + fb * ptm.SIZE_SZ) try: mem = self.dbg.read_memory(offset, ptm.SIZE_SZ) if ptm.SIZE_SZ == 4: fd = struct.unpack("<I", mem)[0] elif ptm.SIZE_SZ == 8: fd = struct.unpack("<Q", mem)[0] except RuntimeError: print_error("Invalid fastbin addr {0:#x}".format(offset)) return print("") print("[ fb {} ] ".format(fb), end="") print("{:#x}{:>{width}}".format(offset, "-> ", width=5), end="") if fd == 0: print("[ {:#x} ] ".format(fd), end="") else: print_value("[ {:#x} ] ".format(fd)) if fd != 0: # fastbin is not empty fb_size = ((ptm.MIN_CHUNK_SIZE) + (ptm.MALLOC_ALIGNMENT) * fb) print("({})".format(int(fb_size)), end="") chunk = malloc_chunk(fd, inuse=False, debugger=self.dbg) while chunk.fd != 0: if chunk.fd is None: # could not read memory section break print_value("\n{:>{width}} {:#x} {} ".format( "[", chunk.fd, "]", width=pad_width)) print("({})".format(fb_size), end="") chunk = malloc_chunk(chunk.fd, inuse=False, debugger=self.dbg) print("")
def invoke(self, arg, from_tty): "Specify an optional arena addr: print_mstats main_arena=0x12345" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() try: # XXX: add mp_ address guessing via offset without symbols mp = self.dbg.read_variable("mp_") if arg.find("main_arena") == -1: main_arena = self.dbg.read_variable("main_arena") main_arena_address = self.dbg.format_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("Malloc Stats", end="\n\n") arena = 0 ar_ptr = malloc_state(main_arena_address, debugger=self.dbg, version=self.version) while(1): ptm.mutex_lock(ar_ptr) # account for top avail = ptm.chunksize(malloc_chunk(ptm.top(ar_ptr), inuse=True, read_data=False, debugger=self.dbg)) nblocks = 1 nfastblocks = 0 fastavail = 0 # traverse fastbins for i in range(ptm.NFASTBINS): p = ptm.fastbin(ar_ptr, i) while p != 0: p = malloc_chunk(p, inuse=False, debugger=self.dbg) nfastblocks += 1 fastavail += ptm.chunksize(p) p = p.fd avail += fastavail # traverse regular bins for i in range(1, ptm.NBINS): b = ptm.bin_at(ar_ptr, i) first = malloc_chunk(b, inuse=False, debugger=self.dbg) first = ptm.first(first) p = malloc_chunk(first, inuse=False, debugger=self.dbg) while p.address != int(b): nblocks += 1 avail += ptm.chunksize(p) p = malloc_chunk(ptm.first(p), inuse=False, debugger=self.dbg) print_header("Arena {}:".format(arena), end="\n") 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) ptm.mutex_unlock(ar_ptr) if ar_ptr.next == main_arena_address: break else: next_addr = self.dbg.format_address(ar_ptr.next) ar_ptr = malloc_state(next_addr, debugger=self.dbg, version=self.version) arena += 1 print_header("\nTotal (including mmap):", end="\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') # XXX: max_total_mem removed in 2.24 try: # catch the error before we print anything val = mp['max_total_mem'] print("{:16} = ".format("max system bytes"), end='') print_value("{}".format(val), end='\n') except gdb.error: pass 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')
def invoke(self, arg, from_tty): "Specify an optional arena addr: print_bin_layout main_arena=0x12345" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() if len(arg) == 0: print_error("Please specify the free bin to dump") return try: if arg.find("main_arena") == -1: main_arena = self.dbg.read_variable("main_arena") main_arena_address = self.dbg.format_address( main_arena.address) else: # XXX: fixme 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, debugger=self.dbg, version=self.version) ptm.mutex_lock(ar_ptr) # print_title("Bin Layout") if int(arg) == 0: print_error("bin_at(0) does not exist") return b = ptm.bin_at(ar_ptr, int(arg)) first = ptm.first(malloc_chunk(b, inuse=False, debugger=self.dbg)) p = malloc_chunk(first, inuse=False, debugger=self.dbg) 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(ptm.first(p), inuse=False, debugger=self.dbg) 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_value("Bin {} ".format(int(arg)), end="") print("empty") ptm.mutex_unlock(ar_ptr)
def invoke(self, arg, from_tty): # XXX: self.dbg.string_to_argv if arg.find("-h") != -1: # print_header("heap ", end="") # print("Options:", end="\n\n") # print_header("{:<15}".format("-a 0x1234")) # print("Specify an arena address") print_header("{:<15}".format("heapls")) print("Print a flat listing of all chunks in an arena") print_header("{:<15}".format("fastbins [#]")) print("Print all fast bins, or only a single fast bin") print_header("{:<15}".format("smallbins [#]")) print("Print all small bins, or only a single small bin") print_header("{:<15}".format("freebins")) print("Print compact bin listing (only free chunks)") print_header("{:<15}".format("heaplsc")) print("Print compact arena listing (all chunks)") print_header("{:<15}".format("mstats"), end="") print("Print memory alloc statistics similar to malloc_stats(3)") # print_header("{:<22}".format("print_bin_layout [#]"), end="") # print("Print the layout of a particular free bin") return ptm = ptmalloc(self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") # XXX: add arena address guessing via offset without symbols arena_address = self.dbg.format_address(main_arena.address) ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # XXX: add arena address passing via arg (-a) if (len(arg) == 0) and (ar_ptr.next == 0): # struct malloc_state may be invalid size (wrong glibc version) print_error("No arenas could be found at {:#x}".format( ar_ptr.address)) return print("Arena(s) found:", end="\n") print(" arena @ ", end="") print_header("{:#x}".format(int(ar_ptr.address)), end="\n") if ar_ptr.address != ar_ptr.next: # we have more than one arena curr_arena = malloc_state(ar_ptr.next, debugger=self.dbg, version=self.version) while (ar_ptr.address != curr_arena.address): print(" arena @ ", end="") print_header("{:#x}".format(int(curr_arena.address)), end="\n") curr_arena = malloc_state(curr_arena.next, debugger=self.dbg, version=self.version) if curr_arena.address == 0: print_error("No arenas could be correctly found.") break # breaking infinite loop
def invoke(self, arg, from_tty): "Specify an optional arena addr: print_bin_layout main_arena=0x12345" ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() if len(arg) == 0: print_error("Please specify the free bin to dump") return try: if arg.find("main_arena") == -1: main_arena = self.dbg.read_variable("main_arena") main_arena_address = self.dbg.format_address( main_arena.address) else: # XXX: fixme 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, debugger=self.dbg, version=self.version) ptm.mutex_lock(ar_ptr) # print_title("Bin Layout") if int(arg) == 0: print_error("bin_at(0) does not exist") return b = ptm.bin_at(ar_ptr, int(arg)) first = ptm.first(malloc_chunk(b, inuse=False, debugger=self.dbg)) p = malloc_chunk(first, inuse=False, debugger=self.dbg) 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(ptm.first(p), inuse=False, debugger=self.dbg) 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_value("Bin {} ".format(int(arg)), end="") print("empty") ptm.mutex_unlock(ar_ptr)
def invoke(self, arg, from_tty): ptm = ptmalloc(debugger=self.dbg) if ptm.SIZE_SZ == 0: ptm.set_globals() if ptm.SIZE_SZ == 4: pad_width = 25 elif ptm.SIZE_SZ == 8: pad_width = 29 # XXX: from old heap command, replace main_arena = self.dbg.read_variable("main_arena") arena_address = self.dbg.format_address(main_arena.address) thread_arena = self.dbg.read_variable("thread_arena") if thread_arena is not None: thread_arena_address = self.dbg.format_address(thread_arena) else: thread_arena_address = arena_address argv = self.dbg.string_to_argv(arg) if len(argv) == 1: arena_address = int(argv[0], 16) elif len(argv): print_error('Too many arguments') return else: arena_address = thread_arena_address ar_ptr = malloc_state(arena_address, debugger=self.dbg, version=self.version) # 8 bytes into struct malloc_state on both 32/64bit # XXX: fixme for glibc <= 2.19 with THREAD_STATS fastbinsY = int(ar_ptr.address) + 8 fb_base = fastbinsY print_title("fastbins", end="") for fb in range(0, ptm.NFASTBINS): offset = int(fb_base + fb * ptm.SIZE_SZ) try: mem = self.dbg.read_memory(offset, ptm.SIZE_SZ) if ptm.SIZE_SZ == 4: fd = struct.unpack("<I", mem)[0] elif ptm.SIZE_SZ == 8: fd = struct.unpack("<Q", mem)[0] except RuntimeError: print_error("Invalid fastbin addr {0:#x}".format(offset)) return print("") print("[ fb {} ] ".format(fb), end="") print("{:#x}{:>{width}}".format(offset, "-> ", width=5), end="") if fd == 0: print("[ {:#x} ] ".format(fd), end="") else: print_value("[ {:#x} ] ".format(fd)) if fd != 0: # fastbin is not empty fb_size = ((ptm.MIN_CHUNK_SIZE) + (ptm.MALLOC_ALIGNMENT) * fb) print("({})".format(int(fb_size)), end="") chunk = malloc_chunk(fd, inuse=False, debugger=self.dbg) while chunk.fd != 0: if chunk.fd is None: # could not read memory section break print_value("\n{:>{width}} {:#x} {} ".format("[", chunk.fd, "]", width=pad_width)) print("({})".format(fb_size), end="") chunk = malloc_chunk(chunk.fd, inuse=False, debugger=self.dbg) print("")