From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx> In systems where BTF isn't available there were reports that the simplest pahole call, without any args, segfaults. To have a proper test before fixing this problem, allow overriding the /sys/kernel/btf/vmlinux filename, so that even in systems with BTF we an point it to a invalid location, making pahole think that there is no BTF available and thus fallback to something that currently segfaults. Using it: $ pahole list_head struct list_head { struct list_head * next; /* 0 8 */ struct list_head * prev; /* 8 8 */ /* size: 16, cachelines: 1, members: 2 */ /* last cacheline: 16 bytes */ }; $ $ PAHOLE_VMLINUX_BTF_FILENAME=foobar pahole list_head Segmentation fault (core dumped) $ Reported-by: Matthias Schwarzott <zzam@xxxxxxxxxx> Cc: Alan Maguire <alan.maguire@xxxxxxxxxx> Cc: Andrii Nakryiko <andrii@xxxxxxxxxx> Cc: Eduard Zingerman <eddyz87@xxxxxxxxx> Cc: Jiri Olsa <jolsa@xxxxxxxxxx> Cc: Song Liu <song@xxxxxxxxxx> Cc: Yonghong Song <yonghong.song@xxxxxxxxx> Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx> --- dwarves.c | 17 +++++++++++++++-- dwarves.h | 2 ++ man-pages/pahole.1 | 4 ++++ pahole.c | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/dwarves.c b/dwarves.c index 14ba4f0c6dd7f90f..5b51b55191177e21 100644 --- a/dwarves.c +++ b/dwarves.c @@ -2807,6 +2807,19 @@ static int filename__sprintf_build_id(const char *pathname, char *sbuild_id) static int vmlinux_path__nr_entries; static char **vmlinux_path; +const char *vmlinux_path__btf_filename(void) +{ + static const char *vmlinux_btf; + + if (vmlinux_btf == NULL) { + vmlinux_btf = getenv("PAHOLE_VMLINUX_BTF_FILENAME"); + if (vmlinux_btf == NULL) + vmlinux_btf = "/sys/kernel/btf/vmlinux"; + } + + return vmlinux_btf; +} + static void vmlinux_path__exit(void) { while (--vmlinux_path__nr_entries >= 0) @@ -2933,7 +2946,7 @@ static int cus__load_running_kernel(struct cus *cus, struct conf_load *conf) int err = 0; if ((!conf || conf->format_path == NULL || strncmp(conf->format_path, "btf", 3) == 0) && - access("/sys/kernel/btf/vmlinux", R_OK) == 0) { + access(vmlinux_path__btf_filename(), R_OK) == 0) { int loader = debugging_formats__loader("btf"); if (loader == -1) goto try_elf; @@ -2941,7 +2954,7 @@ static int cus__load_running_kernel(struct cus *cus, struct conf_load *conf) if (conf && conf->conf_fprintf) conf->conf_fprintf->has_alignment_info = debug_fmt_table[loader]->has_alignment_info; - if (debug_fmt_table[loader]->load_file(cus, conf, "/sys/kernel/btf/vmlinux") == 0) + if (debug_fmt_table[loader]->load_file(cus, conf, vmlinux_path__btf_filename()) == 0) return 0; } try_elf: diff --git a/dwarves.h b/dwarves.h index 49988f1cf9d45be8..1cb0d629f5265523 100644 --- a/dwarves.h +++ b/dwarves.h @@ -1628,6 +1628,8 @@ void dwarves__resolve_cacheline_size(const struct conf_load *conf, uint16_t user const char *dwarf_tag_name(const uint32_t tag); +const char *vmlinux_path__btf_filename(void); + const char *vmlinux_path__find_running_kernel(void); struct argp_state; diff --git a/man-pages/pahole.1 b/man-pages/pahole.1 index bd28259b65429acc..39e7b465c64e7e2c 100644 --- a/man-pages/pahole.1 +++ b/man-pages/pahole.1 @@ -75,6 +75,10 @@ struct list_head { }; $ .fi +It is possible to override the /sys/kernel/btf/vmlinux file location by setting +the PAHOLE_VMLINUX_BTF_FILENAME environment variable. This may be useful for +testing, scripting when using a different BTF for vmlinux. Used in the pahole +regression tests. If BTF is not present and no file is passed, then a vmlinux that matches the build-id for the running kernel will be looked up in the usual places, diff --git a/pahole.c b/pahole.c index 55d04cf82a3da683..b94cb1a979a6923d 100644 --- a/pahole.c +++ b/pahole.c @@ -3754,7 +3754,7 @@ try_sole_arg_as_class_names: if (filename && strstarts(filename, "/sys/kernel/btf/") && strstr(filename, "/vmlinux") == NULL) { - base_btf_file = "/sys/kernel/btf/vmlinux"; + base_btf_file = vmlinux_path__btf_filename(); conf_load.base_btf = btf__parse(base_btf_file, NULL); if (libbpf_get_error(conf_load.base_btf)) { fprintf(stderr, "Failed to parse base BTF '%s': %ld\n", -- 2.47.0