Skip to content

Commit 5dc7a8b

Browse files
anakryikoAlexei Starovoitov
authored and
Alexei Starovoitov
committed
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: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 4a3d6c6 commit 5dc7a8b

File tree

9 files changed

+154
-119
lines changed

9 files changed

+154
-119
lines changed

tools/bpf/bpftool/gen.c

Lines changed: 143 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <libbpf.h>
1717
#include <sys/types.h>
1818
#include <sys/stat.h>
19+
#include <sys/mman.h>
1920
#include <unistd.h>
2021

2122
#include "btf.h"
@@ -261,14 +262,16 @@ static int codegen(const char *template, ...)
261262
static int do_skeleton(int argc, char **argv)
262263
{
263264
char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
264-
size_t i, map_cnt = 0, prog_cnt = 0;
265-
char obj_name[MAX_OBJ_NAME_LEN];
265+
size_t i, map_cnt = 0, prog_cnt = 0, file_sz, mmap_sz;
266+
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
267+
char obj_name[MAX_OBJ_NAME_LEN], *obj_data;
268+
struct bpf_object *obj = NULL;
266269
const char *file, *ident;
267270
struct bpf_program *prog;
268-
struct bpf_object *obj;
271+
int fd, len, err = -1;
269272
struct bpf_map *map;
270273
struct btf *btf;
271-
int err = -1;
274+
struct stat st;
272275

273276
if (!REQ_ARGS(1)) {
274277
usage();
@@ -281,14 +284,31 @@ static int do_skeleton(int argc, char **argv)
281284
return -1;
282285
}
283286

284-
obj = bpf_object__open_file(file, NULL);
285-
if (IS_ERR(obj)) {
286-
p_err("failed to open BPF object file: %ld", PTR_ERR(obj));
287+
if (stat(file, &st)) {
288+
p_err("failed to stat() %s: %s", file, strerror(errno));
287289
return -1;
288290
}
289-
291+
file_sz = st.st_size;
292+
mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
293+
fd = open(file, O_RDONLY);
294+
if (fd < 0) {
295+
p_err("failed to open() %s: %s", file, strerror(errno));
296+
return -1;
297+
}
298+
obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
299+
if (obj_data == MAP_FAILED) {
300+
obj_data = NULL;
301+
p_err("failed to mmap() %s: %s", file, strerror(errno));
302+
goto out;
303+
}
290304
get_obj_name(obj_name, file);
291-
get_header_guard(header_guard, obj_name);
305+
opts.object_name = obj_name;
306+
obj = bpf_object__open_mem(obj_data, file_sz, &opts);
307+
if (IS_ERR(obj)) {
308+
obj = NULL;
309+
p_err("failed to open BPF object file: %ld", PTR_ERR(obj));
310+
goto out;
311+
}
292312

293313
bpf_object__for_each_map(map, obj) {
294314
ident = get_map_ident(map);
@@ -303,8 +323,11 @@ static int do_skeleton(int argc, char **argv)
303323
prog_cnt++;
304324
}
305325

326+
get_header_guard(header_guard, obj_name);
306327
codegen("\
307328
\n\
329+
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ \n\
330+
\n\
308331
/* THIS FILE IS AUTOGENERATED! */ \n\
309332
#ifndef %2$s \n\
310333
#define %2$s \n\
@@ -356,19 +379,95 @@ static int do_skeleton(int argc, char **argv)
356379
\n\
357380
}; \n\
358381
\n\
359-
static inline struct bpf_object_skeleton * \n\
360-
%1$s__create_skeleton(struct %1$s *obj, struct bpf_embed_data *embed)\n\
382+
static void \n\
383+
%1$s__destroy(struct %1$s *obj) \n\
384+
{ \n\
385+
if (!obj) \n\
386+
return; \n\
387+
if (obj->skeleton) \n\
388+
bpf_object__destroy_skeleton(obj->skeleton);\n\
389+
free(obj); \n\
390+
} \n\
391+
\n\
392+
static inline int \n\
393+
%1$s__create_skeleton(struct %1$s *obj); \n\
394+
\n\
395+
static inline struct %1$s * \n\
396+
%1$s__open_opts(const struct bpf_object_open_opts *opts) \n\
397+
{ \n\
398+
struct %1$s *obj; \n\
399+
\n\
400+
obj = calloc(1, sizeof(*obj)); \n\
401+
if (!obj) \n\
402+
return NULL; \n\
403+
if (%1$s__create_skeleton(obj)) \n\
404+
goto err; \n\
405+
if (bpf_object__open_skeleton(obj->skeleton, opts)) \n\
406+
goto err; \n\
407+
\n\
408+
return obj; \n\
409+
err: \n\
410+
%1$s__destroy(obj); \n\
411+
return NULL; \n\
412+
} \n\
413+
\n\
414+
static inline struct %1$s * \n\
415+
%1$s__open(void) \n\
416+
{ \n\
417+
return %1$s__open_opts(NULL); \n\
418+
} \n\
419+
\n\
420+
static inline int \n\
421+
%1$s__load(struct %1$s *obj) \n\
422+
{ \n\
423+
return bpf_object__load_skeleton(obj->skeleton); \n\
424+
} \n\
425+
\n\
426+
static inline struct %1$s * \n\
427+
%1$s__open_and_load(void) \n\
428+
{ \n\
429+
struct %1$s *obj; \n\
430+
\n\
431+
obj = %1$s__open(); \n\
432+
if (!obj) \n\
433+
return NULL; \n\
434+
if (%1$s__load(obj)) { \n\
435+
%1$s__destroy(obj); \n\
436+
return NULL; \n\
437+
} \n\
438+
return obj; \n\
439+
} \n\
440+
\n\
441+
static inline int \n\
442+
%1$s__attach(struct %1$s *obj) \n\
443+
{ \n\
444+
return bpf_object__attach_skeleton(obj->skeleton); \n\
445+
} \n\
446+
\n\
447+
static inline void \n\
448+
%1$s__detach(struct %1$s *obj) \n\
449+
{ \n\
450+
return bpf_object__detach_skeleton(obj->skeleton); \n\
451+
} \n\
452+
",
453+
obj_name
454+
);
455+
456+
codegen("\
457+
\n\
458+
\n\
459+
static inline int \n\
460+
%1$s__create_skeleton(struct %1$s *obj) \n\
361461
{ \n\
362462
struct bpf_object_skeleton *s; \n\
363463
\n\
364464
s = calloc(1, sizeof(*s)); \n\
365465
if (!s) \n\
366-
return NULL; \n\
466+
return -1; \n\
467+
obj->skeleton = s; \n\
367468
\n\
368469
s->sz = sizeof(*s); \n\
369470
s->name = \"%1$s\"; \n\
370-
s->data = embed->data; \n\
371-
s->data_sz = embed->size; \n\
372471
s->obj = &obj->obj; \n\
373472
",
374473
obj_name
@@ -438,90 +537,45 @@ static int do_skeleton(int argc, char **argv)
438537
codegen("\
439538
\n\
440539
\n\
441-
return s; \n\
442-
err: \n\
443-
bpf_object__destroy_skeleton(s); \n\
444-
return NULL; \n\
445-
} \n\
446-
\n\
447-
static void \n\
448-
%1$s__destroy(struct %1$s *obj) \n\
449-
{ \n\
450-
if (!obj) \n\
451-
return; \n\
452-
if (obj->skeleton) \n\
453-
bpf_object__destroy_skeleton(obj->skeleton);\n\
454-
free(obj); \n\
455-
} \n\
456-
\n\
457-
static inline struct %1$s * \n\
458-
%1$s__open_opts(struct bpf_embed_data *embed, const struct bpf_object_open_opts *opts)\n\
459-
{ \n\
460-
struct %1$s *obj; \n\
461-
\n\
462-
obj = calloc(1, sizeof(*obj)); \n\
463-
if (!obj) \n\
464-
return NULL; \n\
465-
\n\
466-
obj->skeleton = %1$s__create_skeleton(obj, embed); \n\
467-
if (!obj->skeleton) \n\
468-
goto err; \n\
469-
\n\
470-
if (bpf_object__open_skeleton(obj->skeleton, opts)) \n\
471-
goto err; \n\
540+
s->data_sz = %d; \n\
541+
s->data = \"\\ \n\
542+
",
543+
file_sz);
544+
545+
/* embed contents of BPF object file */
546+
for (i = 0, len = 0; i < file_sz; i++) {
547+
int w = obj_data[i] ? 4 : 2;
548+
549+
len += w;
550+
if (len > 78) {
551+
printf("\\\n");
552+
len = w;
553+
}
554+
if (!obj_data[i])
555+
printf("\\0");
556+
else
557+
printf("\\x%02x", (unsigned char)obj_data[i]);
558+
}
559+
560+
codegen("\
561+
\n\
562+
\"; \n\
472563
\n\
473-
return obj; \n\
564+
return 0; \n\
474565
err: \n\
475-
%1$s__destroy(obj); \n\
476-
return NULL; \n\
477-
} \n\
478-
\n\
479-
static inline struct %1$s * \n\
480-
%1$s__open(struct bpf_embed_data *embed) \n\
481-
{ \n\
482-
return %1$s__open_opts(embed, NULL); \n\
483-
} \n\
484-
\n\
485-
static inline int \n\
486-
%1$s__load(struct %1$s *obj) \n\
487-
{ \n\
488-
return bpf_object__load_skeleton(obj->skeleton); \n\
489-
} \n\
490-
\n\
491-
static inline struct %1$s * \n\
492-
%1$s__open_and_load(struct bpf_embed_data *embed) \n\
493-
{ \n\
494-
struct %1$s *obj; \n\
495-
\n\
496-
obj = %1$s__open(embed); \n\
497-
if (!obj) \n\
498-
return NULL; \n\
499-
if (%1$s__load(obj)) { \n\
500-
%1$s__destroy(obj); \n\
501-
return NULL; \n\
502-
} \n\
503-
return obj; \n\
504-
} \n\
505-
\n\
506-
static inline int \n\
507-
%1$s__attach(struct %1$s *obj) \n\
508-
{ \n\
509-
return bpf_object__attach_skeleton(obj->skeleton); \n\
510-
} \n\
511-
\n\
512-
static inline void \n\
513-
%1$s__detach(struct %1$s *obj) \n\
514-
{ \n\
515-
return bpf_object__detach_skeleton(obj->skeleton); \n\
566+
bpf_object__destroy_skeleton(s); \n\
567+
return -1; \n\
516568
} \n\
517569
\n\
518570
#endif /* %2$s */ \n\
519571
",
520-
obj_name, header_guard
521-
);
572+
obj_name, header_guard);
522573
err = 0;
523574
out:
524575
bpf_object__close(obj);
576+
if (obj_data)
577+
munmap(obj_data, mmap_sz);
578+
close(fd);
525579
return err;
526580
}
527581

tools/testing/selftests/bpf/prog_tests/attach_probe.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ ssize_t get_base_addr() {
2222
return -EINVAL;
2323
}
2424

25-
BPF_EMBED_OBJ(probe, "test_attach_probe.o");
26-
2725
void test_attach_probe(void)
2826
{
2927
int duration = 0;
@@ -39,7 +37,7 @@ void test_attach_probe(void)
3937
return;
4038
uprobe_offset = (size_t)&get_base_addr - base_addr;
4139

42-
skel = test_attach_probe__open_and_load(&probe_embed);
40+
skel = test_attach_probe__open_and_load();
4341
if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
4442
return;
4543
if (CHECK(!skel->bss, "check_bss", ".bss wasn't mmap()-ed\n"))

tools/testing/selftests/bpf/prog_tests/core_extern.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ static struct test_case {
124124
{ .name = "u64 (max+1)", .fails = 1, .cfg = CFG"CONFIG_ULONG=0x10000000000000000" },
125125
};
126126

127-
BPF_EMBED_OBJ(core_extern, "test_core_extern.o");
128-
129127
void test_core_extern(void)
130128
{
131129
const uint32_t kern_ver = get_kernel_version();
@@ -159,7 +157,7 @@ void test_core_extern(void)
159157
opts.kconfig_path = tmp_cfg_path;
160158
}
161159

162-
skel = test_core_extern__open_opts(&core_extern_embed, &opts);
160+
skel = test_core_extern__open_opts(&opts);
163161
if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
164162
goto cleanup;
165163
err = test_core_extern__load(skel);

tools/testing/selftests/bpf/prog_tests/fentry_fexit.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
#include "fentry_test.skel.h"
66
#include "fexit_test.skel.h"
77

8-
BPF_EMBED_OBJ(pkt_access, "test_pkt_access.o");
9-
BPF_EMBED_OBJ(fentry, "fentry_test.o");
10-
BPF_EMBED_OBJ(fexit, "fexit_test.o");
11-
128
void test_fentry_fexit(void)
139
{
1410
struct test_pkt_access *pkt_skel = NULL;
@@ -18,13 +14,13 @@ void test_fentry_fexit(void)
1814
__u32 duration = 0, retval;
1915
int err, pkt_fd, i;
2016

21-
pkt_skel = test_pkt_access__open_and_load(&pkt_access_embed);
17+
pkt_skel = test_pkt_access__open_and_load();
2218
if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n"))
2319
return;
24-
fentry_skel = fentry_test__open_and_load(&fentry_embed);
20+
fentry_skel = fentry_test__open_and_load();
2521
if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
2622
goto close_prog;
27-
fexit_skel = fexit_test__open_and_load(&fexit_embed);
23+
fexit_skel = fexit_test__open_and_load();
2824
if (CHECK(!fexit_skel, "fexit_skel_load", "fexit skeleton failed\n"))
2925
goto close_prog;
3026

tools/testing/selftests/bpf/prog_tests/fentry_test.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
#include "test_pkt_access.skel.h"
55
#include "fentry_test.skel.h"
66

7-
BPF_EMBED_OBJ_DECLARE(pkt_access);
8-
BPF_EMBED_OBJ_DECLARE(fentry);
9-
107
void test_fentry_test(void)
118
{
129
struct test_pkt_access *pkt_skel = NULL;
@@ -15,10 +12,10 @@ void test_fentry_test(void)
1512
__u32 duration, retval;
1613
__u64 *result;
1714

18-
pkt_skel = test_pkt_access__open_and_load(&pkt_access_embed);
15+
pkt_skel = test_pkt_access__open_and_load();
1916
if (CHECK(!pkt_skel, "pkt_skel_load", "pkt_access skeleton failed\n"))
2017
return;
21-
fentry_skel = fentry_test__open_and_load(&fentry_embed);
18+
fentry_skel = fentry_test__open_and_load();
2219
if (CHECK(!fentry_skel, "fentry_skel_load", "fentry skeleton failed\n"))
2320
goto cleanup;
2421

0 commit comments

Comments
 (0)