The bpftool interface stays the same, but now it's possible to run it over BTF raw data, like: $ bpftool btf dump file /sys/kernel/btf/vmlinux [1] INT '(anon)' size=4 bits_offset=0 nr_bits=32 encoding=(none) [2] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none) [3] CONST '(anon)' type_id=2 Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx> --- v3 changes: - fix title v2 changes: - added is_btf_raw to find out which btf__parse_* function to call - changed labels and error propagation in btf__parse_raw - drop the err initialization, which is not needed under this change tools/bpf/bpftool/btf.c | 57 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c index 9a9376d1d3df..a7b8bf233cf5 100644 --- a/tools/bpf/bpftool/btf.c +++ b/tools/bpf/bpftool/btf.c @@ -12,6 +12,9 @@ #include <libbpf.h> #include <linux/btf.h> #include <linux/hashtable.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include "btf.h" #include "json_writer.h" @@ -388,6 +391,54 @@ static int dump_btf_c(const struct btf *btf, return err; } +static struct btf *btf__parse_raw(const char *file) +{ + struct btf *btf; + struct stat st; + __u8 *buf; + FILE *f; + + if (stat(file, &st)) + return NULL; + + f = fopen(file, "rb"); + if (!f) + return NULL; + + buf = malloc(st.st_size); + if (!buf) { + btf = ERR_PTR(-ENOMEM); + goto exit_close; + } + + if ((size_t) st.st_size != fread(buf, 1, st.st_size, f)) { + btf = ERR_PTR(-EINVAL); + goto exit_free; + } + + btf = btf__new(buf, st.st_size); + +exit_free: + free(buf); +exit_close: + fclose(f); + return btf; +} + +static bool is_btf_raw(const char *file) +{ + __u16 magic = 0; + int fd; + + fd = open(file, O_RDONLY); + if (fd < 0) + return false; + + read(fd, &magic, sizeof(magic)); + close(fd); + return magic == BTF_MAGIC; +} + static int do_dump(int argc, char **argv) { struct btf *btf = NULL; @@ -465,7 +516,11 @@ static int do_dump(int argc, char **argv) } NEXT_ARG(); } else if (is_prefix(src, "file")) { - btf = btf__parse_elf(*argv, NULL); + if (is_btf_raw(*argv)) + btf = btf__parse_raw(*argv); + else + btf = btf__parse_elf(*argv, NULL); + if (IS_ERR(btf)) { err = PTR_ERR(btf); btf = NULL; -- 2.21.0