Skip to content

Commit 418fbe8

Browse files
walking-machineanakryiko
authored andcommitted
bpftool: Use sysfs vmlinux when dumping BTF by ID
Currently, dumping almost all BTFs specified by id requires using the -B option to pass the base BTF. For kernel module BTFs the vmlinux BTF sysfs path should work. This patch simplifies dumping by ID usage by loading vmlinux BTF from sysfs as base, if base BTF was not specified and the ID corresponds to a kernel module BTF. Signed-off-by: Larysa Zaremba <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Reviewed-by: Alexander Lobakin <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 16d1e00 commit 418fbe8

File tree

1 file changed

+53
-9
lines changed

1 file changed

+53
-9
lines changed

tools/bpf/bpftool/btf.c

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,51 @@ static int dump_btf_c(const struct btf *btf,
459459
return err;
460460
}
461461

462+
static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
463+
464+
static struct btf *get_vmlinux_btf_from_sysfs(void)
465+
{
466+
struct btf *base;
467+
468+
base = btf__parse(sysfs_vmlinux, NULL);
469+
if (libbpf_get_error(base)) {
470+
p_err("failed to parse vmlinux BTF at '%s': %ld\n",
471+
sysfs_vmlinux, libbpf_get_error(base));
472+
base = NULL;
473+
}
474+
475+
return base;
476+
}
477+
478+
#define BTF_NAME_BUFF_LEN 64
479+
480+
static bool btf_is_kernel_module(__u32 btf_id)
481+
{
482+
struct bpf_btf_info btf_info = {};
483+
char btf_name[BTF_NAME_BUFF_LEN];
484+
int btf_fd;
485+
__u32 len;
486+
int err;
487+
488+
btf_fd = bpf_btf_get_fd_by_id(btf_id);
489+
if (btf_fd < 0) {
490+
p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
491+
return false;
492+
}
493+
494+
len = sizeof(btf_info);
495+
btf_info.name = ptr_to_u64(btf_name);
496+
btf_info.name_len = sizeof(btf_name);
497+
err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
498+
close(btf_fd);
499+
if (err) {
500+
p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
501+
return false;
502+
}
503+
504+
return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
505+
}
506+
462507
static int do_dump(int argc, char **argv)
463508
{
464509
struct btf *btf = NULL, *base = NULL;
@@ -536,18 +581,11 @@ static int do_dump(int argc, char **argv)
536581
NEXT_ARG();
537582
} else if (is_prefix(src, "file")) {
538583
const char sysfs_prefix[] = "/sys/kernel/btf/";
539-
const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
540584

541585
if (!base_btf &&
542586
strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
543-
strcmp(*argv, sysfs_vmlinux) != 0) {
544-
base = btf__parse(sysfs_vmlinux, NULL);
545-
if (libbpf_get_error(base)) {
546-
p_err("failed to parse vmlinux BTF at '%s': %ld\n",
547-
sysfs_vmlinux, libbpf_get_error(base));
548-
base = NULL;
549-
}
550-
}
587+
strcmp(*argv, sysfs_vmlinux) != 0)
588+
base = get_vmlinux_btf_from_sysfs();
551589

552590
btf = btf__parse_split(*argv, base ?: base_btf);
553591
err = libbpf_get_error(btf);
@@ -591,6 +629,12 @@ static int do_dump(int argc, char **argv)
591629
}
592630

593631
if (!btf) {
632+
if (!base_btf && btf_is_kernel_module(btf_id)) {
633+
p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
634+
sysfs_vmlinux);
635+
base_btf = get_vmlinux_btf_from_sysfs();
636+
}
637+
594638
btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
595639
err = libbpf_get_error(btf);
596640
if (err) {

0 commit comments

Comments
 (0)