aboutsummaryrefslogtreecommitdiff
path: root/python/weenix/kmem.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/weenix/kmem.py')
-rw-r--r--python/weenix/kmem.py109
1 files changed, 109 insertions, 0 deletions
diff --git a/python/weenix/kmem.py b/python/weenix/kmem.py
new file mode 100644
index 0000000..8f8a6f2
--- /dev/null
+++ b/python/weenix/kmem.py
@@ -0,0 +1,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