0%

jemalloc5 脚本实现.md

实现思路

沿着内存dump的步骤

small slab

先忽略tcache的话, 需要关注的结构 je_arenas, arena, bins , bin->slabcur bin->slabs_nofull, bin->slabs_full, je_bin_infos extent_s

1
2
3
4
5
6
7
8
p je_arenas
p (*(struct arena_s*)je_arenas[0])
p (*(struct arena_s*)je_arenas[0]).bins
p (*(struct arena_s*)je_arenas[0]).bins[0] 0-NSIZES
p je_bin_infos
p (*(struct arena_s*)je_arenas[0]).bins[0].slabcur
p *(struct extent_s*) [p (*(struct arena_s*)je_arenas[0]).bins[0].slabcur] #取slabcur 的slab
p (*(struct arena_s*)je_arenas[0]).extents_dirty

extent 元信息中关于ind的信息?

extent_szind_get

(extent->e_bits & EXTENT_BITS_SZIND_MASK) >> EXTENT_BITS_SZIND_SHIFT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
EXTENT_BITS_ARENA_WIDTH = 12 ;
EXTENT_BITS_ARENA_SHIFT =0;
EXTENT_BITS_ARENA_MASK =((((1 << (12)) - 1)) << (0)); //4095 111111111111 fff
EXTENT_BITS_SLAB_WIDTH =1;
EXTENT_BITS_SLAB_SHIFT =(12 + 0);
EXTENT_BITS_SLAB_MASK =((((1 << (1)) - 1)) << ((12 + 0))); //4096 1000000000000 1000
EXTENT_BITS_COMMITTED_WIDTH = 1;
EXTENT_BITS_COMMITTED_SHIFT = (1 + (12 + 0));
EXTENT_BITS_COMMITTED_MASK =((((1 << (1)) - 1)) << ((1 + (12 + 0)))); //8192 10000000000000 2000
EXTENT_BITS_DUMPABLE_WIDTH = 1;
EXTENT_BITS_DUMPABLE_SHIFT = (1 + (1 + (12 + 0))) ;
EXTENT_BITS_DUMPABLE_MASK =((((1 << (1)) - 1)) << ((1 + (1 + (12 + 0))))); //16384 100000000000000 4000
EXTENT_BITS_ZEROED_WIDTH =1;
EXTENT_BITS_ZEROED_SHIFT =(1 + (1 + (1 + (12 + 0)))); //15 1111 f
EXTENT_BITS_ZEROED_MASK = ((((1 << (1)) - 1)) << ((1 + (1 + (1 + (12 + 0)))))); //32768 1000000000000000 8000
EXTENT_BITS_STATE_WIDTH = 2;
EXTENT_BITS_STATE_SHIFT = (1 + (1 + (1 + (1 + (12 + 0))))); //16
EXTENT_BITS_STATE_MASK =((((1 << (2)) - 1)) << ((1 + (1 + (1 + (1 + (12 + 0))))))); //196608 110000000000000000 30000
EXTENT_BITS_SZIND_WIDTH =8;
EXTENT_BITS_SZIND_SHIFT =(2 + (1 + (1 + (1 + (1 + (12 + 0)))))); // 18 10010 12
EXTENT_BITS_SZIND_MASK =((((1 << (8)) - 1)) << ((2 + (1 + (1 + (1 + (1 + (12 + 0)))))))); // 66846720 11111111000000000000000000 3FC0000
EXTENT_BITS_NFREE_WIDTH =((12 - 3) + 1); //10 1010 a
EXTENT_BITS_NFREE_SHIFT =(8 + (2 + (1 + (1 + (1 + (1 + (12 + 0))))))); //26 11010 1a
EXTENT_BITS_NFREE_MASK =((((1 << (((12 - 3) + 1))) - 1)) << ((8 + (2 + (1 + (1 + (1 + (1 + (12 + 0))))))))); // 68652367872 111111111100000000000000000000000000 FFC000000
EXTENT_BITS_SN_SHIFT =(((12 - 3) + 1) + (8 + (2 + (1 + (1 + (1 + (1 + (12 + 0)))))))); // 36 100100 24
EXTENT_BITS_SN_MASK =(18446744073709551615 << (((12 - 3) + 1) + (8 + (2 + (1 + (1 + (1 + (1 + (12 + 0))))))))); // FFFFFFFFFFFFFFFF000000000
1
2
e_bits = 29863505920
11011110100000000001111000000000000

通过rtree 信息直接检索所有的extent

1
2
3
p je_extents_rtree.root #遍历R树 是一个1<<18 容量的数组, root是头指针
p je_extents_rtree.root[x].child # 每一个都是1个 1<<18容量的数组, child是头指针, 需要遍历非0x0的有效数
#最后找出有效的叶子节点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct rtree_leaf_elm_s {
/*
* Single pointer-width field containing all three leaf element fields.
* For example, on a 64-bit x64 system with 48 significant virtual
* memory address bits, the index, extent, and slab fields are packed as
* such:
*
* x: index
* e: extent
* b: slab
*
* 00000000 xxxxxxxx eeeeeeee [...] eeeeeeee eeee000b
*/
atomic_p_t le_bits;
};
JEMALLOC_ALWAYS_INLINE extent_t *
rtree_leaf_elm_bits_extent_get(uintptr_t bits) {
/*
* aarch64 doesn't sign extend the highest virtual address bit to set
* the higher ones. Instead, the high bits gets zeroed.
*/
uintptr_t high_bit_mask = ((uintptr_t)1 << LG_VADDR) - 1 = (1 << 48) - 1;
/* Mask off the slab bit. */
uintptr_t low_bit_mask = ~(uintptr_t)1;
uintptr_t mask = high_bit_mask & low_bit_mask; // mask是48位的, 最后一位是0, 其余全1
return (extent_t *)(bits & mask);
}

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
eg:
slab对应的base地址是 0x7a45207040
# 查看e_addr的地址为extent分配块的地址, 其中存放了各个region
(gdb) p *(struct extent_s*)0x7a45207040
$7 = {
e_bits = 29863505920,
e_addr = 0x7a45009000,
{
e_size_esn = 4096,
e_bsize = 4096
},
ql_link = {
qre_next = 0x7a45207040,
qre_prev = 0x7a45207040
},
ph_link = {
phn_prev = 0x0,
phn_next = 0x0,
phn_lchild = 0x0
},
{
e_slab_data = {
bitmap = {2814749767106560, 18446744073709551404, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615}
},
e_prof_tctx = {
repr = 0xa000000000000
}
}
}

# rtree 第一级节点
0x7a45009000>>30
Out[60]: 489
(gdb) p je_extents_rtree.root[489].child
$23 = {
repr = 0x7a44c000c0
}
# rtree 第二级节点
In [62]: 0x7a45009000>>12 & ((1<<18)-1)
Out[62]: 20489
# 算相对 0x7a44c000c0 的偏移量
20489*8 + 0x7a44c000c0 = 0x7a44c28108
# 查看 0x7a44c28108 的内容
(gdb) x/a 0x7a44c28108
0x7a44c28108: 0x7a45207041
# 其index是0
0x7a45207041 >> 48 = 0