Message ID | 20220428111442.111805-1-larysa.zaremba@intel.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | [RESEND,bpf-next] bpftool: Use sysfs vmlinux when dumping BTF by ID | expand |
On 4/28/22 1:14 PM, Larysa Zaremba wrote: > Currently, dumping almost all BTFs specified by id requires > using the -B option to pass the base BTF. For most cases > the vmlinux BTF sysfs path should work. > > This patch simplifies dumping by ID usage by attempting to > use vmlinux BTF from sysfs, if the first try of loading BTF by ID > fails with certain conditions. > > Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com> > Reviewed-by: Alexander Lobakin <alexandr.lobakin@intel.com> > --- > tools/bpf/bpftool/btf.c | 35 ++++++++++++++++++++++++++--------- > 1 file changed, 26 insertions(+), 9 deletions(-) > > diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c > index a2c665beda87..557f65e2de5c 100644 > --- a/tools/bpf/bpftool/btf.c > +++ b/tools/bpf/bpftool/btf.c > @@ -459,6 +459,22 @@ static int dump_btf_c(const struct btf *btf, > return err; > } > > +static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; > + > +static struct btf *get_vmlinux_btf_from_sysfs(void) > +{ > + struct btf *base; > + > + base = btf__parse(sysfs_vmlinux, NULL); > + if (libbpf_get_error(base)) { > + p_err("failed to parse vmlinux BTF at '%s': %ld\n", > + sysfs_vmlinux, libbpf_get_error(base)); > + base = NULL; > + } Could we reuse libbpf's btf__load_vmlinux_btf() which probes well-known locations? > + return base; > +} > + > static int do_dump(int argc, char **argv) > { > struct btf *btf = NULL, *base = NULL; > @@ -536,18 +552,11 @@ static int do_dump(int argc, char **argv) > NEXT_ARG(); > } else if (is_prefix(src, "file")) { > const char sysfs_prefix[] = "/sys/kernel/btf/"; > - const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; > > if (!base_btf && > strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 && > - strcmp(*argv, sysfs_vmlinux) != 0) { > - base = btf__parse(sysfs_vmlinux, NULL); > - if (libbpf_get_error(base)) { > - p_err("failed to parse vmlinux BTF at '%s': %ld\n", > - sysfs_vmlinux, libbpf_get_error(base)); > - base = NULL; > - } > - } > + strcmp(*argv, sysfs_vmlinux)) > + base = get_vmlinux_btf_from_sysfs(); > > btf = btf__parse_split(*argv, base ?: base_btf); > err = libbpf_get_error(btf); > @@ -593,6 +602,14 @@ static int do_dump(int argc, char **argv) > if (!btf) { > btf = btf__load_from_kernel_by_id_split(btf_id, base_btf); > err = libbpf_get_error(btf); > + if (err == -EINVAL && !base_btf) { > + btf__free(base); > + base = get_vmlinux_btf_from_sysfs(); > + p_info("Warning: valid base BTF was not specified with -B option, falling back on standard base BTF (sysfs vmlinux)"); > + btf = btf__load_from_kernel_by_id_split(btf_id, base); > + err = libbpf_get_error(btf); > + } > + > if (err) { > p_err("get btf by id (%u): %s", btf_id, strerror(err)); > goto done; >
On Thu, Apr 28, 2022 at 8:17 AM Daniel Borkmann <daniel@iogearbox.net> wrote: > > On 4/28/22 1:14 PM, Larysa Zaremba wrote: > > Currently, dumping almost all BTFs specified by id requires > > using the -B option to pass the base BTF. For most cases > > the vmlinux BTF sysfs path should work. > > > > This patch simplifies dumping by ID usage by attempting to > > use vmlinux BTF from sysfs, if the first try of loading BTF by ID > > fails with certain conditions. > > > > Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com> > > Reviewed-by: Alexander Lobakin <alexandr.lobakin@intel.com> > > --- > > tools/bpf/bpftool/btf.c | 35 ++++++++++++++++++++++++++--------- > > 1 file changed, 26 insertions(+), 9 deletions(-) > > > > diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c > > index a2c665beda87..557f65e2de5c 100644 > > --- a/tools/bpf/bpftool/btf.c > > +++ b/tools/bpf/bpftool/btf.c > > @@ -459,6 +459,22 @@ static int dump_btf_c(const struct btf *btf, > > return err; > > } > > > > +static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; > > + > > +static struct btf *get_vmlinux_btf_from_sysfs(void) > > +{ > > + struct btf *base; > > + > > + base = btf__parse(sysfs_vmlinux, NULL); > > + if (libbpf_get_error(base)) { > > + p_err("failed to parse vmlinux BTF at '%s': %ld\n", > > + sysfs_vmlinux, libbpf_get_error(base)); > > + base = NULL; > > + } > > Could we reuse libbpf's btf__load_vmlinux_btf() which probes well-known > locations? Systems that don't have /sys/kernel/btf/vmlinux exposed definitely don't support base BTF, so there is no point in trying to find vmlinux BTF anywhere else (which is only necessary for old kernels). So I think it should be fine as is, except we shouldn't guess when base BTF is needed, it should always be for kernel module BTFs only. > > > + return base; > > +} > > + > > static int do_dump(int argc, char **argv) > > { > > struct btf *btf = NULL, *base = NULL; > > @@ -536,18 +552,11 @@ static int do_dump(int argc, char **argv) > > NEXT_ARG(); > > } else if (is_prefix(src, "file")) { > > const char sysfs_prefix[] = "/sys/kernel/btf/"; > > - const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; > > > > if (!base_btf && > > strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 && > > - strcmp(*argv, sysfs_vmlinux) != 0) { > > - base = btf__parse(sysfs_vmlinux, NULL); > > - if (libbpf_get_error(base)) { > > - p_err("failed to parse vmlinux BTF at '%s': %ld\n", > > - sysfs_vmlinux, libbpf_get_error(base)); > > - base = NULL; > > - } > > - } > > + strcmp(*argv, sysfs_vmlinux)) > > + base = get_vmlinux_btf_from_sysfs(); > > > > btf = btf__parse_split(*argv, base ?: base_btf); > > err = libbpf_get_error(btf); > > @@ -593,6 +602,14 @@ static int do_dump(int argc, char **argv) > > if (!btf) { > > btf = btf__load_from_kernel_by_id_split(btf_id, base_btf); > > err = libbpf_get_error(btf); > > + if (err == -EINVAL && !base_btf) { > > + btf__free(base); > > + base = get_vmlinux_btf_from_sysfs(); > > + p_info("Warning: valid base BTF was not specified with -B option, falling back on standard base BTF (sysfs vmlinux)"); > > + btf = btf__load_from_kernel_by_id_split(btf_id, base); > > + err = libbpf_get_error(btf); > > + } > > + > > if (err) { > > p_err("get btf by id (%u): %s", btf_id, strerror(err)); > > goto done; > > >
diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c index a2c665beda87..557f65e2de5c 100644 --- a/tools/bpf/bpftool/btf.c +++ b/tools/bpf/bpftool/btf.c @@ -459,6 +459,22 @@ static int dump_btf_c(const struct btf *btf, return err; } +static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; + +static struct btf *get_vmlinux_btf_from_sysfs(void) +{ + struct btf *base; + + base = btf__parse(sysfs_vmlinux, NULL); + if (libbpf_get_error(base)) { + p_err("failed to parse vmlinux BTF at '%s': %ld\n", + sysfs_vmlinux, libbpf_get_error(base)); + base = NULL; + } + + return base; +} + static int do_dump(int argc, char **argv) { struct btf *btf = NULL, *base = NULL; @@ -536,18 +552,11 @@ static int do_dump(int argc, char **argv) NEXT_ARG(); } else if (is_prefix(src, "file")) { const char sysfs_prefix[] = "/sys/kernel/btf/"; - const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; if (!base_btf && strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 && - strcmp(*argv, sysfs_vmlinux) != 0) { - base = btf__parse(sysfs_vmlinux, NULL); - if (libbpf_get_error(base)) { - p_err("failed to parse vmlinux BTF at '%s': %ld\n", - sysfs_vmlinux, libbpf_get_error(base)); - base = NULL; - } - } + strcmp(*argv, sysfs_vmlinux)) + base = get_vmlinux_btf_from_sysfs(); btf = btf__parse_split(*argv, base ?: base_btf); err = libbpf_get_error(btf); @@ -593,6 +602,14 @@ static int do_dump(int argc, char **argv) if (!btf) { btf = btf__load_from_kernel_by_id_split(btf_id, base_btf); err = libbpf_get_error(btf); + if (err == -EINVAL && !base_btf) { + btf__free(base); + base = get_vmlinux_btf_from_sysfs(); + p_info("Warning: valid base BTF was not specified with -B option, falling back on standard base BTF (sysfs vmlinux)"); + btf = btf__load_from_kernel_by_id_split(btf_id, base); + err = libbpf_get_error(btf); + } + if (err) { p_err("get btf by id (%u): %s", btf_id, strerror(err)); goto done;