The skeleton generated by `bpftool` makes it easy to attach and load bpf objects as a whole. Some BPF programs are not directly portable across kernel versions, though, and require some cherry-picking on which programs to load/attach. The skeleton makes this cherry-picking possible, but not entirely friendly in some cases. For example, an useful feature is `attach_with_fallback` so that one program can be attempted, and fallback programs tried subsequently until one works (think `tcp_recvmsg` interface changing on kernel 5.19). Being able to represent a set of probes programatically in a way that is both descriptive, compile-time validated, runtime efficient and custom library friendly is quite desirable for application developers. A very simple way to represent a set of probes is with an array of indices. This patch creates a couple of enums under the `__cplusplus` section to represent the program and map indices inside the skeleton object, that can be used to refer to the proper program/map object. This is the code generated for the `__cplusplus` section of `profiler.skel.h`: ``` enum map_idxs: size_t { events = 0, fentry_readings = 1, accum_readings = 2, counts = 3, rodata = 4 }; enum prog_idxs: size_t { fentry_XXX = 0, fexit_XXX = 1 }; static inline struct profiler_bpf *open(const struct bpf_object_open_opts *opts = nullptr); static inline struct profiler_bpf *open_and_load(); static inline int load(struct profiler_bpf *skel); static inline int attach(struct profiler_bpf *skel); static inline void detach(struct profiler_bpf *skel); static inline void destroy(struct profiler_bpf *skel); static inline const void *elf_bytes(size_t *sz); ``` --- src/gen.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/gen.c b/src/gen.c index 7070dcf..7e28dc7 100644 --- a/src/gen.c +++ b/src/gen.c @@ -1086,6 +1086,38 @@ static int do_skeleton(int argc, char **argv) \n\ \n\ #ifdef __cplusplus \n\ + " + ); + + { + size_t i = 0; + printf("\tenum map_index: size_t {"); + bpf_object__for_each_map(map, obj) { + if (!get_map_ident(map, ident, sizeof(ident))) + continue; + if (i) { + printf(","); + } + printf("\n\t\t%s = %lu", ident, i); + ++i; + } + printf("\n\t};\n"); + } + { + size_t i = 0; + printf("\tenum prog_index: size_t {"); + bpf_object__for_each_program(prog, obj) { + if (i) { + printf(","); + } + printf("\n\t\t%s = %lu", bpf_program__name(prog), i); + ++i; + } + printf("\n\t};\n"); + } + + codegen("\ + \n\ static inline struct %1$s *open(const struct bpf_object_open_opts *opts = nullptr);\n\ static inline struct %1$s *open_and_load(); \n\ static inline int load(struct %1$s *skel); \n\ -- 2.37.2