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): "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): "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): "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): # 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