Skip to content

Commit

Permalink
Merge branch 'bpf-libbpf-btf-parsing'
Browse files Browse the repository at this point in the history
Andrii Nakryiko says:

====================
It's pretty common for applications to want to parse raw (binary) BTF data
from file, as opposed to parsing it from ELF sections. It's also pretty common
for tools to not care whether given file is ELF or raw BTF format. This patch
series exposes internal raw BTF parsing API and adds generic variant of BTF
parsing, which will efficiently determine the format of a given fail and will
parse BTF appropriately.

Patches #2 and #3 removes re-implementations of such APIs from bpftool and
resolve_btfids tools.
====================

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
borkmann committed Aug 3, 2020
2 parents 041549b + f86ca3c commit cfa3eb6
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 148 deletions.
54 changes: 1 addition & 53 deletions tools/bpf/bpftool/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,54 +422,6 @@ 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, nb_read;

fd = open(file, O_RDONLY);
if (fd < 0)
return false;

nb_read = read(fd, &magic, sizeof(magic));
close(fd);
return nb_read == sizeof(magic) && magic == BTF_MAGIC;
}

static int do_dump(int argc, char **argv)
{
struct btf *btf = NULL;
Expand Down Expand Up @@ -547,11 +499,7 @@ static int do_dump(int argc, char **argv)
}
NEXT_ARG();
} else if (is_prefix(src, "file")) {
if (is_btf_raw(*argv))
btf = btf__parse_raw(*argv);
else
btf = btf__parse_elf(*argv, NULL);

btf = btf__parse(*argv, NULL);
if (IS_ERR(btf)) {
err = -PTR_ERR(btf);
btf = NULL;
Expand Down
4 changes: 4 additions & 0 deletions tools/bpf/resolve_btfids/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/FEATURE-DUMP.libbpf
/bpf_helper_defs.h
/fixdep
/resolve_btfids
58 changes: 1 addition & 57 deletions tools/bpf/resolve_btfids/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,62 +403,6 @@ static int symbols_collect(struct object *obj)
return 0;
}

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, nb_read;

fd = open(file, O_RDONLY);
if (fd < 0)
return false;

nb_read = read(fd, &magic, sizeof(magic));
close(fd);
return nb_read == sizeof(magic) && magic == BTF_MAGIC;
}

static struct btf *btf_open(const char *path)
{
if (is_btf_raw(path))
return btf__parse_raw(path);
else
return btf__parse_elf(path, NULL);
}

static int symbols_resolve(struct object *obj)
{
int nr_typedefs = obj->nr_typedefs;
Expand All @@ -469,7 +413,7 @@ static int symbols_resolve(struct object *obj)
struct btf *btf;
__u32 nr;

btf = btf_open(obj->btf ?: obj->path);
btf = btf__parse(obj->btf ?: obj->path, NULL);
err = libbpf_get_error(btf);
if (err) {
pr_err("FAILED: load BTF from %s: %s",
Expand Down
114 changes: 78 additions & 36 deletions tools/lib/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,83 @@ struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
return btf;
}

struct btf *btf__parse_raw(const char *path)
{
void *data = NULL;
struct btf *btf;
FILE *f = NULL;
__u16 magic;
int err = 0;
long sz;

f = fopen(path, "rb");
if (!f) {
err = -errno;
goto err_out;
}

/* check BTF magic */
if (fread(&magic, 1, sizeof(magic), f) < sizeof(magic)) {
err = -EIO;
goto err_out;
}
if (magic != BTF_MAGIC) {
/* definitely not a raw BTF */
err = -EPROTO;
goto err_out;
}

/* get file size */
if (fseek(f, 0, SEEK_END)) {
err = -errno;
goto err_out;
}
sz = ftell(f);
if (sz < 0) {
err = -errno;
goto err_out;
}
/* rewind to the start */
if (fseek(f, 0, SEEK_SET)) {
err = -errno;
goto err_out;
}

/* pre-alloc memory and read all of BTF data */
data = malloc(sz);
if (!data) {
err = -ENOMEM;
goto err_out;
}
if (fread(data, 1, sz, f) < sz) {
err = -EIO;
goto err_out;
}

/* finally parse BTF data */
btf = btf__new(data, sz);

err_out:
free(data);
if (f)
fclose(f);
return err ? ERR_PTR(err) : btf;
}

struct btf *btf__parse(const char *path, struct btf_ext **btf_ext)
{
struct btf *btf;

if (btf_ext)
*btf_ext = NULL;

btf = btf__parse_raw(path);
if (!IS_ERR(btf) || PTR_ERR(btf) != -EPROTO)
return btf;

return btf__parse_elf(path, btf_ext);
}

static int compare_vsi_off(const void *_a, const void *_b)
{
const struct btf_var_secinfo *a = _a;
Expand Down Expand Up @@ -2951,41 +3028,6 @@ static int btf_dedup_remap_types(struct btf_dedup *d)
return 0;
}

static struct btf *btf_load_raw(const char *path)
{
struct btf *btf;
size_t read_cnt;
struct stat st;
void *data;
FILE *f;

if (stat(path, &st))
return ERR_PTR(-errno);

data = malloc(st.st_size);
if (!data)
return ERR_PTR(-ENOMEM);

f = fopen(path, "rb");
if (!f) {
btf = ERR_PTR(-errno);
goto cleanup;
}

read_cnt = fread(data, 1, st.st_size, f);
fclose(f);
if (read_cnt < st.st_size) {
btf = ERR_PTR(-EBADF);
goto cleanup;
}

btf = btf__new(data, read_cnt);

cleanup:
free(data);
return btf;
}

/*
* Probe few well-known locations for vmlinux kernel image and try to load BTF
* data out of it to use for target BTF.
Expand Down Expand Up @@ -3021,7 +3063,7 @@ struct btf *libbpf_find_kernel_btf(void)
continue;

if (locations[i].raw_btf)
btf = btf_load_raw(path);
btf = btf__parse_raw(path);
else
btf = btf__parse_elf(path, NULL);

Expand Down
5 changes: 3 additions & 2 deletions tools/lib/bpf/btf.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ struct btf_ext_header {

LIBBPF_API void btf__free(struct btf *btf);
LIBBPF_API struct btf *btf__new(const void *data, __u32 size);
LIBBPF_API struct btf *btf__parse_elf(const char *path,
struct btf_ext **btf_ext);
LIBBPF_API struct btf *btf__parse(const char *path, struct btf_ext **btf_ext);
LIBBPF_API struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext);
LIBBPF_API struct btf *btf__parse_raw(const char *path);
LIBBPF_API int btf__finalize_data(struct bpf_object *obj, struct btf *btf);
LIBBPF_API int btf__load(struct btf *btf);
LIBBPF_API __s32 btf__find_by_name(const struct btf *btf,
Expand Down
2 changes: 2 additions & 0 deletions tools/lib/bpf/libbpf.map
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,7 @@ LIBBPF_0.1.0 {
bpf_program__is_sk_lookup;
bpf_program__set_autoload;
bpf_program__set_sk_lookup;
btf__parse;
btf__parse_raw;
btf__set_fd;
} LIBBPF_0.0.9;

0 comments on commit cfa3eb6

Please sign in to comment.