diff options
Diffstat (limited to 'bird-gdb.py')
-rw-r--r-- | bird-gdb.py | 124 |
1 files changed, 61 insertions, 63 deletions
diff --git a/bird-gdb.py b/bird-gdb.py index e11f9757..c53a3b55 100644 --- a/bird-gdb.py +++ b/bird-gdb.py @@ -1,6 +1,3 @@ -import itertools -import functools - class BIRDPrinter: def __init__(self, val): self.val = val @@ -29,7 +26,6 @@ class BIRDFValPrinter(BIRDPrinter): "T_ENUM_RTS": "i", "T_ENUM_BGP_ORIGIN": "i", "T_ENUM_SCOPE": "i", - "T_ENUM_RTC": "i", "T_ENUM_RTD": "i", "T_ENUM_ROA": "i", "T_ENUM_NETTYPE": "i", @@ -201,20 +197,12 @@ class BIRDList: if str(self.tail_node["prev"].address) == '0x0': raise Exception("List tail is NULL") - def __iter__(self): + def walk(self, do): cur = self.head while cur.dereference() != self.tail_node: - yield cur + do(cur) cur = cur.dereference()["next"] - def __len__(self): - return sum([1 for _ in self]) - - def __getitem__(self, key): - for item in itertools.islice(self, key): - return item - - raise KeyError("Not enough elements in list") class BIRDListLength(gdb.Function): """Returns length of the list, as in @@ -222,8 +210,13 @@ class BIRDListLength(gdb.Function): def __init__(self): super(BIRDListLength, self).__init__("list_length") + def count(self, _): + self.cnt += 1 + def invoke(self, l): - return len(BIRDList(l)) + self.cnt = 0 + BIRDList(l).walk(self.count) + return self.cnt BIRDListLength() @@ -232,11 +225,30 @@ class BIRDListItem(gdb.Function): def __init__(self): super(BIRDListItem, self).__init__("list_item") + class BLException(Exception): + def __init__(self, node, msg): + Exception.__init__(self, msg) + self.node = node + + def count(self, node): + if self.cnt == self.pos: + raise self.BLException(node, "Node found") + + self.cnt += 1 + def invoke(self, l, n, t=None, item="n"): - if t is None: - return BIRDList(l)[n] - else: - return BIRD.skip_back(t, item, BIRDList(l)[n]) + self.cnt = 0 + self.pos = n + bl = BIRDList(l) + try: + bl.walk(self.count) + except self.BLException as e: + if t is None: + return e.node + else: + return BIRD.skip_back(t, item, e.node) + + raise Exception("List too short") BIRDListItem() @@ -290,26 +302,19 @@ class BIRDLinPoolResource(BIRDResource): self.lptype = gdb.lookup_type("struct linpool") self.val = val.cast(self.lptype) self.info = None - self.std = self.ChunkList(self.val["first"]) - self.large = self.ChunkList(self.val["first_large"]) - - class ChunkList: - def __init__(self, val): - self.val = val - - def __iter__(self): - chunk = self.val - while str(chunk) != 0x0: - yield chunk - chunk = chunk.dereference()["next"] - def __len__(self): - return sum([1 for _ in self]) + def count_chunk(self, which): + cnt = 0 + chunk = self.val[which] + while str(chunk) != '0x0': + cnt += 1 + chunk = chunk.dereference()["next"] + return cnt def parse(self): self.info = { - "std_chunks": len(self.std), - "large_chunks": len(self.large), + "std_chunks": self.count_chunk("first"), + "large_chunks": self.count_chunk("first_large"), } def memsize(self): @@ -334,13 +339,14 @@ class BIRDSlabResource(BIRDResource): self.val = val.cast(self.slabtype) self.info = None + def count_heads_item(self, item): + self.hcnt += 1 + self.used += item.dereference().cast(self.slheadtype)["num_full"] + def count_heads(self, which): self.hcnt = 0 self.used = 0 - for item in BIRDList(self.val[which + "_heads"]): - self.hcnt += 1 - self.used += item.dereference().cast(self.slheadtype)["num_full"] - + BIRDList(self.val[which + "_heads"]).walk(self.count_heads_item) self.info[which + "_heads"] = self.hcnt self.info[which + "_used"] = self.used return (self.hcnt, self.used) @@ -375,36 +381,25 @@ class BIRDSlabResource(BIRDResource): f", {self.val['objs_per_slab']} objects of size {self.val['obj_size']} per head" -class BIRDIOLoopResource(BIRDResource): - def __init__(self, val): - self.iolooptype = gdb.lookup_type("struct birdloop") - self.val = val.cast(self.iolooptype) - self.pages = self.val["pages"] - self.page_size = gdb.lookup_symbol("page_size")[0].value() - - def memsize(self): - return BIRDResourceSize(0, self.iolooptype.sizeof, self.pages['cnt'] * self.page_size) - - def __str__(self): - return f"IO Loop {self.val.address} containing {self.pages['cnt']} free pages (min {self.pages['min']} max {self.pages['max']}), cleanup event {self.pages['cleanup'].dereference().address}: " + \ - ", ".join([ str(p) for p in BIRDList(self.pages["list"])]) - - class BIRDPoolResource(BIRDResource): def __init__(self, val): self.pooltype = gdb.lookup_type("struct pool") self.resptrtype = gdb.lookup_type("struct resource").pointer() + self.page_size = gdb.lookup_symbol("page_size")[0].value() self.val = val.cast(self.pooltype) - self.inside = BIRDList(self.val["inside"]) + self.items = None - def __iter__(self): - for val in self.inside: - yield BIRDNewResource(val.cast(self.resptrtype).dereference()) + def parse_inside(self, val): + self.items.append(BIRDNewResource(val.cast(self.resptrtype).dereference())) - def __len__(self): - return len(self.inside) + def parse(self): + self.items = [] + BIRDList(self.val["inside"]).walk(self.parse_inside) def memsize(self): + if self.items is None: + self.parse() + sum = BIRDResourceSize(0, self.pooltype.sizeof, 0) # for i in self.items: # sum += i.memsize() @@ -412,17 +407,19 @@ class BIRDPoolResource(BIRDResource): return sum def __str__(self): + if self.items is None: + self.parse() + # for i in self.items: # print(i) - return f"Resource pool {self.val.address} \"{self.val['name'].string()}\" containing {len(self)} items" + return f"Resource pool {self.val.address} \"{self.val['name'].string()}\" containing {len(self.items)} items" BIRDResourceMap = { "mbl_memsize": BIRDMBResource, "pool_memsize": BIRDPoolResource, "lp_memsize": BIRDLinPoolResource, "slab_memsize": BIRDSlabResource, - "birdloop_memsize": BIRDIOLoopResource, } def BIRDNewResource(res): @@ -442,13 +439,14 @@ class BIRDResourcePrinter(BIRDPrinter): def __init__(self, val): super(BIRDResourcePrinter, self).__init__(val) self.resource = BIRDNewResource(val) + self.resource.parse() self.resourcetype = gdb.lookup_type("struct resource") if type(self.resource) == BIRDPoolResource: self.children = self.pool_children def pool_children(self): - return iter([ ("\n", i.val.cast(self.resourcetype)) for i in self.resource ]) + return iter([ ("\n", i.val.cast(self.resourcetype)) for i in self.resource.items ]) def to_string(self): return f"[ {str(self.resource.memsize())} ] {str(self.resource)}" |