Merge tag 'docs-5.15' of git://git.lwn.net/linux
[linux-2.6-microblaze.git] / tools / bpf / bpftool / gen.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2019 Facebook */
3
4 #ifndef _GNU_SOURCE
5 #define _GNU_SOURCE
6 #endif
7 #include <ctype.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <linux/err.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <bpf/bpf.h>
16 #include <bpf/libbpf.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/mman.h>
20 #include <bpf/btf.h>
21 #include <bpf/bpf_gen_internal.h>
22
23 #include "json_writer.h"
24 #include "main.h"
25
26 #define MAX_OBJ_NAME_LEN 64
27
28 static void sanitize_identifier(char *name)
29 {
30         int i;
31
32         for (i = 0; name[i]; i++)
33                 if (!isalnum(name[i]) && name[i] != '_')
34                         name[i] = '_';
35 }
36
37 static bool str_has_suffix(const char *str, const char *suffix)
38 {
39         size_t i, n1 = strlen(str), n2 = strlen(suffix);
40
41         if (n1 < n2)
42                 return false;
43
44         for (i = 0; i < n2; i++) {
45                 if (str[n1 - i - 1] != suffix[n2 - i - 1])
46                         return false;
47         }
48
49         return true;
50 }
51
52 static void get_obj_name(char *name, const char *file)
53 {
54         /* Using basename() GNU version which doesn't modify arg. */
55         strncpy(name, basename(file), MAX_OBJ_NAME_LEN - 1);
56         name[MAX_OBJ_NAME_LEN - 1] = '\0';
57         if (str_has_suffix(name, ".o"))
58                 name[strlen(name) - 2] = '\0';
59         sanitize_identifier(name);
60 }
61
62 static void get_header_guard(char *guard, const char *obj_name)
63 {
64         int i;
65
66         sprintf(guard, "__%s_SKEL_H__", obj_name);
67         for (i = 0; guard[i]; i++)
68                 guard[i] = toupper(guard[i]);
69 }
70
71 static const char *get_map_ident(const struct bpf_map *map)
72 {
73         const char *name = bpf_map__name(map);
74
75         if (!bpf_map__is_internal(map))
76                 return name;
77
78         if (str_has_suffix(name, ".data"))
79                 return "data";
80         else if (str_has_suffix(name, ".rodata"))
81                 return "rodata";
82         else if (str_has_suffix(name, ".bss"))
83                 return "bss";
84         else if (str_has_suffix(name, ".kconfig"))
85                 return "kconfig";
86         else
87                 return NULL;
88 }
89
90 static void codegen_btf_dump_printf(void *ctx, const char *fmt, va_list args)
91 {
92         vprintf(fmt, args);
93 }
94
95 static int codegen_datasec_def(struct bpf_object *obj,
96                                struct btf *btf,
97                                struct btf_dump *d,
98                                const struct btf_type *sec,
99                                const char *obj_name)
100 {
101         const char *sec_name = btf__name_by_offset(btf, sec->name_off);
102         const struct btf_var_secinfo *sec_var = btf_var_secinfos(sec);
103         int i, err, off = 0, pad_cnt = 0, vlen = btf_vlen(sec);
104         const char *sec_ident;
105         char var_ident[256];
106         bool strip_mods = false;
107
108         if (strcmp(sec_name, ".data") == 0) {
109                 sec_ident = "data";
110                 strip_mods = true;
111         } else if (strcmp(sec_name, ".bss") == 0) {
112                 sec_ident = "bss";
113                 strip_mods = true;
114         } else if (strcmp(sec_name, ".rodata") == 0) {
115                 sec_ident = "rodata";
116                 strip_mods = true;
117         } else if (strcmp(sec_name, ".kconfig") == 0) {
118                 sec_ident = "kconfig";
119         } else {
120                 return 0;
121         }
122
123         printf("        struct %s__%s {\n", obj_name, sec_ident);
124         for (i = 0; i < vlen; i++, sec_var++) {
125                 const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
126                 const char *var_name = btf__name_by_offset(btf, var->name_off);
127                 DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
128                         .field_name = var_ident,
129                         .indent_level = 2,
130                         .strip_mods = strip_mods,
131                 );
132                 int need_off = sec_var->offset, align_off, align;
133                 __u32 var_type_id = var->type;
134
135                 /* static variables are not exposed through BPF skeleton */
136                 if (btf_var(var)->linkage == BTF_VAR_STATIC)
137                         continue;
138
139                 if (off > need_off) {
140                         p_err("Something is wrong for %s's variable #%d: need offset %d, already at %d.\n",
141                               sec_name, i, need_off, off);
142                         return -EINVAL;
143                 }
144
145                 align = btf__align_of(btf, var->type);
146                 if (align <= 0) {
147                         p_err("Failed to determine alignment of variable '%s': %d",
148                               var_name, align);
149                         return -EINVAL;
150                 }
151                 /* Assume 32-bit architectures when generating data section
152                  * struct memory layout. Given bpftool can't know which target
153                  * host architecture it's emitting skeleton for, we need to be
154                  * conservative and assume 32-bit one to ensure enough padding
155                  * bytes are generated for pointer and long types. This will
156                  * still work correctly for 64-bit architectures, because in
157                  * the worst case we'll generate unnecessary padding field,
158                  * which on 64-bit architectures is not strictly necessary and
159                  * would be handled by natural 8-byte alignment. But it still
160                  * will be a correct memory layout, based on recorded offsets
161                  * in BTF.
162                  */
163                 if (align > 4)
164                         align = 4;
165
166                 align_off = (off + align - 1) / align * align;
167                 if (align_off != need_off) {
168                         printf("\t\tchar __pad%d[%d];\n",
169                                pad_cnt, need_off - off);
170                         pad_cnt++;
171                 }
172
173                 /* sanitize variable name, e.g., for static vars inside
174                  * a function, it's name is '<function name>.<variable name>',
175                  * which we'll turn into a '<function name>_<variable name>'
176                  */
177                 var_ident[0] = '\0';
178                 strncat(var_ident, var_name, sizeof(var_ident) - 1);
179                 sanitize_identifier(var_ident);
180
181                 printf("\t\t");
182                 err = btf_dump__emit_type_decl(d, var_type_id, &opts);
183                 if (err)
184                         return err;
185                 printf(";\n");
186
187                 off = sec_var->offset + sec_var->size;
188         }
189         printf("        } *%s;\n", sec_ident);
190         return 0;
191 }
192
193 static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
194 {
195         struct btf *btf = bpf_object__btf(obj);
196         int n = btf__get_nr_types(btf);
197         struct btf_dump *d;
198         int i, err = 0;
199
200         d = btf_dump__new(btf, NULL, NULL, codegen_btf_dump_printf);
201         if (IS_ERR(d))
202                 return PTR_ERR(d);
203
204         for (i = 1; i <= n; i++) {
205                 const struct btf_type *t = btf__type_by_id(btf, i);
206
207                 if (!btf_is_datasec(t))
208                         continue;
209
210                 err = codegen_datasec_def(obj, btf, d, t, obj_name);
211                 if (err)
212                         goto out;
213         }
214 out:
215         btf_dump__free(d);
216         return err;
217 }
218
219 static void codegen(const char *template, ...)
220 {
221         const char *src, *end;
222         int skip_tabs = 0, n;
223         char *s, *dst;
224         va_list args;
225         char c;
226
227         n = strlen(template);
228         s = malloc(n + 1);
229         if (!s)
230                 exit(-1);
231         src = template;
232         dst = s;
233
234         /* find out "baseline" indentation to skip */
235         while ((c = *src++)) {
236                 if (c == '\t') {
237                         skip_tabs++;
238                 } else if (c == '\n') {
239                         break;
240                 } else {
241                         p_err("unrecognized character at pos %td in template '%s'",
242                               src - template - 1, template);
243                         free(s);
244                         exit(-1);
245                 }
246         }
247
248         while (*src) {
249                 /* skip baseline indentation tabs */
250                 for (n = skip_tabs; n > 0; n--, src++) {
251                         if (*src != '\t') {
252                                 p_err("not enough tabs at pos %td in template '%s'",
253                                       src - template - 1, template);
254                                 free(s);
255                                 exit(-1);
256                         }
257                 }
258                 /* trim trailing whitespace */
259                 end = strchrnul(src, '\n');
260                 for (n = end - src; n > 0 && isspace(src[n - 1]); n--)
261                         ;
262                 memcpy(dst, src, n);
263                 dst += n;
264                 if (*end)
265                         *dst++ = '\n';
266                 src = *end ? end + 1 : end;
267         }
268         *dst++ = '\0';
269
270         /* print out using adjusted template */
271         va_start(args, template);
272         n = vprintf(s, args);
273         va_end(args);
274
275         free(s);
276 }
277
278 static void print_hex(const char *data, int data_sz)
279 {
280         int i, len;
281
282         for (i = 0, len = 0; i < data_sz; i++) {
283                 int w = data[i] ? 4 : 2;
284
285                 len += w;
286                 if (len > 78) {
287                         printf("\\\n");
288                         len = w;
289                 }
290                 if (!data[i])
291                         printf("\\0");
292                 else
293                         printf("\\x%02x", (unsigned char)data[i]);
294         }
295 }
296
297 static size_t bpf_map_mmap_sz(const struct bpf_map *map)
298 {
299         long page_sz = sysconf(_SC_PAGE_SIZE);
300         size_t map_sz;
301
302         map_sz = (size_t)roundup(bpf_map__value_size(map), 8) * bpf_map__max_entries(map);
303         map_sz = roundup(map_sz, page_sz);
304         return map_sz;
305 }
306
307 static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
308 {
309         struct bpf_program *prog;
310
311         bpf_object__for_each_program(prog, obj) {
312                 const char *tp_name;
313
314                 codegen("\
315                         \n\
316                         \n\
317                         static inline int                                           \n\
318                         %1$s__%2$s__attach(struct %1$s *skel)                       \n\
319                         {                                                           \n\
320                                 int prog_fd = skel->progs.%2$s.prog_fd;             \n\
321                         ", obj_name, bpf_program__name(prog));
322
323                 switch (bpf_program__get_type(prog)) {
324                 case BPF_PROG_TYPE_RAW_TRACEPOINT:
325                         tp_name = strchr(bpf_program__section_name(prog), '/') + 1;
326                         printf("\tint fd = bpf_raw_tracepoint_open(\"%s\", prog_fd);\n", tp_name);
327                         break;
328                 case BPF_PROG_TYPE_TRACING:
329                         printf("\tint fd = bpf_raw_tracepoint_open(NULL, prog_fd);\n");
330                         break;
331                 default:
332                         printf("\tint fd = ((void)prog_fd, 0); /* auto-attach not supported */\n");
333                         break;
334                 }
335                 codegen("\
336                         \n\
337                                                                                     \n\
338                                 if (fd > 0)                                         \n\
339                                         skel->links.%1$s_fd = fd;                   \n\
340                                 return fd;                                          \n\
341                         }                                                           \n\
342                         ", bpf_program__name(prog));
343         }
344
345         codegen("\
346                 \n\
347                                                                             \n\
348                 static inline int                                           \n\
349                 %1$s__attach(struct %1$s *skel)                             \n\
350                 {                                                           \n\
351                         int ret = 0;                                        \n\
352                                                                             \n\
353                 ", obj_name);
354
355         bpf_object__for_each_program(prog, obj) {
356                 codegen("\
357                         \n\
358                                 ret = ret < 0 ? ret : %1$s__%2$s__attach(skel);   \n\
359                         ", obj_name, bpf_program__name(prog));
360         }
361
362         codegen("\
363                 \n\
364                         return ret < 0 ? ret : 0;                           \n\
365                 }                                                           \n\
366                                                                             \n\
367                 static inline void                                          \n\
368                 %1$s__detach(struct %1$s *skel)                             \n\
369                 {                                                           \n\
370                 ", obj_name);
371
372         bpf_object__for_each_program(prog, obj) {
373                 codegen("\
374                         \n\
375                                 skel_closenz(skel->links.%1$s_fd);          \n\
376                         ", bpf_program__name(prog));
377         }
378
379         codegen("\
380                 \n\
381                 }                                                           \n\
382                 ");
383 }
384
385 static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
386 {
387         struct bpf_program *prog;
388         struct bpf_map *map;
389
390         codegen("\
391                 \n\
392                 static void                                                 \n\
393                 %1$s__destroy(struct %1$s *skel)                            \n\
394                 {                                                           \n\
395                         if (!skel)                                          \n\
396                                 return;                                     \n\
397                         %1$s__detach(skel);                                 \n\
398                 ",
399                 obj_name);
400
401         bpf_object__for_each_program(prog, obj) {
402                 codegen("\
403                         \n\
404                                 skel_closenz(skel->progs.%1$s.prog_fd);     \n\
405                         ", bpf_program__name(prog));
406         }
407
408         bpf_object__for_each_map(map, obj) {
409                 const char * ident;
410
411                 ident = get_map_ident(map);
412                 if (!ident)
413                         continue;
414                 if (bpf_map__is_internal(map) &&
415                     (bpf_map__def(map)->map_flags & BPF_F_MMAPABLE))
416                         printf("\tmunmap(skel->%1$s, %2$zd);\n",
417                                ident, bpf_map_mmap_sz(map));
418                 codegen("\
419                         \n\
420                                 skel_closenz(skel->maps.%1$s.map_fd);       \n\
421                         ", ident);
422         }
423         codegen("\
424                 \n\
425                         free(skel);                                         \n\
426                 }                                                           \n\
427                 ",
428                 obj_name);
429 }
430
431 static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *header_guard)
432 {
433         struct bpf_object_load_attr load_attr = {};
434         DECLARE_LIBBPF_OPTS(gen_loader_opts, opts);
435         struct bpf_map *map;
436         int err = 0;
437
438         err = bpf_object__gen_loader(obj, &opts);
439         if (err)
440                 return err;
441
442         load_attr.obj = obj;
443         if (verifier_logs)
444                 /* log_level1 + log_level2 + stats, but not stable UAPI */
445                 load_attr.log_level = 1 + 2 + 4;
446
447         err = bpf_object__load_xattr(&load_attr);
448         if (err) {
449                 p_err("failed to load object file");
450                 goto out;
451         }
452         /* If there was no error during load then gen_loader_opts
453          * are populated with the loader program.
454          */
455
456         /* finish generating 'struct skel' */
457         codegen("\
458                 \n\
459                 };                                                          \n\
460                 ", obj_name);
461
462
463         codegen_attach_detach(obj, obj_name);
464
465         codegen_destroy(obj, obj_name);
466
467         codegen("\
468                 \n\
469                 static inline struct %1$s *                                 \n\
470                 %1$s__open(void)                                            \n\
471                 {                                                           \n\
472                         struct %1$s *skel;                                  \n\
473                                                                             \n\
474                         skel = calloc(sizeof(*skel), 1);                    \n\
475                         if (!skel)                                          \n\
476                                 goto cleanup;                               \n\
477                         skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
478                 ",
479                 obj_name, opts.data_sz);
480         bpf_object__for_each_map(map, obj) {
481                 const char *ident;
482                 const void *mmap_data = NULL;
483                 size_t mmap_size = 0;
484
485                 ident = get_map_ident(map);
486                 if (!ident)
487                         continue;
488
489                 if (!bpf_map__is_internal(map) ||
490                     !(bpf_map__def(map)->map_flags & BPF_F_MMAPABLE))
491                         continue;
492
493                 codegen("\
494                         \n\
495                                 skel->%1$s =                                     \n\
496                                         mmap(NULL, %2$zd, PROT_READ | PROT_WRITE,\n\
497                                              MAP_SHARED | MAP_ANONYMOUS, -1, 0); \n\
498                                 if (skel->%1$s == (void *) -1)                   \n\
499                                         goto cleanup;                            \n\
500                                 memcpy(skel->%1$s, (void *)\"\\                  \n\
501                         ", ident, bpf_map_mmap_sz(map));
502                 mmap_data = bpf_map__initial_value(map, &mmap_size);
503                 print_hex(mmap_data, mmap_size);
504                 printf("\", %2$zd);\n"
505                        "\tskel->maps.%1$s.initial_value = (__u64)(long)skel->%1$s;\n",
506                        ident, mmap_size);
507         }
508         codegen("\
509                 \n\
510                         return skel;                                        \n\
511                 cleanup:                                                    \n\
512                         %1$s__destroy(skel);                                \n\
513                         return NULL;                                        \n\
514                 }                                                           \n\
515                                                                             \n\
516                 static inline int                                           \n\
517                 %1$s__load(struct %1$s *skel)                               \n\
518                 {                                                           \n\
519                         struct bpf_load_and_run_opts opts = {};             \n\
520                         int err;                                            \n\
521                                                                             \n\
522                         opts.ctx = (struct bpf_loader_ctx *)skel;           \n\
523                         opts.data_sz = %2$d;                                \n\
524                         opts.data = (void *)\"\\                            \n\
525                 ",
526                 obj_name, opts.data_sz);
527         print_hex(opts.data, opts.data_sz);
528         codegen("\
529                 \n\
530                 \";                                                         \n\
531                 ");
532
533         codegen("\
534                 \n\
535                         opts.insns_sz = %d;                                 \n\
536                         opts.insns = (void *)\"\\                           \n\
537                 ",
538                 opts.insns_sz);
539         print_hex(opts.insns, opts.insns_sz);
540         codegen("\
541                 \n\
542                 \";                                                         \n\
543                         err = bpf_load_and_run(&opts);                      \n\
544                         if (err < 0)                                        \n\
545                                 return err;                                 \n\
546                 ", obj_name);
547         bpf_object__for_each_map(map, obj) {
548                 const char *ident, *mmap_flags;
549
550                 ident = get_map_ident(map);
551                 if (!ident)
552                         continue;
553
554                 if (!bpf_map__is_internal(map) ||
555                     !(bpf_map__def(map)->map_flags & BPF_F_MMAPABLE))
556                         continue;
557                 if (bpf_map__def(map)->map_flags & BPF_F_RDONLY_PROG)
558                         mmap_flags = "PROT_READ";
559                 else
560                         mmap_flags = "PROT_READ | PROT_WRITE";
561
562                 printf("\tskel->%1$s =\n"
563                        "\t\tmmap(skel->%1$s, %2$zd, %3$s, MAP_SHARED | MAP_FIXED,\n"
564                        "\t\t\tskel->maps.%1$s.map_fd, 0);\n",
565                        ident, bpf_map_mmap_sz(map), mmap_flags);
566         }
567         codegen("\
568                 \n\
569                         return 0;                                           \n\
570                 }                                                           \n\
571                                                                             \n\
572                 static inline struct %1$s *                                 \n\
573                 %1$s__open_and_load(void)                                   \n\
574                 {                                                           \n\
575                         struct %1$s *skel;                                  \n\
576                                                                             \n\
577                         skel = %1$s__open();                                \n\
578                         if (!skel)                                          \n\
579                                 return NULL;                                \n\
580                         if (%1$s__load(skel)) {                             \n\
581                                 %1$s__destroy(skel);                        \n\
582                                 return NULL;                                \n\
583                         }                                                   \n\
584                         return skel;                                        \n\
585                 }                                                           \n\
586                 ", obj_name);
587
588         codegen("\
589                 \n\
590                                                                             \n\
591                 #endif /* %s */                                             \n\
592                 ",
593                 header_guard);
594         err = 0;
595 out:
596         return err;
597 }
598
599 static int do_skeleton(int argc, char **argv)
600 {
601         char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
602         size_t i, map_cnt = 0, prog_cnt = 0, file_sz, mmap_sz;
603         DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
604         char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
605         struct bpf_object *obj = NULL;
606         const char *file, *ident;
607         struct bpf_program *prog;
608         int fd, err = -1;
609         struct bpf_map *map;
610         struct btf *btf;
611         struct stat st;
612
613         if (!REQ_ARGS(1)) {
614                 usage();
615                 return -1;
616         }
617         file = GET_ARG();
618
619         while (argc) {
620                 if (!REQ_ARGS(2))
621                         return -1;
622
623                 if (is_prefix(*argv, "name")) {
624                         NEXT_ARG();
625
626                         if (obj_name[0] != '\0') {
627                                 p_err("object name already specified");
628                                 return -1;
629                         }
630
631                         strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
632                         obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
633                 } else {
634                         p_err("unknown arg %s", *argv);
635                         return -1;
636                 }
637
638                 NEXT_ARG();
639         }
640
641         if (argc) {
642                 p_err("extra unknown arguments");
643                 return -1;
644         }
645
646         if (stat(file, &st)) {
647                 p_err("failed to stat() %s: %s", file, strerror(errno));
648                 return -1;
649         }
650         file_sz = st.st_size;
651         mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
652         fd = open(file, O_RDONLY);
653         if (fd < 0) {
654                 p_err("failed to open() %s: %s", file, strerror(errno));
655                 return -1;
656         }
657         obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
658         if (obj_data == MAP_FAILED) {
659                 obj_data = NULL;
660                 p_err("failed to mmap() %s: %s", file, strerror(errno));
661                 goto out;
662         }
663         if (obj_name[0] == '\0')
664                 get_obj_name(obj_name, file);
665         opts.object_name = obj_name;
666         obj = bpf_object__open_mem(obj_data, file_sz, &opts);
667         if (IS_ERR(obj)) {
668                 char err_buf[256];
669
670                 libbpf_strerror(PTR_ERR(obj), err_buf, sizeof(err_buf));
671                 p_err("failed to open BPF object file: %s", err_buf);
672                 obj = NULL;
673                 goto out;
674         }
675
676         bpf_object__for_each_map(map, obj) {
677                 ident = get_map_ident(map);
678                 if (!ident) {
679                         p_err("ignoring unrecognized internal map '%s'...",
680                               bpf_map__name(map));
681                         continue;
682                 }
683                 map_cnt++;
684         }
685         bpf_object__for_each_program(prog, obj) {
686                 prog_cnt++;
687         }
688
689         get_header_guard(header_guard, obj_name);
690         if (use_loader) {
691                 codegen("\
692                 \n\
693                 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
694                 /* THIS FILE IS AUTOGENERATED! */                           \n\
695                 #ifndef %2$s                                                \n\
696                 #define %2$s                                                \n\
697                                                                             \n\
698                 #include <stdlib.h>                                         \n\
699                 #include <bpf/bpf.h>                                        \n\
700                 #include <bpf/skel_internal.h>                              \n\
701                                                                             \n\
702                 struct %1$s {                                               \n\
703                         struct bpf_loader_ctx ctx;                          \n\
704                 ",
705                 obj_name, header_guard
706                 );
707         } else {
708                 codegen("\
709                 \n\
710                 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
711                                                                             \n\
712                 /* THIS FILE IS AUTOGENERATED! */                           \n\
713                 #ifndef %2$s                                                \n\
714                 #define %2$s                                                \n\
715                                                                             \n\
716                 #include <errno.h>                                          \n\
717                 #include <stdlib.h>                                         \n\
718                 #include <bpf/libbpf.h>                                     \n\
719                                                                             \n\
720                 struct %1$s {                                               \n\
721                         struct bpf_object_skeleton *skeleton;               \n\
722                         struct bpf_object *obj;                             \n\
723                 ",
724                 obj_name, header_guard
725                 );
726         }
727
728         if (map_cnt) {
729                 printf("\tstruct {\n");
730                 bpf_object__for_each_map(map, obj) {
731                         ident = get_map_ident(map);
732                         if (!ident)
733                                 continue;
734                         if (use_loader)
735                                 printf("\t\tstruct bpf_map_desc %s;\n", ident);
736                         else
737                                 printf("\t\tstruct bpf_map *%s;\n", ident);
738                 }
739                 printf("\t} maps;\n");
740         }
741
742         if (prog_cnt) {
743                 printf("\tstruct {\n");
744                 bpf_object__for_each_program(prog, obj) {
745                         if (use_loader)
746                                 printf("\t\tstruct bpf_prog_desc %s;\n",
747                                        bpf_program__name(prog));
748                         else
749                                 printf("\t\tstruct bpf_program *%s;\n",
750                                        bpf_program__name(prog));
751                 }
752                 printf("\t} progs;\n");
753                 printf("\tstruct {\n");
754                 bpf_object__for_each_program(prog, obj) {
755                         if (use_loader)
756                                 printf("\t\tint %s_fd;\n",
757                                        bpf_program__name(prog));
758                         else
759                                 printf("\t\tstruct bpf_link *%s;\n",
760                                        bpf_program__name(prog));
761                 }
762                 printf("\t} links;\n");
763         }
764
765         btf = bpf_object__btf(obj);
766         if (btf) {
767                 err = codegen_datasecs(obj, obj_name);
768                 if (err)
769                         goto out;
770         }
771         if (use_loader) {
772                 err = gen_trace(obj, obj_name, header_guard);
773                 goto out;
774         }
775
776         codegen("\
777                 \n\
778                 };                                                          \n\
779                                                                             \n\
780                 static void                                                 \n\
781                 %1$s__destroy(struct %1$s *obj)                             \n\
782                 {                                                           \n\
783                         if (!obj)                                           \n\
784                                 return;                                     \n\
785                         if (obj->skeleton)                                  \n\
786                                 bpf_object__destroy_skeleton(obj->skeleton);\n\
787                         free(obj);                                          \n\
788                 }                                                           \n\
789                                                                             \n\
790                 static inline int                                           \n\
791                 %1$s__create_skeleton(struct %1$s *obj);                    \n\
792                                                                             \n\
793                 static inline struct %1$s *                                 \n\
794                 %1$s__open_opts(const struct bpf_object_open_opts *opts)    \n\
795                 {                                                           \n\
796                         struct %1$s *obj;                                   \n\
797                         int err;                                            \n\
798                                                                             \n\
799                         obj = (struct %1$s *)calloc(1, sizeof(*obj));       \n\
800                         if (!obj) {                                         \n\
801                                 errno = ENOMEM;                             \n\
802                                 return NULL;                                \n\
803                         }                                                   \n\
804                                                                             \n\
805                         err = %1$s__create_skeleton(obj);                   \n\
806                         err = err ?: bpf_object__open_skeleton(obj->skeleton, opts);\n\
807                         if (err)                                            \n\
808                                 goto err_out;                               \n\
809                                                                             \n\
810                         return obj;                                         \n\
811                 err_out:                                                    \n\
812                         %1$s__destroy(obj);                                 \n\
813                         errno = -err;                                       \n\
814                         return NULL;                                        \n\
815                 }                                                           \n\
816                                                                             \n\
817                 static inline struct %1$s *                                 \n\
818                 %1$s__open(void)                                            \n\
819                 {                                                           \n\
820                         return %1$s__open_opts(NULL);                       \n\
821                 }                                                           \n\
822                                                                             \n\
823                 static inline int                                           \n\
824                 %1$s__load(struct %1$s *obj)                                \n\
825                 {                                                           \n\
826                         return bpf_object__load_skeleton(obj->skeleton);    \n\
827                 }                                                           \n\
828                                                                             \n\
829                 static inline struct %1$s *                                 \n\
830                 %1$s__open_and_load(void)                                   \n\
831                 {                                                           \n\
832                         struct %1$s *obj;                                   \n\
833                         int err;                                            \n\
834                                                                             \n\
835                         obj = %1$s__open();                                 \n\
836                         if (!obj)                                           \n\
837                                 return NULL;                                \n\
838                         err = %1$s__load(obj);                              \n\
839                         if (err) {                                          \n\
840                                 %1$s__destroy(obj);                         \n\
841                                 errno = -err;                               \n\
842                                 return NULL;                                \n\
843                         }                                                   \n\
844                         return obj;                                         \n\
845                 }                                                           \n\
846                                                                             \n\
847                 static inline int                                           \n\
848                 %1$s__attach(struct %1$s *obj)                              \n\
849                 {                                                           \n\
850                         return bpf_object__attach_skeleton(obj->skeleton);  \n\
851                 }                                                           \n\
852                                                                             \n\
853                 static inline void                                          \n\
854                 %1$s__detach(struct %1$s *obj)                              \n\
855                 {                                                           \n\
856                         return bpf_object__detach_skeleton(obj->skeleton);  \n\
857                 }                                                           \n\
858                 ",
859                 obj_name
860         );
861
862         codegen("\
863                 \n\
864                                                                             \n\
865                 static inline int                                           \n\
866                 %1$s__create_skeleton(struct %1$s *obj)                     \n\
867                 {                                                           \n\
868                         struct bpf_object_skeleton *s;                      \n\
869                                                                             \n\
870                         s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\
871                         if (!s)                                             \n\
872                                 goto err;                                   \n\
873                         obj->skeleton = s;                                  \n\
874                                                                             \n\
875                         s->sz = sizeof(*s);                                 \n\
876                         s->name = \"%1$s\";                                 \n\
877                         s->obj = &obj->obj;                                 \n\
878                 ",
879                 obj_name
880         );
881         if (map_cnt) {
882                 codegen("\
883                         \n\
884                                                                             \n\
885                                 /* maps */                                  \n\
886                                 s->map_cnt = %zu;                           \n\
887                                 s->map_skel_sz = sizeof(*s->maps);          \n\
888                                 s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);\n\
889                                 if (!s->maps)                               \n\
890                                         goto err;                           \n\
891                         ",
892                         map_cnt
893                 );
894                 i = 0;
895                 bpf_object__for_each_map(map, obj) {
896                         ident = get_map_ident(map);
897
898                         if (!ident)
899                                 continue;
900
901                         codegen("\
902                                 \n\
903                                                                             \n\
904                                         s->maps[%zu].name = \"%s\";         \n\
905                                         s->maps[%zu].map = &obj->maps.%s;   \n\
906                                 ",
907                                 i, bpf_map__name(map), i, ident);
908                         /* memory-mapped internal maps */
909                         if (bpf_map__is_internal(map) &&
910                             (bpf_map__def(map)->map_flags & BPF_F_MMAPABLE)) {
911                                 printf("\ts->maps[%zu].mmaped = (void **)&obj->%s;\n",
912                                        i, ident);
913                         }
914                         i++;
915                 }
916         }
917         if (prog_cnt) {
918                 codegen("\
919                         \n\
920                                                                             \n\
921                                 /* programs */                              \n\
922                                 s->prog_cnt = %zu;                          \n\
923                                 s->prog_skel_sz = sizeof(*s->progs);        \n\
924                                 s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);\n\
925                                 if (!s->progs)                              \n\
926                                         goto err;                           \n\
927                         ",
928                         prog_cnt
929                 );
930                 i = 0;
931                 bpf_object__for_each_program(prog, obj) {
932                         codegen("\
933                                 \n\
934                                                                             \n\
935                                         s->progs[%1$zu].name = \"%2$s\";    \n\
936                                         s->progs[%1$zu].prog = &obj->progs.%2$s;\n\
937                                         s->progs[%1$zu].link = &obj->links.%2$s;\n\
938                                 ",
939                                 i, bpf_program__name(prog));
940                         i++;
941                 }
942         }
943         codegen("\
944                 \n\
945                                                                             \n\
946                         s->data_sz = %d;                                    \n\
947                         s->data = (void *)\"\\                              \n\
948                 ",
949                 file_sz);
950
951         /* embed contents of BPF object file */
952         print_hex(obj_data, file_sz);
953
954         codegen("\
955                 \n\
956                 \";                                                         \n\
957                                                                             \n\
958                         return 0;                                           \n\
959                 err:                                                        \n\
960                         bpf_object__destroy_skeleton(s);                    \n\
961                         return -ENOMEM;                                     \n\
962                 }                                                           \n\
963                                                                             \n\
964                 #endif /* %s */                                             \n\
965                 ",
966                 header_guard);
967         err = 0;
968 out:
969         bpf_object__close(obj);
970         if (obj_data)
971                 munmap(obj_data, mmap_sz);
972         close(fd);
973         return err;
974 }
975
976 static int do_object(int argc, char **argv)
977 {
978         struct bpf_linker *linker;
979         const char *output_file, *file;
980         int err = 0;
981
982         if (!REQ_ARGS(2)) {
983                 usage();
984                 return -1;
985         }
986
987         output_file = GET_ARG();
988
989         linker = bpf_linker__new(output_file, NULL);
990         if (!linker) {
991                 p_err("failed to create BPF linker instance");
992                 return -1;
993         }
994
995         while (argc) {
996                 file = GET_ARG();
997
998                 err = bpf_linker__add_file(linker, file, NULL);
999                 if (err) {
1000                         p_err("failed to link '%s': %s (%d)", file, strerror(err), err);
1001                         goto out;
1002                 }
1003         }
1004
1005         err = bpf_linker__finalize(linker);
1006         if (err) {
1007                 p_err("failed to finalize ELF file: %s (%d)", strerror(err), err);
1008                 goto out;
1009         }
1010
1011         err = 0;
1012 out:
1013         bpf_linker__free(linker);
1014         return err;
1015 }
1016
1017 static int do_help(int argc, char **argv)
1018 {
1019         if (json_output) {
1020                 jsonw_null(json_wtr);
1021                 return 0;
1022         }
1023
1024         fprintf(stderr,
1025                 "Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
1026                 "       %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
1027                 "       %1$s %2$s help\n"
1028                 "\n"
1029                 "       " HELP_SPEC_OPTIONS " |\n"
1030                 "                    {-L|--use-loader} }\n"
1031                 "",
1032                 bin_name, "gen");
1033
1034         return 0;
1035 }
1036
1037 static const struct cmd cmds[] = {
1038         { "object",     do_object },
1039         { "skeleton",   do_skeleton },
1040         { "help",       do_help },
1041         { 0 }
1042 };
1043
1044 int do_gen(int argc, char **argv)
1045 {
1046         return cmd_select(cmds, argc, argv, do_help);
1047 }