From 7e2d9f31d8f89315f07461825252c63b7ec54ee6 Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Tue, 25 Jun 2024 20:07:25 +0800 Subject: [PATCH 1/2] contrib/bpf_inspect.py: show used maps of prog Unlike `bpftool p` to show bpf map ids, `drgn contrib/bpf_inspect.py p --show-details` is able to show more bpf map info, which is useful to identify the used `.rodata` map. Signed-off-by: Leon Hwang --- contrib/bpf_inspect.py | 67 +++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/contrib/bpf_inspect.py b/contrib/bpf_inspect.py index 5571f31ff..045f870b0 100755 --- a/contrib/bpf_inspect.py +++ b/contrib/bpf_inspect.py @@ -65,6 +65,31 @@ def get_progs(self): return +class BpfMap(object): + def __init__(self, bpf_map): + self.map = bpf_map + + @staticmethod + def inspect_owner(owner): + type_ = BpfProgType(owner.type).name + jited = " JITed" if owner.jited.value_() else "" + return f"{type_:32}{jited}" + + def get_owner(self): + try: + owner = self.map.member_("owner") + return self.inspect_owner(owner) + except LookupError: + return "" + + def __repr__(self): + id_ = self.map.id.value_() + type_ = BpfMapType(self.map.map_type).name + name = self.map.name.string_().decode() + + return f"{id_:>6}: {type_:32} {name:32}" + + class BpfProg(object): def __init__(self, bpf_prog): self.prog = bpf_prog @@ -86,6 +111,10 @@ def get_btf_name(self): def get_prog_name(self): return self.get_btf_name() or self.prog.aux.name.string_().decode() + def get_used_maps(self): + for i in range(0, self.prog.aux.used_map_cnt.value_()): + yield BpfMap(self.prog.aux.used_maps[i]) + def get_linked_func(self): kind = bpf_attach_type_to_tramp(self.prog.expected_attach_type) @@ -141,44 +170,25 @@ def __repr__(self): return f"{id_:>6}: {type_:32} {name:32}{tail_call_desc}" -def list_bpf_progs(): +def list_bpf_progs(show_details=False): for bpf_prog_ in bpf_prog_for_each(prog): bpf_prog = BpfProg(bpf_prog_) print(f"{bpf_prog}") + if not show_details: + continue + linked_progs = bpf_prog.get_tramp_progs() if linked_progs: for linked_prog in linked_progs: print(f"\tlinked: {BpfProg(linked_prog)}") + for map_ in bpf_prog.get_used_maps(): + print(f"\t{"used map:":9} {map_}") -def __list_bpf_progs(args): - list_bpf_progs() - - -class BpfMap(object): - def __init__(self, bpf_map): - self.map = bpf_map - - @staticmethod - def inspect_owner(owner): - type_ = BpfProgType(owner.type).name - jited = " JITed" if owner.jited.value_() else "" - return f"{type_:32}{jited}" - def get_owner(self): - try: - owner = self.map.member_("owner") - return self.inspect_owner(owner) - except LookupError: - return "" - - def __repr__(self): - id_ = self.map.id.value_() - type_ = BpfMapType(self.map.map_type).name - name = self.map.name.string_().decode() - - return f"{id_:>6}: {type_:32} {name:32}" +def __list_bpf_progs(args): + list_bpf_progs(args.show_details) class BpfProgArrayMap(BpfMap): @@ -384,6 +394,9 @@ def main(): prog_parser = subparsers.add_parser("prog", aliases=["p"], help="list BPF programs") prog_parser.set_defaults(func=__list_bpf_progs) + prog_parser.add_argument( + "--show-details", action="store_true", help="show program internal details" + ) map_parser = subparsers.add_parser("map", aliases=["m"], help="list BPF maps") map_parser.set_defaults(func=__list_bpf_maps) From 7ff49062e6a8e9401a41ae3bbcbaa1e5feed3f5c Mon Sep 17 00:00:00 2001 From: Leon Hwang Date: Tue, 25 Jun 2024 20:24:09 +0800 Subject: [PATCH 2/2] contrib/bpf_inspect.py: show subprogs of prog Show subprog list when `--show-details`. It's useful to inspect subprog function name. Signed-off-by: Leon Hwang --- contrib/bpf_inspect.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/contrib/bpf_inspect.py b/contrib/bpf_inspect.py index 045f870b0..0be2ec3f8 100755 --- a/contrib/bpf_inspect.py +++ b/contrib/bpf_inspect.py @@ -94,6 +94,9 @@ class BpfProg(object): def __init__(self, bpf_prog): self.prog = bpf_prog + def is_subprog(self): + return self.prog.aux.func_idx.value_() != 0 + @staticmethod def __get_btf_name(btf, btf_id): type_ = btf.types[btf_id] @@ -108,13 +111,26 @@ def get_btf_name(self): return self.__get_btf_name(aux.btf, aux.func_info[0].type_id) return "" + def get_ksym_name(self): + try: + ksym = self.prog.aux.member_("ksym") + return ksym.name.string_().decode()[26:] + except LookupError: + return "" + def get_prog_name(self): + if self.is_subprog(): + return self.get_ksym_name() or self.prog.aux.name.string_().decode() return self.get_btf_name() or self.prog.aux.name.string_().decode() def get_used_maps(self): for i in range(0, self.prog.aux.used_map_cnt.value_()): yield BpfMap(self.prog.aux.used_maps[i]) + def get_subprogs(self): + for i in range(0, self.prog.aux.func_cnt.value_()): + yield i, BpfProg(self.prog.aux.func[i]) + def get_linked_func(self): kind = bpf_attach_type_to_tramp(self.prog.expected_attach_type) @@ -186,6 +202,9 @@ def list_bpf_progs(show_details=False): for map_ in bpf_prog.get_used_maps(): print(f"\t{"used map:":9} {map_}") + for index, subprog in bpf_prog.get_subprogs(): + print(f"\t{f"func[{index:>2}]:":9} {subprog}") + def __list_bpf_progs(args): list_bpf_progs(args.show_details)