From b591cb449d02133dcc2c617e7b8f1010e7482fbb Mon Sep 17 00:00:00 2001 From: Quentin Monnet Date: Mon, 17 Jan 2022 17:05:59 +0000 Subject: [PATCH] tools: Add commands to list BPF links and BTF objects to BPF script Add two commands to the BPF script, "b" and "l", to list the BTF objects and the BPF link (respectively) loaded on the system. These commands make use of the recently introduced helpers for iterating over those objects. Older kernels do not have eBPF links, so make sure we handle the lookup exception properly. Signed-off-by: Quentin Monnet --- tools/bpf_inspect.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tools/bpf_inspect.py b/tools/bpf_inspect.py index f6d8b183b..e875b6747 100755 --- a/tools/bpf_inspect.py +++ b/tools/bpf_inspect.py @@ -7,12 +7,18 @@ from drgn import container_of from drgn.helpers import enum_type_to_class from drgn.helpers.linux import ( + bpf_btf_for_each, bpf_link_for_each, bpf_map_for_each, bpf_prog_for_each, hlist_for_each_entry, ) +try: + BpfLinkType = enum_type_to_class(prog.type("enum bpf_link_type"), "BpfLinkType") +except LookupError: + BpfLinkType = None + BpfMapType = enum_type_to_class(prog.type("enum bpf_map_type"), "BpfMapType") BpfProgType = enum_type_to_class(prog.type("enum bpf_prog_type"), "BpfProgType") BpfAttachType = enum_type_to_class(prog.type("enum bpf_attach_type"), "BpfAttachType") @@ -145,9 +151,35 @@ def list_bpf_maps(args): print(f"{id_:>6}: {type_:32} {name}") +def list_bpf_btf(args): + for btf in bpf_btf_for_each(prog): + id_ = btf.id.value_() + name = btf.name.string_().decode() or "" + kernel = "kernel" if btf.kernel_btf.value_() == 1 else "" + + print(f"{id_:>6}: {kernel:6} {name}") + + +def list_bpf_links(args): + if BpfLinkType is None: + # BpfLinkType was not initialized properly, likely because the kernel + # is too old to support link. So there is no link to list, simply + # return. + return + + for link in bpf_link_for_each(prog): + id_ = link.id.value_() + type_ = BpfLinkType(link.type).name + prog_id = "" + if link.prog: + prog_id = link.prog.aux.id.value_() + + print(f"{id_:>6}: {type_:32} {prog_id:>6}") + + def main(): parser = argparse.ArgumentParser( - description="drgn script to list BPF programs or maps and their properties unavailable via kernel API" + description="drgn script to list BPF objects and their properties unavailable via kernel API" ) subparsers = parser.add_subparsers(title="subcommands", dest="subcommand") @@ -159,6 +191,12 @@ def main(): map_parser = subparsers.add_parser("map", aliases=["m"], help="list BPF maps") map_parser.set_defaults(func=list_bpf_maps) + link_parser = subparsers.add_parser("link", aliases=["l"], help="list BPF links") + link_parser.set_defaults(func=list_bpf_links) + + btf_parser = subparsers.add_parser("btf", aliases=["b"], help="list BTF objects") + btf_parser.set_defaults(func=list_bpf_btf) + args = parser.parse_args() args.func(args)