#include <libbpf.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include <unistd.h>
#include "btf.h"
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();
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);
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\
\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
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;
}