Ejemplo n.º 1
0
    def listing(self):
        """Print all the chunks in all the given arenas using a flat listing
        """

        pu.print_title("{:>15} for arena @ {:#x}".format("flat heap listing", self.cache.mstate.address), end="\n")

        # Prepare arguments for "ptchunk" format
        # i.e. there is only one start address == sbrk_base
        if self.ptm.SIZE_SZ == 4:
            # Workaround on 32-bit. Empirically it seems the first chunk starts at offset +0x8?
            self.args.addresses = [ f"{self.sbrk_base+0x8:#x}"]
        else:
            self.args.addresses = [ f"{self.sbrk_base:#x}"]
        self.args.no_newline = False
        
        chunks = ptchunk.ptchunk.parse_many2(self)

        if len(chunks) > 0:
            if self.args.count == None:
                print(f"Total of {len(chunks)} chunks")
            else:
                print(f"Total of {len(chunks)}+ chunks")

        if self.args.json_filename != None:
            ptchunk.ptchunk.dump_json(self, chunks)
Ejemplo n.º 2
0
    def compact_listing(self):
        """Print all the chunks in a given arena using a compact flat listing
        """

        max_count = self.args.count

        pu.print_title("{:>15} for arena @ {:#x}".format("compact flat heap listing", self.cache.mstate.address), end="\n")

        if self.ptm.SIZE_SZ == 4:
            # Workaround on 32-bit. Empirically it seems the first chunk starts at offset +0x8?
            addr = self.sbrk_base+8
        else:
            addr = self.sbrk_base

        count = 0
        while True:
            p = mc.malloc_chunk(
                self.ptm, 
                addr, 
                read_data=False, 
                debugger=self.dbg,
                use_cache=True
            )

            if p.address == self.ptm.top(self.cache.mstate):
                print("|T", end="")
                count += 1
                break

            if p.type == pt.chunk_type.FREE_FAST:
                print("|f%d" % self.ptm.fast_bin_index(self.ptm.chunksize(p)), end="")
            elif p.type == pt.chunk_type.FREE_TCACHE:
                print("|t%d" % self.ptm.tcache_bin_index(self.ptm.chunksize(p)), end="")
            elif p.type == pt.chunk_type.INUSE:
                print("|M", end="")
            else:
                if (
                    (p.fd == self.cache.mstate.last_remainder)
                    and (p.bk == self.cache.mstate.last_remainder)
                    and (self.cache.mstate.last_remainder != 0)
                ):
                    print("|L", end="")
                else:
                    print("|F%d" % self.ptm.bin_index(self.ptm.chunksize(p)), end="")
            count += 1
            sys.stdout.flush()

            if max_count != None and count == max_count:
                break

            addr = self.ptm.next_chunk(p)

        print("|")
        if max_count == None:
            print(f"Total of {count} chunks")
        else:
            print(f"Total of {count}+ chunks")
Ejemplo n.º 3
0
    def show_fastbins(self, mstate, use_cache=False):
        """Browse the malloc_state.fastbinsY[] fd entries and show how many chunks there is.
        It does not show the actual chunks in each bin though
        """

        # We update the cache here so we can see the status before we print
        # the title below. Hence we pass use_cache=False on fastbins_to_string() call
        self.ptm.cache.update_fast_bins(show_status=self.args.debug, use_cache=use_cache)

        pu.print_title("Fast bins in malloc_state @ {:#x}".format(mstate.address), end="")
        txt = mstate.fastbins_to_string(verbose=self.args.verbose+1, use_cache=False)
        print(txt)
Ejemplo n.º 4
0
    def show_stats(self):
        """Show a summary of the memory statistics
        """

        self.cache.update_arena(show_status=False)
        self.cache.update_param(show_status=False)
        self.cache.update_tcache(show_status=False)
        self.cache.update_tcache_bins(show_status=False)

        main_arena_address = self.cache.main_arena_address
        par = self.cache.par

        in_use_b = par.mmapped_mem
        avail_b = 0
        system_b = in_use_b

        pu.print_title("Malloc Stats", end="\n\n")

        arena = 0
        mstate = ms.malloc_state(
            self.ptm, main_arena_address, debugger=self.dbg, version=self.version
        )
        while 1:

            self.cache.update_arena(address=mstate.address, show_status=False)
            self.cache.update_fast_bins(show_status=False)
            self.cache.update_bins(show_status=False)

            if mstate.address == self.cache.main_arena_address:
                sbrk_base, _ = self.dbg.get_heap_address(par)
            else:
                sbrk_base = (mstate.address + mstate.size + self.ptm.MALLOC_ALIGN_MASK) & ~self.ptm.MALLOC_ALIGN_MASK

            avail = 0
            inuse = 0
            nblocks = 1
            addr = sbrk_base
            while True:
                p = mc.malloc_chunk(
                    self.ptm, 
                    addr, 
                    read_data=False, 
                    debugger=self.dbg,
                    use_cache=True
                )

                if p.address == self.ptm.top(self.cache.mstate):
                    avail += self.ptm.chunksize(p)
                    break

                if p.type == pt.chunk_type.FREE_FAST:
                    avail += self.ptm.chunksize(p)
                elif p.type == pt.chunk_type.FREE_TCACHE:
                    avail += self.ptm.chunksize(p)
                elif p.type == pt.chunk_type.INUSE:
                    inuse += self.ptm.chunksize(p)
                else:
                    avail += self.ptm.chunksize(p)
                nblocks += 1

                addr = self.ptm.next_chunk(p)

            pu.print_header("Arena {} @ {:#x}:".format(arena, mstate.address), end="\n")
            print("{:16} = ".format("system bytes"), end="")
            pu.print_value("{} ({:#x})".format(mstate.max_system_mem, mstate.max_system_mem), end="\n")
            print("{:16} = ".format("free bytes"), end="")
            pu.print_value("{} ({:#x})".format(avail, avail), end="\n")
            print("{:16} = ".format("in use bytes"), end="")
            pu.print_value("{} ({:#x})".format(inuse, inuse), end="\n")

            system_b += mstate.max_system_mem
            avail_b += avail
            in_use_b += inuse

            if mstate.next == main_arena_address:
                break
            else:
                next_addr = self.dbg.format_address(mstate.next)
                mstate = ms.malloc_state(
                    self.ptm, next_addr, debugger=self.dbg, version=self.version
                )
                arena += 1

        pu.print_header("\nTotal (including mmap):", end="\n")
        print("{:16} = ".format("system bytes"), end="")
        pu.print_value("{} ({:#x})".format(system_b, system_b), end="\n")
        print("{:16} = ".format("free bytes"), end="")
        pu.print_value("{} ({:#x})".format(avail_b, avail_b), end="\n")
        print("{:16} = ".format("in use bytes"), end="")
        pu.print_value("{} ({:#x})".format(in_use_b, in_use_b), end="\n")

        if self.version <= 2.23:
            # catch the error before we print anything
            val = par.max_total_mem

            print("{:16} = ".format("max system bytes"), end="")
            pu.print_value("{}".format(val), end="\n")

        print("{:16} = ".format("max mmap regions"), end="")
        pu.print_value("{}".format(par.max_n_mmaps), end="\n")
        print("{:16} = ".format("max mmap bytes"), end="")
        pu.print_value("{}".format(par.max_mmapped_mem), end="\n")