Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <larysa.zaremba@intel.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Alexander Lobakin <alexandr.lobakin@intel.com>
Link: https://lore.kernel.org/bpf/20220513121743.12411-1-larysa.zaremba@intel.com

authored by

Larysa Zaremba and committed by
Andrii Nakryiko
418fbe82 16d1e00c

+53 -9
+53 -9
tools/bpf/bpftool/btf.c
··· 459 459 return err; 460 460 } 461 461 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 + 462 507 static int do_dump(int argc, char **argv) 463 508 { 464 509 struct btf *btf = NULL, *base = NULL; ··· 581 536 NEXT_ARG(); 582 537 } else if (is_prefix(src, "file")) { 583 538 const char sysfs_prefix[] = "/sys/kernel/btf/"; 584 - const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; 585 539 586 540 if (!base_btf && 587 541 strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 && 588 - strcmp(*argv, sysfs_vmlinux) != 0) { 589 - base = btf__parse(sysfs_vmlinux, NULL); 590 - if (libbpf_get_error(base)) { 591 - p_err("failed to parse vmlinux BTF at '%s': %ld\n", 592 - sysfs_vmlinux, libbpf_get_error(base)); 593 - base = NULL; 594 - } 595 - } 542 + strcmp(*argv, sysfs_vmlinux) != 0) 543 + base = get_vmlinux_btf_from_sysfs(); 596 544 597 545 btf = btf__parse_split(*argv, base ?: base_btf); 598 546 err = libbpf_get_error(btf); ··· 629 591 } 630 592 631 593 if (!btf) { 594 + if (!base_btf && btf_is_kernel_module(btf_id)) { 595 + p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)", 596 + sysfs_vmlinux); 597 + base_btf = get_vmlinux_btf_from_sysfs(); 598 + } 599 + 632 600 btf = btf__load_from_kernel_by_id_split(btf_id, base_btf); 633 601 err = libbpf_get_error(btf); 634 602 if (err) {