Commit 5dc7a8b2 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov

bpftool, selftests/bpf: Embed object file inside skeleton

Embed contents of BPF object file used for BPF skeleton generation inside
skeleton itself. This allows to keep BPF object file and its skeleton in sync
at all times, and simpifies skeleton instantiation.

Also switch existing selftests to not require BPF_EMBED_OBJ anymore.
Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20191218052552.2915188-2-andriin@fb.com
parent 4a3d6c6a
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <libbpf.h> #include <libbpf.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#include "btf.h" #include "btf.h"
...@@ -261,14 +262,16 @@ static int codegen(const char *template, ...) ...@@ -261,14 +262,16 @@ static int codegen(const char *template, ...)
static int do_skeleton(int argc, char **argv) static int do_skeleton(int argc, char **argv)
{ {
char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")]; char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
size_t i, map_cnt = 0, prog_cnt = 0; size_t i, map_cnt = 0, prog_cnt = 0, file_sz, mmap_sz;
char obj_name[MAX_OBJ_NAME_LEN]; DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
char obj_name[MAX_OBJ_NAME_LEN], *obj_data;
struct bpf_object *obj = NULL;
const char *file, *ident; const char *file, *ident;
struct bpf_program *prog; struct bpf_program *prog;
struct bpf_object *obj; int fd, len, err = -1;
struct bpf_map *map; struct bpf_map *map;
struct btf *btf; struct btf *btf;
int err = -1; struct stat st;
if (!REQ_ARGS(1)) { if (!REQ_ARGS(1)) {
usage(); usage();
...@@ -281,14 +284,31 @@ static int do_skeleton(int argc, char **argv) ...@@ -281,14 +284,31 @@ static int do_skeleton(int argc, char **argv)
return -1; return -1;
} }
obj = bpf_object__open_file(file, NULL); if (stat(file, &st)) {
if (IS_ERR(obj)) { p_err("failed to stat() %s: %s", file, strerror(errno));
p_err("failed to open BPF object file: %ld", PTR_ERR(obj));
return -1; return -1;
} }
file_sz = st.st_size;
mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
fd = open(file, O_RDONLY);
if (fd < 0) {
p_err("failed to open() %s: %s", file, strerror(errno));
return -1;
}
obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
if (obj_data == MAP_FAILED) {
obj_data = NULL;
p_err("failed to mmap() %s: %s", file, strerror(errno));
goto out;
}
get_obj_name(obj_name, file); get_obj_name(obj_name, file);
get_header_guard(header_guard, obj_name); opts.object_name = obj_name;
obj = bpf_object__open_mem(obj_data, file_sz, &opts);
if (IS_ERR(obj)) {
obj = NULL;
p_err("failed to open BPF object file: %ld", PTR_ERR(obj));
goto out;
}
bpf_object__for_each_map(map, obj) { bpf_object__for_each_map(map, obj) {
ident = get_map_ident(map); ident = get_map_ident(map);
...@@ -303,8 +323,11 @@ static int do_skeleton(int argc, char **argv) ...@@ -303,8 +323,11 @@ static int do_skeleton(int argc, char **argv)
prog_cnt++; prog_cnt++;
} }
get_header_guard(header_guard, obj_name);
codegen("\ codegen("\
\n\ \n\
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ \n\
\n\
/* THIS FILE IS AUTOGENERATED! */ \n\ /* THIS FILE IS AUTOGENERATED! */ \n\
#ifndef %2$s \n\ #ifndef %2$s \n\
#define %2$s \n\ #define %2$s \n\
...@@ -356,19 +379,95 @@ static int do_skeleton(int argc, char **argv) ...@@ -356,19 +379,95 @@ static int do_skeleton(int argc, char **argv)
\n\ \n\
}; \n\ }; \n\
\n\ \n\
static inline struct bpf_object_skeleton * \n\ static void \n\
%1$s__create_skeleton(struct %1$s *obj, struct bpf_embed_data *embed)\n\ %1$s__destroy(struct %1$s *obj) \n\
{ \n\
if (!obj) \n\
return; \n\
if (obj->skeleton) \n\
bpf_object__destroy_skeleton(obj->skeleton);\n\
free(obj); \n\
} \n\
\n\
static inline int \n\
%1$s__create_skeleton(struct %1$s *obj); \n\
\n\
static inline struct %1$s * \n\
%1$s__open_opts(const struct bpf_object_open_opts *opts) \n\
{ \n\
struct %1$s *obj; \n\
\n\
obj = calloc(1, sizeof(*obj)); \n\
if (!obj) \n\
return NULL; \n\
if (%1$s__create_skeleton(obj)) \n\
goto err; \n\
if (bpf_object__open_skeleton(obj->skeleton, opts)) \n\
goto err; \n\
\n\
return obj; \n\
err: \n\
%1$s__destroy(obj); \n\
return NULL; \n\
} \n\
\n\
static inline struct %1$s * \n\
%1$s__open(void) \n\
{ \n\
return %1$s__open_opts(NULL); \n\
} \n\
\n\
static inline int \n\
%1$s__load(struct %1$s *obj) \n\
{ \n\
return bpf_object__load_skeleton(obj->skeleton); \n\
} \n\
\n\
static inline struct %1$s * \n\
%1$s__open_and_load(void) \n\
{ \n\
struct %1$s *obj; \n\
\n\
obj = %1$s__open(); \n\
if (!obj) \n\
return NULL; \n\
if (%1$s__load(obj)) { \n\
%1$s__destroy(obj); \n\
return NULL; \n\
} \n\
return obj; \n\
} \n\
\n\
static inline int \n\
%1$s__attach(struct %1$s *obj) \n\
{ \n\
return bpf_object__attach_skeleton(obj->skeleton); \n\
} \n\
\n\
static inline void \n\
%1$s__detach(struct %1$s *obj) \n\
{ \n\
return bpf_object__detach_skeleton(obj->skeleton); \n\
} \n\
",
obj_name
);
codegen("\
\n\
\n\
static inline int \n\
%1$s__create_skeleton(struct %1$s *obj) \n\
{ \n\ { \n\
struct bpf_object_skeleton *s; \n\ struct bpf_object_skeleton *s; \n\
\n\ \n\
s = calloc(1, sizeof(*s)); \n\ s = calloc(1, sizeof(*s)); \n\
if (!s) \n\ if (!s) \n\
return NULL; \n\ return -1; \n\
obj->skeleton = s; \n\
\n\ \n\
s->sz = sizeof(*s); \n\ s->sz = sizeof(*s); \n\
s->name = \"%1$s\"; \n\ s->name = \"%1$s\"; \n\
s->data = embed->data; \n\
s->data_sz = embed->size; \n\
s->obj = &obj->obj; \n\ s->obj = &obj->obj; \n\
", ",
obj_name obj_name
...@@ -438,90 +537,45 @@ static int do_skeleton(int argc, char **argv) ...@@ -438,90 +537,45 @@ static int do_skeleton(int argc, char **argv)
codegen("\ codegen("\
\n\ \n\
\n\ \n\
return s; \n\ s->data_sz = %d; \n\
err: \n\ s->data = \"\\ \n\
bpf_object__destroy_skeleton(s); \n\ ",
return NULL; \n\ file_sz);
} \n\
\n\ /* embed contents of BPF object file */
static void \n\ for (i = 0, len = 0; i < file_sz; i++) {
%1$s__destroy(struct %1$s *obj) \n\ int w = obj_data[i] ? 4 : 2;
{ \n\
if (!obj) \n\ len += w;
return; \n\ if (len > 78) {
if (obj->skeleton) \n\ printf("\\\n");
bpf_object__destroy_skeleton(obj->skeleton);\n\ len = w;
free(obj); \n\ }
} \n\ if (!obj_data[i])
\n\ printf("\\0");
static inline struct %1$s * \n\ else
%1$s__open_opts(struct bpf_embed_data *embed, const struct bpf_object_open_opts *opts)\n\ printf("\\x%02x", (unsigned char)obj_data[i]);
{ \n\ }
struct %1$s *obj; \n\
\n\ codegen("\
obj = calloc(1, sizeof(*obj)); \n\ \n\
if (!obj) \n\ \"; \n\
return NULL; \n\
\n\
obj->skeleton = %1$s__create_skeleton(obj, embed); \n\
if (!obj->skeleton) \n\
goto err; \n\
\n\
if (bpf_object__open_skeleton(obj->skeleton, opts)) \n\
goto err; \n\
\n\ \n\
return obj; \n\ return 0; \n\
err: \n\ err: \n\
%1$s__destroy(obj); \n\ bpf_object__destroy_skeleton(s); \n\
return NULL; \n\ return -1; \n\
} \n\
\n\
static inline struct %1$s * \n\
%1$s__open(struct bpf_embed_data *embed) \n\
{ \n\
return %1$s__open_opts(embed, NULL); \n\
} \n\
\n\
static inline int \n\
%1$s__load(struct %1$s *obj) \n\
{ \n\
return bpf_object__load_skeleton(obj->skeleton); \n\
} \n\
\n\
static inline struct %1$s * \n\
%1$s__open_and_load(struct bpf_embed_data *embed) \n\
{ \n\
struct %1$s *obj; \n\
\n\
obj = %1$s__open(embed); \n\
if (!obj) \n\
return NULL; \n\
if (%1$s__load(obj)) { \n\
%1$s__destroy(obj); \n\
return NULL; \n\
} \n\
return obj; \n\
} \n\
\n\
static inline int \n\
%1$s__attach(struct %1$s *obj) \n\
{ \n\
return bpf_object__attach_skeleton(obj->skeleton); \n\
} \n\
\n\
static inline void \n\
%1$s__detach(struct %1$s *obj) \n\
{ \n\
return bpf_object__detach_skeleton(obj->skeleton); \n\
} \n\ } \n\
\n\ \n\
#endif /* %2$s */ \n\ #endif /* %2$s */ \n\
", ",
obj_name, header_guard obj_name, header_guard);
);
err = 0; err = 0;
out: out:
bpf_object__close(obj); bpf_object__close(obj);
if (obj_data)
munmap(obj_data, mmap_sz);
close(fd);
return err; return err;
} }
......
...@@ -22,8 +22,6 @@ ssize_t get_base_addr() { ...@@ -22,8 +22,6 @@ ssize_t get_base_addr() {
return -EINVAL; return -EINVAL;
} }
BPF_EMBED_OBJ(probe, "test_attach_probe.o");
void test_attach_probe(void) void test_attach_probe(void)
{ {
int duration = 0; int duration = 0;
...@@ -39,7 +37,7 @@ void test_attach_probe(void) ...@@ -39,7 +37,7 @@ void test_attach_probe(void)
return; return;
uprobe_offset = (size_t)&get_base_addr - base_addr; uprobe_offset = (size_t)&get_base_addr - base_addr;
skel = test_attach_probe__open_and_load(&probe_embed); skel = test_attach_probe__open_and_load();
if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
return; return;
if (CHECK(!skel->bss, "check_bss", ".bss wasn't mmap()-ed\n")) if (CHECK(!skel->bss, "check_bss", ".bss wasn't mmap()-ed\n"))
......
...@@ -124,8 +124,6 @@ static struct test_case { ...@@ -124,8 +124,6 @@ static struct test_case {
{ .name = "u64 (max+1)", .fails = 1, .cfg = CFG"CONFIG_ULONG=0x10000000000000000" }, { .name = "u64 (max+1)", .fails = 1, .cfg = CFG"CONFIG_ULONG=0x10000000000000000" },
}; };
BPF_EMBED_OBJ(core_extern, "test_core_extern.o");
void test_core_extern(void) void test_core_extern(void)
{ {
const uint32_t kern_ver = get_kernel_version(); const uint32_t kern_ver = get_kernel_version();
...@@ -159,7 +157,7 @@ void test_core_extern(void) ...@@ -159,7 +157,7 @@ void test_core_extern(void)
opts.kconfig_path = tmp_cfg_path; opts.kconfig_path = tmp_cfg_path;
} }
skel = test_core_extern__open_opts(&core_extern_embed, &opts); skel = test_core_extern__open_opts(&opts);
if (CHECK(!skel, "skel_open", "skeleton open failed\n")) if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
goto cleanup; goto cleanup;
err = test_core_extern__load(skel); err = test_core_extern__load(skel);
......
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
#include "fentry_test.skel.h" #include "fentry_test.skel.h"
#include "fexit_test.skel.h" #include "fexit_test.skel.h"
BPF_EMBED_OBJ(pkt_access, "test_pkt_access.o");
BPF_EMBED_OBJ(fentry, "fentry_test.o");
BPF_EMBED_OBJ(fexit, "fexit_test.o");
void test_fentry_fexit(void) void test_fentry_fexit(void)
{ {
struct test_pkt_access *pkt_skel = NULL; struct test_pkt_access *pkt_skel = NULL;
...@@ -18,13 +14,13 @@ void test_fentry_fexit(void) ...@@ -18,13 +14,13 @@ void test_fentry_fexit(void)
__u32 duration = 0, retval; __u32 duration = 0, retval;
int err, pkt_fd, i; int err, pkt_fd, i;
pkt_skel = test_pkt_access__open_and_load(&pkt_access_embed); pkt_skel = test_pkt_access__open_and_load();
if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n")) if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n"))
return; return;
fentry_skel = fentry_test__open_and_load(&fentry_embed); fentry_skel = fentry_test__open_and_load();
if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n")) if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
goto close_prog; goto close_prog;
fexit_skel = fexit_test__open_and_load(&fexit_embed); fexit_skel = fexit_test__open_and_load();
if (CHECK(!fexit_skel, "fexit_skel_load", "fexit skeleton failed\n")) if (CHECK(!fexit_skel, "fexit_skel_load", "fexit skeleton failed\n"))
goto close_prog; goto close_prog;
......
...@@ -4,9 +4,6 @@ ...@@ -4,9 +4,6 @@
#include "test_pkt_access.skel.h" #include "test_pkt_access.skel.h"
#include "fentry_test.skel.h" #include "fentry_test.skel.h"
BPF_EMBED_OBJ_DECLARE(pkt_access);
BPF_EMBED_OBJ_DECLARE(fentry);
void test_fentry_test(void) void test_fentry_test(void)
{ {
struct test_pkt_access *pkt_skel = NULL; struct test_pkt_access *pkt_skel = NULL;
...@@ -15,10 +12,10 @@ void test_fentry_test(void) ...@@ -15,10 +12,10 @@ void test_fentry_test(void)
__u32 duration, retval; __u32 duration, retval;
__u64 *result; __u64 *result;
pkt_skel = test_pkt_access__open_and_load(&pkt_access_embed); pkt_skel = test_pkt_access__open_and_load();
if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n")) if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n"))
return; return;
fentry_skel = fentry_test__open_and_load(&fentry_embed); fentry_skel = fentry_test__open_and_load();
if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n")) if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
goto cleanup; goto cleanup;
......
...@@ -13,8 +13,6 @@ static size_t roundup_page(size_t sz) ...@@ -13,8 +13,6 @@ static size_t roundup_page(size_t sz)
return (sz + page_size - 1) / page_size * page_size; return (sz + page_size - 1) / page_size * page_size;
} }
BPF_EMBED_OBJ(test_mmap, "test_mmap.o");
void test_mmap(void) void test_mmap(void)
{ {
const size_t bss_sz = roundup_page(sizeof(struct test_mmap__bss)); const size_t bss_sz = roundup_page(sizeof(struct test_mmap__bss));
...@@ -30,7 +28,7 @@ void test_mmap(void) ...@@ -30,7 +28,7 @@ void test_mmap(void)
__u64 val = 0; __u64 val = 0;
skel = test_mmap__open_and_load(&test_mmap_embed); skel = test_mmap__open_and_load();
if (CHECK(!skel, "skel_open_and_load", "skeleton open/load failed\n")) if (CHECK(!skel, "skel_open_and_load", "skeleton open/load failed\n"))
return; return;
......
...@@ -10,8 +10,6 @@ struct s { ...@@ -10,8 +10,6 @@ struct s {
#include "test_skeleton.skel.h" #include "test_skeleton.skel.h"
BPF_EMBED_OBJ(skeleton, "test_skeleton.o");
void test_skeleton(void) void test_skeleton(void)
{ {
int duration = 0, err; int duration = 0, err;
...@@ -19,7 +17,7 @@ void test_skeleton(void) ...@@ -19,7 +17,7 @@ void test_skeleton(void)
struct test_skeleton__bss *bss; struct test_skeleton__bss *bss;
struct test_skeleton__externs *exts; struct test_skeleton__externs *exts;
skel = test_skeleton__open(&skeleton_embed); skel = test_skeleton__open();
if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
return; return;
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
#include <test_progs.h> #include <test_progs.h>
#include "test_stacktrace_build_id.skel.h" #include "test_stacktrace_build_id.skel.h"
BPF_EMBED_OBJ(stacktrace_build_id, "test_stacktrace_build_id.o");
void test_stacktrace_build_id(void) void test_stacktrace_build_id(void)
{ {
...@@ -18,7 +16,7 @@ void test_stacktrace_build_id(void) ...@@ -18,7 +16,7 @@ void test_stacktrace_build_id(void)
int retry = 1; int retry = 1;
retry: retry:
skel = test_stacktrace_build_id__open_and_load(&stacktrace_build_id_embed); skel = test_stacktrace_build_id__open_and_load();
if (CHECK(!skel, "skel_open_and_load", "skeleton open/load failed\n")) if (CHECK(!skel, "skel_open_and_load", "skeleton open/load failed\n"))
return; return;
......
...@@ -15,8 +15,6 @@ static __u64 read_perf_max_sample_freq(void) ...@@ -15,8 +15,6 @@ static __u64 read_perf_max_sample_freq(void)
return sample_freq; return sample_freq;
} }
BPF_EMBED_OBJ_DECLARE(stacktrace_build_id);
void test_stacktrace_build_id_nmi(void) void test_stacktrace_build_id_nmi(void)
{ {
int control_map_fd, stackid_hmap_fd, stackmap_fd; int control_map_fd, stackid_hmap_fd, stackmap_fd;
...@@ -37,7 +35,7 @@ void test_stacktrace_build_id_nmi(void) ...@@ -37,7 +35,7 @@ void test_stacktrace_build_id_nmi(void)
attr.sample_freq = read_perf_max_sample_freq(); attr.sample_freq = read_perf_max_sample_freq();
retry: retry:
skel = test_stacktrace_build_id__open(&stacktrace_build_id_embed); skel = test_stacktrace_build_id__open();
if (CHECK(!skel, "skel_open", "skeleton open failed\n")) if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment