summaryrefslogtreecommitdiff
path: root/tools/bpf/bpftool/gen.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2019-12-17 22:16:36 -0800
committerAlexei Starovoitov <ast@kernel.org>2019-12-17 22:16:40 -0800
commit58d8dc2a98f50d4741a49e047bd7b322d7692d0b (patch)
tree2b0baea8a420a4e6949b3ce8f7e9e374a549d186 /tools/bpf/bpftool/gen.c
parent4a3d6c6a6e4d652808729e7a2a8c3774a5a5c814 (diff)
parentcb21ac58854605e6c15fd7da2c619823967b3140 (diff)
Merge branch 'skel-fixes'
Andrii Nakryiko says: ==================== Simplify skeleton usage by embedding source BPF object file inside skeleton itself. This allows to keep skeleton and object file in sync at all times with no chance of confusion. Also, add bpftool-gen.rst manpage, explaining concepts and ideas behind skeleton. In examples section it also includes a complete small BPF application utilizing skeleton, as a demonstration of API. Patch #2 also removes BPF_EMBED_OBJ, as there is currently no use of it. v2->v3: - (void) in no-args function (Alexei); - bpftool-gen.rst code block formatting fix (Alexei); - simplified xxx__create_skeleton to fill in obj and return error code; v1->v2: - remove whitespace from empty lines in code blocks (Yonghong). ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'tools/bpf/bpftool/gen.c')
-rw-r--r--tools/bpf/bpftool/gen.c232
1 files changed, 143 insertions, 89 deletions
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index f70088b4c19b..8d93c8f90f82 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -16,6 +16,7 @@
#include <libbpf.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <unistd.h>
#include "btf.h"
@@ -261,14 +262,16 @@ static int codegen(const char *template, ...)
static int do_skeleton(int argc, char **argv)
{
char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
- size_t i, map_cnt = 0, prog_cnt = 0;
- char obj_name[MAX_OBJ_NAME_LEN];
+ size_t i, map_cnt = 0, prog_cnt = 0, file_sz, mmap_sz;
+ 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;
struct bpf_program *prog;
- struct bpf_object *obj;
+ int fd, len, err = -1;
struct bpf_map *map;
struct btf *btf;
- int err = -1;
+ struct stat st;
if (!REQ_ARGS(1)) {
usage();
@@ -281,14 +284,31 @@ static int do_skeleton(int argc, char **argv)
return -1;
}
- obj = bpf_object__open_file(file, NULL);
- if (IS_ERR(obj)) {
- p_err("failed to open BPF object file: %ld", PTR_ERR(obj));
+ if (stat(file, &st)) {
+ p_err("failed to stat() %s: %s", file, strerror(errno));
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_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) {
ident = get_map_ident(map);
@@ -303,8 +323,11 @@ static int do_skeleton(int argc, char **argv)
prog_cnt++;
}
+ get_header_guard(header_guard, obj_name);
codegen("\
\n\
+ /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ \n\
+ \n\
/* THIS FILE IS AUTOGENERATED! */ \n\
#ifndef %2$s \n\
#define %2$s \n\
@@ -356,19 +379,95 @@ static int do_skeleton(int argc, char **argv)
\n\
}; \n\
\n\
- static inline struct bpf_object_skeleton * \n\
- %1$s__create_skeleton(struct %1$s *obj, struct bpf_embed_data *embed)\n\
+ static void \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\
struct bpf_object_skeleton *s; \n\
\n\
s = calloc(1, sizeof(*s)); \n\
if (!s) \n\
- return NULL; \n\
+ return -1; \n\
+ obj->skeleton = s; \n\
\n\
s->sz = sizeof(*s); \n\
s->name = \"%1$s\"; \n\
- s->data = embed->data; \n\
- s->data_sz = embed->size; \n\
s->obj = &obj->obj; \n\
",
obj_name
@@ -438,90 +537,45 @@ static int do_skeleton(int argc, char **argv)
codegen("\
\n\
\n\
- return s; \n\
- err: \n\
- bpf_object__destroy_skeleton(s); \n\
- return NULL; \n\
- } \n\
- \n\
- static void \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 struct %1$s * \n\
- %1$s__open_opts(struct bpf_embed_data *embed, 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\
- \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\
+ s->data_sz = %d; \n\
+ s->data = \"\\ \n\
+ ",
+ file_sz);
+
+ /* embed contents of BPF object file */
+ for (i = 0, len = 0; i < file_sz; i++) {
+ int w = obj_data[i] ? 4 : 2;
+
+ len += w;
+ if (len > 78) {
+ printf("\\\n");
+ len = w;
+ }
+ if (!obj_data[i])
+ printf("\\0");
+ else
+ printf("\\x%02x", (unsigned char)obj_data[i]);
+ }
+
+ codegen("\
+ \n\
+ \"; \n\
\n\
- return obj; \n\
+ return 0; \n\
err: \n\
- %1$s__destroy(obj); \n\
- return NULL; \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\
+ bpf_object__destroy_skeleton(s); \n\
+ return -1; \n\
} \n\
\n\
#endif /* %2$s */ \n\
",
- obj_name, header_guard
- );
+ obj_name, header_guard);
err = 0;
out:
bpf_object__close(obj);
+ if (obj_data)
+ munmap(obj_data, mmap_sz);
+ close(fd);
return err;
}