Skip to content

Conversation

@suchit07-git
Copy link

Introduce a new crash command 'bpf' to list eBPF programs and maps from the kernel. The command enumerates over all loaded BPF programs and maps, showing each program’s ID, addresses, type, tag, and the maps it uses.

@suchit07-git
Copy link
Author

@osandov, following up on this PR just in case if you haven't had a chance to look at this PR yet.

@osandov
Copy link
Owner

osandov commented Oct 23, 2025

Thanks again for working on this! I'm wrapping up a few things before cutting a new release, so I won't be able to take a good look until Friday at the earliest, but I haven't forgotten about it.

@suchit07-git
Copy link
Author

Thanks for the heads up @osandov. Sorry if I bugged you.

Copy link
Owner

@osandov osandov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, Suchit! Thanks so much for working on this. A couple of high-level comments:

  • The object-oriented style isn't idiomatic for drgn, which tends to follow a procedural style in order to follow the C kernel code more. I think you mostly inherited that from the contrib/bpf_inspect.py script, but that script wasn't typical either. Specifically, I'd prefer for the more complex methods to be helper functions in drgn.helpers.linux.bpf that operate directly on drgn.Objects (e.g., BpfProg.get_used_maps() -> bpf_prog_used_maps() or something like that). The simpler methods that only format things can just be folded directly into _crash_cmd_bpf(). You can add those helpers as separate PRs or as separate commits in this PR, your choice.
  • The --drgn option is the main motivation for doing this porting work, so it'd be nice for the initial version of this command to support it. Adding support for that will likely make it clear what should be added as a helper.

I left a couple of minor comments inline, too.

Let me know if you need any clarification or pointers!

Comment on lines 12 to 16
from drgn.helpers.linux import ( # type: ignore[attr-defined]
bpf_map_for_each,
bpf_prog_for_each,
hlist_for_each_entry,
)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import these from the specific submodules where they're defined (drgn.helpers.linux.bpf and drgn.helpers.linux.list) to avoid the need for the type: ignore.

Comment on lines 212 to 215
print(
f"{'ID':>4} {'BPF_PROG':<18} {'BPF_PROG_AUX':<18} {'BPF_PROG_TYPE':<18} "
f"{'TAG':<18} {'USED_MAPS'}"
)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer use of drgn.helpers.common.format.print_table() rather than manual formatting. There are lots of example in drgn/commands.

@suchit07-git
Copy link
Author

Hi @osandov. Thanks for the comments. I’ll make the required changes and let you know once they’re done. Apologies for the inconvenience.

@suchit07-git suchit07-git force-pushed the feat/display-ebpf-progs-and-maps-in-crash branch from 187ac4e to d828cc7 Compare November 6, 2025 12:20
@suchit07-git
Copy link
Author

Hi @osandov. Sorry for the delay. I've rewritten the code according to your comments. Could you please review it? Apologies in advance if I did mistakes again. Thanks.

Copy link
Owner

@osandov osandov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much closer to what I had in mind, thanks! I left some inline comments about formatting things more like crash and little tricks/cleanups.

Some high-level things:

  • --drgn still needs to be implemented. Search for args.drgn in drgn/commands/_builtin/crash for some examples.
  • This needs a test case. I implemented a test for the bpf_prog_used_maps() helper in my bpf-prog-used-maps branch. The crash command test cases tend to be pretty basic sanity checks, see tests/linux_kernel/crash_commands for examples. I think a test case for this command could simply create a BPF program and map just like test_bpf_prog_used_maps() and then check that the command prints at least that program and map.
  • When this is ready to be merged, just like when contributing to the kernel, I'd prefer for the commit history to be cleaned up so that there's one commit adding the helper and another adding the command (rather than the development history with fixups and merges).

@suchit07-git
Copy link
Author

Hi @osandov. Extremely sorry for the delay. I got a bit busy with work and some other stuff. I'll try to address your comments as early as possible. Thanks and sorry for the inconvenience.

@suchit07-git suchit07-git force-pushed the feat/display-ebpf-progs-and-maps-in-crash branch from 741d9e7 to 2ebbe80 Compare December 9, 2025 17:02
Introduce a new crash command 'bpf' to list eBPF programs and maps
from the kernel. The command enumerates over all loaded BPF programs and
maps, showing each program’s ID, addresses, type, tag, and the maps it
uses.

Signed-off-by: Suchit Karunakaran <[email protected]>
Refactor BPF inspection logic to follow drgn's procedural style rather
than an object-oriented one. Complex methods previously implemented as
class methods are now standalone helper functions.

Also replace manual table formatting in _crash_cmd_bpf() with
print_table() for consistency with other commands in the drgn codebase.

Signed-off-by: Suchit Karunakaran <[email protected]>
Refactor drgn BPF helpers by removing bpf_prog_trampoline_progs() and bpf_prog_subprogs() to streamline the API. Update the _crash_cmd_bpf() command to consistently format BPF program and map information, display addresses in hexadecimal, and support drgn code generation in interactive mode. Enhance the test suite by adding instruction constants and helper functions in tests/linux_kernel/bpf.py, and introduce a dedicated crash command test that verifies BPF program and map output, including tags and map IDs.

Signed-off-by: Suchit Karunakaran <[email protected]>
@suchit07-git suchit07-git force-pushed the feat/display-ebpf-progs-and-maps-in-crash branch from 201cfbf to b31991f Compare December 11, 2025 18:51
@osandov osandov linked an issue Dec 11, 2025 that may be closed by this pull request
Copy link
Owner

@osandov osandov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than cleaning up the commits, some linter errors in the CI, and a couple of minor comments below, this looks pretty much ready, thank you!

Comment on lines +36 to +59
"""\
for bpf_prog in bpf_prog_for_each(prog):
prog_id = bpf_prog.aux.id.value_()
prog_type_name = bpf_prog.type.format_(type_name=False).split("BPF_PROG_TYPE_")[
-1
]
tag = bpf_prog.tag
prog_tag = "".join(f"{b.value_():02x}" for b in tag)
used_maps = []
for map in bpf_prog_used_maps(bpf_prog):
used_maps.append(map.id.value_())
used_maps_str = ",".join(str(m) for m in used_maps)
for bpf_map in bpf_map_for_each(prog):
map_id = bpf_map.id.value_()
map_type_name = bpf_map.map_type.format_(type_name=False).split("BPF_MAP_TYPE_")[-1]
try:
map_flags = f"{bpf_map.map_flags.value_():08x}"
except LookupError:
map_flags = "00000000"
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry about any of the formatting stuff in the --drgn output; it's good enough to fetch the fields. Something like this:

Suggested change
"""\
for bpf_prog in bpf_prog_for_each(prog):
prog_id = bpf_prog.aux.id.value_()
prog_type_name = bpf_prog.type.format_(type_name=False).split("BPF_PROG_TYPE_")[
-1
]
tag = bpf_prog.tag
prog_tag = "".join(f"{b.value_():02x}" for b in tag)
used_maps = []
for map in bpf_prog_used_maps(bpf_prog):
used_maps.append(map.id.value_())
used_maps_str = ",".join(str(m) for m in used_maps)
for bpf_map in bpf_map_for_each(prog):
map_id = bpf_map.id.value_()
map_type_name = bpf_map.map_type.format_(type_name=False).split("BPF_MAP_TYPE_")[-1]
try:
map_flags = f"{bpf_map.map_flags.value_():08x}"
except LookupError:
map_flags = "00000000"
"""
"""\
for bpf_prog in bpf_prog_for_each():
aux = bpf_prog.aux
prog_id = aux.id
prog_type = bpf_prog.type
tag = bpf_prog.tag
for used_map in bpf_prog_used_maps(bpf_prog):
map_id = used_map.id
for bpf_map in bpf_map_for_each():
map_id = bpf_map.id
map_type = bpf_map.map_type
try:
map_flags = bpf_map.map_flags
except AttributeError:
# map_flags is only available since Linux 4.6.
pass
"""

# may not have this field, so we catch LookupError and default to 0.
try:
map_flags = f"{bpf_map.map_flags.value_():08x}"
except LookupError:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be AttributeError:

Suggested change
except LookupError:
except AttributeError:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash command: bpf

2 participants