blob: 8f8a6f2f8fc42444b1931a1577a4d796ccc74343 (
plain)
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
import gdb
import weenix
import weenix.list
PAGE_SIZE = 4096
_uint32_type = gdb.lookup_type("uint32_t")
_uintptr_type = gdb.lookup_type("uintptr_t")
_slab_type = gdb.lookup_type("struct slab")
_allocator_type = gdb.lookup_type("struct slab_allocator")
_bufctl_type = gdb.lookup_type("struct slab_bufctl")
_void_type = gdb.lookup_type("void")
# for Python 3 compatibility, where xrange is done away with
try:
xrange
except NameError:
xrange = range
class Slab:
def __init__(self, alloc, val):
self._alloc = alloc
if (val.type.code == gdb.TYPE_CODE_PTR):
self._value = val.cast(_slab_type.pointer()).dereference()
else:
self._value = val.cast(_slab_type)
def objs(self, typ=None):
next = self._value["s_addr"]
for i in xrange(int(self._alloc["sa_slab_nobjs"])):
bufctl = (next.cast(_uintptr_type)
+ self._alloc["sa_objsize"]).cast(_bufctl_type.pointer())
if (bufctl.dereference()["u"]["sb_slab"] == self._value.address):
# if redzones are in effect we need to skip them
if (int(next.cast(_uint32_type.pointer()).dereference()) == 0xdeadbeef):
value = (next.cast(_uint32_type.pointer()) + 1).cast(_void_type.pointer())
else:
value = next
if (typ != None):
yield value.cast(typ.pointer())
else:
yield value
next = (next.cast(_uintptr_type)
+ self._alloc["sa_objsize"]
+ _bufctl_type.sizeof).cast(_void_type.pointer())
class SlabAllocator:
def __init__(self, val):
if (val.type.code == gdb.TYPE_CODE_PTR):
self._value = val.cast(_allocator_type.pointer()).dereference()
else:
self._value = val.cast(_allocator_type)
def name(self):
return self._value["sa_name"].string()
def size(self):
return int(self._value["sa_objsize"])
def slabs(self):
next = self._value["sa_slabs"]
while (next != 0):
yield Slab(self._value, next.dereference())
next = next.dereference()["s_next"]
def objs(self, typ=None):
for slab in self.slabs():
for obj in slab.objs(typ):
yield obj
def __str__(self):
res = "name: {0}\n".format(self.name())
res += "slabcount: {0}\n".format(len(list(self.slabs())))
res += "objsize: {0}\n".format(self.size())
res += "objcount: {0}".format(len(list(self.objs())))
return res
def allocators():
next = gdb.parse_and_eval("slab_allocators")
while (next != 0):
yield SlabAllocator(next.dereference())
next = next.dereference()["sa_next"]
def allocator(name):
for alloc in allocators():
if name == alloc.name():
return alloc
raise KeyError(name)
def pagesize():
return PAGE_SIZE
def freepages():
freepages = dict()
for pagegroup in weenix.list.load("pagegroup_list", "struct pagegroup", "pg_link"):
freelist = pagegroup.item()["pg_freelist"]
for order in xrange(freelist.type.sizeof // freelist.type.target().sizeof):
psize = (1 << order) * PAGE_SIZE
count = len(weenix.list.load(freelist[order]))
if (order in freepages):
freepages[order] += count
else:
freepages[order] = count
return freepages
|