Ejemplo n.º 1
0
def jeparse_general():
    global jeheap

    try:
        jeheap.narenas = gdbutil.to_int(gdb.parse_and_eval('narenas'))
    except RuntimeError:
        print '[unmask_jemalloc] error: symbol narenas not found'
        sys.exit()

    try:
        jeheap.nbins = gdbutil.to_int(gdb.parse_and_eval('nbins'))
    except RuntimeError:
        # XXX: these are firefox specific, we must add support for more
        #      jemalloc variants in the future
        if sys.platform == 'darwin':
            jeheap.nbins = 35
        else:
            if jeheap.DWORD_SIZE == 4:
                jeheap.nbins = 24
            elif jeheap.DWORD_SIZE == 8:
                jeheap.nbins = 23

    # XXX: figure out how to calculate the chunk size correctly, this is
    #      firefox specific
    jeheap.chunk_size = 1 << 20
Ejemplo n.º 2
0
def jeparse_general():
    global jeheap

    try:
        jeheap.narenas = gdbutil.to_int(gdb.parse_and_eval('narenas'))
    except RuntimeError:
        print('[unmask_jemalloc] error: symbol narenas not found')
        sys.exit()

    try:
        jeheap.nbins = gdbutil.to_int(gdb.parse_and_eval('nbins'))
    except RuntimeError:
        # XXX: these are firefox specific, we must add support for more
        #      jemalloc variants in the future
        if sys.platform == 'darwin':
            jeheap.ntbins = gdbutil.to_int(gdb.parse_and_eval('ntbins'))
            jeheap.nsbins = gdbutil.to_int(gdb.parse_and_eval('nsbins'))
            jeheap.nqbins = gdbutil.to_int(gdb.parse_and_eval('nqbins'))
            jeheap.nbins = jeheap.ntbins + jeheap.nsbins + jeheap.nqbins
        else:
            if jeheap.DWORD_SIZE == 4:
                jeheap.nbins = 36
            elif jeheap.DWORD_SIZE == 8:
                jeheap.nbins = 35

    # XXX: figure out how to calculate the chunk size correctly, this is
    #      firefox specific
    jeheap.chunk_size = 1 << 20
Ejemplo n.º 3
0
def jeparse_chunks():
    global jeheap

    # delete the chunks' list
    jeheap.chunks[:] = []

    try:
        root = gdbutil.to_int(gdb.parse_and_eval('chunk_rtree.root'))
        height = gdbutil.to_int(gdb.parse_and_eval('chunk_rtree.height'))

        level2bits = []
        for i in range(0, height):
            expr = 'chunk_rtree.level2bits[%d]' % (i)
            level2bits.append(gdbutil.to_int(gdb.parse_and_eval(expr)))
    except:
        print('[unmask_jemalloc] error: cannot parse chunk radix tree')
        sys.exit()

    # check if we're running on x86_64
    if jeheap.DWORD_SIZE == 8:
        dw_fmt = 'g'
    else:
        dw_fmt = 'w'

    # parse the radix tree using a stack
    stack = [(root, 0)]
    while len(stack):
        (node, node_height) = stack.pop()
        child_cnt = 1 << level2bits[node_height]
        dump = gdb.execute('x/%d%sx %#x' % (child_cnt, dw_fmt, node),
                           to_string=true)

        for line in dump.split('\n'):
            line = line[line.find(':') + 1:]

            for address in line.split():
                address = int(address, 16)

                if address != 0:
                    # leaf nodes hold pointers to actual values
                    if node_height == height - 1:
                        expr = '((arena_chunk_t *)%#x)->arena' % address
                        arena = gdbutil.to_int(gdb.parse_and_eval(expr))

                        exists = false
                        if arena in [i.addr for i in jeheap.arenas]:
                            exists = true

                        if exists:
                            jeheap.chunks.append(
                                jemalloc.arena_chunk(address, arena))
                        else:
                            jeheap.chunks.append(jemalloc.arena_chunk(address))

                    # non-leaf nodes are inserted in the stack
                    else:
                        stack.append((address, node_height + 1))
Ejemplo n.º 4
0
def jeparse_chunks():
    global jeheap

    # delete the chunks' list
    jeheap.chunks = []

    try:
        root = gdbutil.to_int(gdb.parse_and_eval('chunk_rtree.root'))
        height = gdbutil.to_int(gdb.parse_and_eval('chunk_rtree.height'))

        level2bits = []
        for i in range(0, height):
            expr = 'chunk_rtree.level2bits[%d]' % (i)
            level2bits.append(gdbutil.to_int(gdb.parse_and_eval(expr)))
    except:
        print '[unmask_jemalloc] error: cannot parse chunk radix tree'
        sys.exit()

    # check if we're running on x86_64
    if jeheap.DWORD_SIZE == 8:
        dw_fmt = 'g'
    else:
        dw_fmt = 'w'

    # parse the radix tree using a stack
    stack = [(root, 0)]
    while len(stack):
        (node, node_height) = stack.pop()
        child_cnt = 1 << level2bits[node_height]
        dump = gdb.execute('x/%d%sx %#x' % (child_cnt, dw_fmt, node), to_string = true)

        for line in dump.split('\n'):
            line = line[line.find(':') + 1:]

            for address in line.split():
                address = int(address, 16) 

                if address != 0:
                    # leaf nodes hold pointers to actual values
                    if node_height == height - 1:
                        expr = '((arena_chunk_t *)%#x)->arena' % address
                        arena = gdbutil.to_int(gdb.parse_and_eval(expr))
 
                        exists = false
                        if arena in [i.addr for i in jeheap.arenas]:
                            exists = true

                        if exists:
                            jeheap.chunks.append(jemalloc.arena_chunk(address, arena))
                        else:
                            jeheap.chunks.append(jemalloc.arena_chunk(address))

                    # non-leaf nodes are inserted in the stack
                    else:
                        stack.append((address, node_height + 1))
Ejemplo n.º 5
0
def jeparse_options():
    global jeheap    
    
    opt_tcache = gdb.parse_and_eval('je_opt_tcache')
    if opt_tcache != 0:
        jeheap.MAGAZINES = true
        
        try:
            expr = 'sizeof(mag_rack_t) + (sizeof(bin_mags_t) * (jeheap.nbins - 1))'
            jeheap.magrack_size = gdbutil.to_int(gdb.parse_and_eval(expr))
        except RuntimeError:
            # standalone variant
            jeheap.STANDALONE = true
            expr = 'sizeof(tcache_t) + (sizeof(tcache_bin_t) * %d)' % (jeheap.nbins - 1)
            jemalloc.magrack_size = gdbutil.to_int(gdb.parse_and_eval(expr))
Ejemplo n.º 6
0
def jeparse_general():
    global jeheap

    try:
        jeheap.narenas = gdbutil.to_int(gdb.parse_and_eval('narenas'))
    except RuntimeError:
        print('[unmask_jemalloc] error: symbol narenas not found')
        sys.exit()

    if LG_SIZEOF_PTR == 2 and LG_TINY_MIN == 3 and LG_QUANTUM == 3 and LG_PAGE == 12:
        jeheap.ntbins = 0
        jeheap.nlbins = 32
        jeheap.nbins = 39
        jeheap.NSIZES = 107
    elif LG_SIZEOF_PTR == 2 and LG_TINY_MIN == 3 and LG_QUANTUM == 4 and LG_PAGE == 12:
        jeheap.ntbins = 1
        jeheap.nlbins = 29
        jeheap.nbins = 36
        jeheap.NSIZES = 104
    elif LG_SIZEOF_PTR == 2 and LG_TINY_MIN == 4 and LG_QUANTUM == 4 and LG_PAGE == 12:
        jeheap.ntbins = 0
        jeheap.nlbins = 28
        jeheap.nbins = 35
        jeheap.NSIZES = 103
    elif LG_SIZEOF_PTR == 3 and LG_TINY_MIN == 3 and LG_QUANTUM == 3 and LG_PAGE == 12:
        jeheap.ntbins = 0
        jeheap.nlbins = 32
        jeheap.nbins = 39
        jeheap.NSIZES = 235
    elif LG_SIZEOF_PTR == 3 and LG_TINY_MIN == 3 and LG_QUANTUM == 4 and LG_PAGE == 12:
        jeheap.ntbins = 1
        jeheap.nlbins = 29
        jeheap.nbins = 36
        jeheap.NSIZES = 232
    elif LG_SIZEOF_PTR == 3 and LG_TINY_MIN == 4 and LG_QUANTUM == 4 and LG_PAGE == 12:
        jeheap.ntbins = 0
        jeheap.nlbins = 28
        jeheap.nbins = 35
        jeheap.NSIZES = 231
    else:
        print("[unmask_jemalloc] error: configuation not specified!")
        sys.exit()

    # usually 1<<21
    jeheap.chunk_size = gdbutil.to_int(gdb.parse_and_eval('je_chunksize'))
Ejemplo n.º 7
0
def jeparse_options():
    global jeheap

    # thread magazine caches (disabled on firefox)
    try:
        opt_mag = gdb.parse_and_eval('opt_mag')
    except RuntimeError:
        opt_mag = 0

    try:
        opt_tcache = gdb.parse_and_eval('opt_tcache')
    except RuntimeError:
        opt_tcache = 0

    try:
        opt_lg_tcache_nslots = \
            gdb.parse_and_eval('opt_lg_tcache_nslots')
    except RuntimeError:
        opt_lg_tcache_nslots = 0

    if opt_mag != 0 or opt_tcache != 0 or opt_lg_tcache_nslots != 0:
        jeheap.MAGAZINES = true

    if jeheap.MAGAZINES == true:
        try:
            expr = 'sizeof(mag_rack_t) + (sizeof(bin_mags_t) * (jeheap.nbins - 1))'
            jeheap.magrack_size = \
                gdbutil.to_int(gdb.parse_and_eval(expr))

        except RuntimeError:
            # standalone variant
            jeheap.STANDALONE = true

            expr = 'sizeof(tcache_t) + (sizeof(tcache_bin_t) * (jeheap.nbins - 1))'
            jemalloc.magrack_size = \
                gdbutil.to_int(gdb.parse_and_eval())
Ejemplo n.º 8
0
def jeparse_options():
    global jeheap

    # thread magazine caches (disabled on firefox)
    try:
        opt_mag = gdb.parse_and_eval('opt_mag')
    except RuntimeError:
        opt_mag = 0

    try:
        opt_tcache = gdb.parse_and_eval('opt_tcache')
    except RuntimeError:
        opt_tcache = 0

    try:
        opt_lg_tcache_nslots = \
            gdb.parse_and_eval('opt_lg_tcache_nslots')
    except RuntimeError:
        opt_lg_tcache_nslots = 0

    if opt_mag != 0 or opt_tcache != 0 or opt_lg_tcache_nslots != 0:
        jeheap.MAGAZINES = true

    if jeheap.MAGAZINES == true:
        try:
            expr = 'sizeof(mag_rack_t) + (sizeof(bin_mags_t) * (jeheap.nbins - 1))'
            jeheap.magrack_size = \
                gdbutil.to_int(gdb.parse_and_eval(expr))

        except RuntimeError:
            # standalone variant
            jeheap.STANDALONE = true

            expr = 'sizeof(tcache_t) + (sizeof(tcache_bin_t) * (jeheap.nbins - 1))'
            jemalloc.magrack_size = \
                gdbutil.to_int(gdb.parse_and_eval(expr))
Ejemplo n.º 9
0
def jeparse_arenas():
    global jeheap

    jeheap.arenas[:] = []

    for i in range(0, jeheap.narenas):
        current_arena = jemalloc.arena(0, i, [])

        try:
            current_arena.addr = \
                gdbutil.to_int(gdb.parse_and_eval('arenas[%d]' % (i)))
        except:
            print '[unmask_jemalloc] error: cannot evaluate arenas[%d]' % (i)
            sys.exit()

        for j in range(0, jeheap.nbins):
            nrg        = 0
            run_sz     = 0
            reg_size   = 0
            reg_offset = 0
            end_addr   = 0

            try:
                expr = 'arenas[%d].bins[%d].reg_size' % (i, j)
                reg_size = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))
               
                expr = 'arenas[%d].bins[%d].reg0_offset' % (i, j) 
                reg_offset = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

            except RuntimeError:
                # XXX: for now assume it's a standalone variant; we
                #      need to do some error checking here too.
                jeheap.STANDALONE = true

                expr = 'arena_bin_info[%d].reg_size' % (j)
                reg_size = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

                expr = 'arena_bin_info[%d].nregs' % (j)
                nrg = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

                expr = 'arena_bin_info[%d].run_size' % (j)
                run_sz = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

            try:
                expr = 'arenas[%d].bins[%d].runcur' % (i, j)
                runcur_addr = runcur = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))
                end_addr = runcur_addr + run_sz

                if runcur != 0:
                    current_run = \
                        jemalloc.arena_run(runcur, end_addr, run_sz, 0, \
                            int(reg_size), reg_offset, nrg, 0, [])

                    current_bin = jemalloc.arena_bin(0, j, current_run)
                    current_bin.addr = \
                        gdbutil.to_int(gdb.parse_and_eval('&arenas[%d].bins[%d]' % (i, j)))

                    current_arena.bins.append(current_bin)

                else:
                    # no regions for this size class yet, therefore no runcur
                    current_run = jemalloc.arena_run()
                    current_bin = jemalloc.arena_bin(0, j, current_run)
                    current_arena.bins.append(current_bin)

            except RuntimeError:
                current_run = jemalloc.arena_run()
                current_bin = jemalloc.arena_bin(0, j, current_run)
                current_arena.bins.append(current_bin)
                continue

        # add arena to the list of arenas
        jeheap.arenas.append(current_arena)
Ejemplo n.º 10
0
def jeparse_arenas():
    global jeheap

    jeheap.arenas[:] = []

    for i in range(0, jeheap.narenas):
        current_arena = jemalloc.arena(0, i, [])

        try:
            current_arena.addr = \
                gdbutil.to_int(gdb.parse_and_eval('arenas[%d]' % (i)))
        except:
            print('[unmask_jemalloc] error: cannot evaluate arenas[%d]') % (i)
            sys.exit()

        for j in range(0, jeheap.nbins):
            nrg = 0
            run_sz = 0
            reg_size = 0
            reg_offset = 0
            end_addr = 0

            try:
                expr = 'arenas[%d].bins[%d].reg_size' % (i, j)
                reg_size = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

                expr = 'arenas[%d].bins[%d].reg0_offset' % (i, j)
                reg_offset = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

            except RuntimeError:
                # XXX: for now assume it's a standalone variant; we
                #      need to do some error checking here too.
                jeheap.STANDALONE = true

                expr = 'arena_bin_info[%d].reg_size' % (j)
                reg_size = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

                expr = 'arena_bin_info[%d].nregs' % (j)
                nrg = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

                expr = 'arena_bin_info[%d].run_size' % (j)
                run_sz = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))

            try:
                expr = 'arenas[%d].bins[%d].runcur' % (i, j)
                runcur_addr = runcur = \
                    gdbutil.to_int(gdb.parse_and_eval(expr))
                end_addr = runcur_addr + run_sz

                if runcur != 0:
                    current_run = \
                        jemalloc.arena_run(runcur, end_addr, run_sz, 0, \
                            int(reg_size), reg_offset, nrg, 0, [])

                    current_bin = jemalloc.arena_bin(0, j, current_run)
                    current_bin.addr = \
                        gdbutil.to_int(gdb.parse_and_eval('&arenas[%d].bins[%d]' % (i, j)))

                    current_arena.bins.append(current_bin)

                else:
                    # no regions for this size class yet, therefore no runcur
                    current_run = jemalloc.arena_run()
                    current_bin = jemalloc.arena_bin(0, j, current_run)
                    current_arena.bins.append(current_bin)

            except RuntimeError:
                current_run = jemalloc.arena_run()
                current_bin = jemalloc.arena_bin(0, j, current_run)
                current_arena.bins.append(current_bin)
                continue

        # add arena to the list of arenas
        jeheap.arenas.append(current_arena)
Ejemplo n.º 11
0
def jeparse_all_runs(proc):
    global jeheap

    # number of pages a chunk occupies
    chunk_npages = gdbutil.to_int(gdb.parse_and_eval("je_chunk_npages"))

    # offset of bits in arena_chunk_map_t in double words
    bitmap_offset = \
        gdbutil.offsetof('arena_chunk_map_bits_t', 'bits') / jeheap.DWORD_SIZE

    # number of double words occupied by an arena_chunk_map_t
    chunk_map_dwords = (bitmap_offset / jeheap.DWORD_SIZE) + 1

    # prefix to use in gdb's examine command
    if jeheap.DWORD_SIZE == 8:
        dword_fmt = 'g'
    else:
        dword_fmt = 'w'

    # the 12 least significant bits of each bitmap entry hold
    # various flags for the corresponding run
    flags_mask = (1 << 13) - 1

    # delete the heap's runs' array
    jeheap.runs[:] = []

    for chunk in jeheap.chunks:
        if not chunk.arena:
            continue

        try:
            # parse the whole map at once to avoid gdb delays
            expr = 'x/%d%sx ((arena_chunk_t *)%#x)->map_bits' % \
                (chunk_npages * chunk_map_dwords, dword_fmt, chunk.addr)
        except:
            print('[unmask_jemalloc] error: cannot read bitmap from chunk %#x' % (chunk.addr))
            sys.exit()

        lines = (gdb.execute(expr, to_string = true)).split('\n')

        dwords = []
        i = 0

        for line in lines:
            dwords += [int(dw, 16) for dw in line[line.find(':') + 1:].split()]

        bitmap = [dwords[i] for i in range(int(bitmap_offset), \
                int(len(dwords)), int(bitmap_offset + 1))]

        # traverse the bitmap
        for mapelm in bitmap:
            flags = mapelm & flags_mask

            # flags == 1 means the chunk is small and the rest of the bits
            # hold the actual run address
            if flags == 1:
                addr = mapelm & ~flags_mask
                size = gdbutil.get_page_size()

            # flags = 3 indicates a large chunk; calculate the run's address
            # directly from the map element index and extract the run's size 
            elif flags == 3:
                addr = chunk.addr + i * gdbutil.get_page_size()
                size = mapelm & ~flags_mask

            # run is not allocated? skip it
            else:
                continue
    
            if addr not in [r.start for r in jeheap.runs]:
                # XXX: we need to parse run headers here with a
                #      dedicated function
                new_run = jemalloc.arena_run(addr, 0, size, 0, 0, 0, 0, 0, [])
                jeheap.runs.append(new_run)
Ejemplo n.º 12
0
def jeparse_chunks():
    global jeheap

    # delete the chunks' list
    jeheap.chunks[:] = []

    try:
        height = gdbutil.to_int(gdb.parse_and_eval('je_chunks_rtree.height'))

    except:
        print('[unmask_jemalloc] error: cannot parse chunk radix tree')
        sys.exit()
        
    # check if we're running on x86_64
    # TODO: make it global
    if jeheap.DWORD_SIZE == 8:
        dw_fmt = 'g'
    else:
        dw_fmt = 'w'
        
    # insert root node to stack first (on level[0])
    stack = []
    for level in range(0, 3):
        bits = gdbutil.to_int(gdb.parse_and_eval('je_chunks_rtree.levels[%d].bits' % (level)))
        for bit in range(0, bits):
            try:
                subtree = gdbutil.to_int(gdb.parse_and_eval('je_chunks_rtree.levels[%d].subtree[%d]' %(level, bit)))
                print(subtree)
                if subtree == 0:
                    continue
            except:
                continue
    print("f****d!")

    while len(stack):
        (node, node_height) = stack.pop()

        child_cnt = gdbutil.to_int(node.bits)
        dump = gdb.execute('x/%d%sx %#x' % (child_cnt, dw_fmt, node), to_string = true)
        print(dump)
        print('--------')

        for line in dump.split('\n'):
            line = line[line.find(':') + 1:]

            for address in line.split():
                address = int(address, 16)

                if address != 0:
                    # leaf nodes hold pointers to actual values
                    if node_height == height - 1:
                        expr = '((arena_chunk_t *)%#x)->arena' % address
                        arena = gdbutil.to_int(gdb.parse_and_eval(expr))
 
                        exists = false
                        if arena in [i.addr for i in jeheap.arenas]:
                            exists = true

                        if exists:
                            jeheap.chunks.append(jemalloc.arena_chunk(address, arena))
                        else:
                            jeheap.chunks.append(jemalloc.arena_chunk(address))

                    # non-leaf nodes are inserted in the stack
                    else:
                        stack.append((address, node_height + 1))
Ejemplo n.º 13
0
def jeparse_arenas():
    global jeheap

    jeheap.arenas[:] = []

    for i in range(0, jeheap.narenas):
        current_arena = jemalloc.arena(0, i, [])

        try:
            current_arena.addr = \
                gdbutil.to_int(gdb.parse_and_eval('je_arenas[%d]' % (i)))
        except:
            print('[unmask_jemalloc] error: cannot evaluate je_arenas[%d]') % (i)
            sys.exit()

        for j in range(0, jeheap.nbins):
            nrg        = 0
            run_sz     = 0
            reg_size   = 0
            reg_offset = 0
            end_addr   = 0

            jeheap.STANDALONE = true

            reg_size = gdbutil.to_int(gdb.parse_and_eval('je_arena_bin_info[%d].reg_size' % (j)))
            nrg = gdbutil.to_int(gdb.parse_and_eval('je_arena_bin_info[%d].nregs' % (j)))
            run_sz = gdbutil.to_int(gdb.parse_and_eval('je_arena_bin_info[%d].run_size' % (j)))
            reg_offset = gdbutil.to_int(gdb.parse_and_eval('je_arena_bin_info[%d].reg0_offset' % (j)))

            try:
                expr = 'je_arenas[%d].bins[%d].runcur' % (i, j)
                runcur_addr = runcur = gdbutil.to_int(gdb.parse_and_eval(expr))
                end_addr = runcur_addr + run_sz

                if runcur != 0:
                    expr = 'je_arenas[%d].bins[%d].runcur.nfree' % (i, j)
                    nfree = gdbutil.to_int(gdb.parse_and_eval(expr))
                
                    current_run = \
                        jemalloc.arena_run(runcur, end_addr, run_sz, 0, \
                            int(reg_size), reg_offset, nrg, nfree, [])

                    current_bin = jemalloc.arena_bin(0, j, current_run)
                    current_bin.addr = \
                        gdbutil.to_int(gdb.parse_and_eval('&je_arenas[%d].bins[%d]' % (i, j)))

                    current_arena.bins.append(current_bin)

                else:
                    # no regions for this size class yet, therefore no runcur
                    current_run = jemalloc.arena_run()
                    current_bin = jemalloc.arena_bin(0, j, current_run)
                    current_arena.bins.append(current_bin)

            except RuntimeError:
                current_run = jemalloc.arena_run()
                current_bin = jemalloc.arena_bin(0, j, current_run)
                current_arena.bins.append(current_bin)
                continue

        # add arena to the list of arenas
        jeheap.arenas.append(current_arena)