Exemple #1
0
    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("")
Exemple #2
0
    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("")
Exemple #3
0
    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("")
Exemple #4
0
    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
Exemple #5
0
    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("")
Exemple #6
0
    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')
Exemple #7
0
    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("")
Exemple #8
0
    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("")
Exemple #10
0
    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')
Exemple #11
0
    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)
Exemple #12
0
    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)
Exemple #14
0
    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("")