a3d72be347b0cb73a505af6a28889df6ec236855
[linux-block.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 <libgen.h>
11 #include <linux/err.h>
12 #include <stdbool.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <bpf/bpf.h>
17 #include <bpf/libbpf.h>
18 #include <bpf/libbpf_internal.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/mman.h>
22 #include <bpf/btf.h>
23
24 #include "json_writer.h"
25 #include "main.h"
26
27 #define MAX_OBJ_NAME_LEN 64
28
29 static void sanitize_identifier(char *name)
30 {
31         int i;
32
33         for (i = 0; name[i]; i++)
34                 if (!isalnum(name[i]) && name[i] != '_')
35                         name[i] = '_';
36 }
37
38 static bool str_has_prefix(const char *str, const char *prefix)
39 {
40         return strncmp(str, prefix, strlen(prefix)) == 0;
41 }
42
43 static bool str_has_suffix(const char *str, const char *suffix)
44 {
45         size_t i, n1 = strlen(str), n2 = strlen(suffix);
46
47         if (n1 < n2)
48                 return false;
49
50         for (i = 0; i < n2; i++) {
51                 if (str[n1 - i - 1] != suffix[n2 - i - 1])
52                         return false;
53         }
54
55         return true;
56 }
57
58 static const struct btf_type *
59 resolve_func_ptr(const struct btf *btf, __u32 id, __u32 *res_id)
60 {
61         const struct btf_type *t;
62
63         t = skip_mods_and_typedefs(btf, id, NULL);
64         if (!btf_is_ptr(t))
65                 return NULL;
66
67         t = skip_mods_and_typedefs(btf, t->type, res_id);
68
69         return btf_is_func_proto(t) ? t : NULL;
70 }
71
72 static void get_obj_name(char *name, const char *file)
73 {
74         char file_copy[PATH_MAX];
75
76         /* Using basename() POSIX version to be more portable. */
77         strncpy(file_copy, file, PATH_MAX - 1)[PATH_MAX - 1] = '\0';
78         strncpy(name, basename(file_copy), MAX_OBJ_NAME_LEN - 1)[MAX_OBJ_NAME_LEN - 1] = '\0';
79         if (str_has_suffix(name, ".o"))
80                 name[strlen(name) - 2] = '\0';
81         sanitize_identifier(name);
82 }
83
84 static void get_header_guard(char *guard, const char *obj_name, const char *suffix)
85 {
86         int i;
87
88         sprintf(guard, "__%s_%s__", obj_name, suffix);
89         for (i = 0; guard[i]; i++)
90                 guard[i] = toupper(guard[i]);
91 }
92
93 static bool get_map_ident(const struct bpf_map *map, char *buf, size_t buf_sz)
94 {
95         static const char *sfxs[] = { ".data", ".rodata", ".bss", ".kconfig" };
96         const char *name = bpf_map__name(map);
97         int i, n;
98
99         if (!bpf_map__is_internal(map)) {
100                 snprintf(buf, buf_sz, "%s", name);
101                 return true;
102         }
103
104         for  (i = 0, n = ARRAY_SIZE(sfxs); i < n; i++) {
105                 const char *sfx = sfxs[i], *p;
106
107                 p = strstr(name, sfx);
108                 if (p) {
109                         snprintf(buf, buf_sz, "%s", p + 1);
110                         sanitize_identifier(buf);
111                         return true;
112                 }
113         }
114
115         return false;
116 }
117
118 static bool get_datasec_ident(const char *sec_name, char *buf, size_t buf_sz)
119 {
120         static const char *pfxs[] = { ".data", ".rodata", ".bss", ".kconfig" };
121         int i, n;
122
123         for  (i = 0, n = ARRAY_SIZE(pfxs); i < n; i++) {
124                 const char *pfx = pfxs[i];
125
126                 if (str_has_prefix(sec_name, pfx)) {
127                         snprintf(buf, buf_sz, "%s", sec_name + 1);
128                         sanitize_identifier(buf);
129                         return true;
130                 }
131         }
132
133         return false;
134 }
135
136 static void codegen_btf_dump_printf(void *ctx, const char *fmt, va_list args)
137 {
138         vprintf(fmt, args);
139 }
140
141 static int codegen_datasec_def(struct bpf_object *obj,
142                                struct btf *btf,
143                                struct btf_dump *d,
144                                const struct btf_type *sec,
145                                const char *obj_name)
146 {
147         const char *sec_name = btf__name_by_offset(btf, sec->name_off);
148         const struct btf_var_secinfo *sec_var = btf_var_secinfos(sec);
149         int i, err, off = 0, pad_cnt = 0, vlen = btf_vlen(sec);
150         char var_ident[256], sec_ident[256];
151         bool strip_mods = false;
152
153         if (!get_datasec_ident(sec_name, sec_ident, sizeof(sec_ident)))
154                 return 0;
155
156         if (strcmp(sec_name, ".kconfig") != 0)
157                 strip_mods = true;
158
159         printf("        struct %s__%s {\n", obj_name, sec_ident);
160         for (i = 0; i < vlen; i++, sec_var++) {
161                 const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
162                 const char *var_name = btf__name_by_offset(btf, var->name_off);
163                 DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
164                         .field_name = var_ident,
165                         .indent_level = 2,
166                         .strip_mods = strip_mods,
167                 );
168                 int need_off = sec_var->offset, align_off, align;
169                 __u32 var_type_id = var->type;
170
171                 /* static variables are not exposed through BPF skeleton */
172                 if (btf_var(var)->linkage == BTF_VAR_STATIC)
173                         continue;
174
175                 if (off > need_off) {
176                         p_err("Something is wrong for %s's variable #%d: need offset %d, already at %d.\n",
177                               sec_name, i, need_off, off);
178                         return -EINVAL;
179                 }
180
181                 align = btf__align_of(btf, var->type);
182                 if (align <= 0) {
183                         p_err("Failed to determine alignment of variable '%s': %d",
184                               var_name, align);
185                         return -EINVAL;
186                 }
187                 /* Assume 32-bit architectures when generating data section
188                  * struct memory layout. Given bpftool can't know which target
189                  * host architecture it's emitting skeleton for, we need to be
190                  * conservative and assume 32-bit one to ensure enough padding
191                  * bytes are generated for pointer and long types. This will
192                  * still work correctly for 64-bit architectures, because in
193                  * the worst case we'll generate unnecessary padding field,
194                  * which on 64-bit architectures is not strictly necessary and
195                  * would be handled by natural 8-byte alignment. But it still
196                  * will be a correct memory layout, based on recorded offsets
197                  * in BTF.
198                  */
199                 if (align > 4)
200                         align = 4;
201
202                 align_off = (off + align - 1) / align * align;
203                 if (align_off != need_off) {
204                         printf("\t\tchar __pad%d[%d];\n",
205                                pad_cnt, need_off - off);
206                         pad_cnt++;
207                 }
208
209                 /* sanitize variable name, e.g., for static vars inside
210                  * a function, it's name is '<function name>.<variable name>',
211                  * which we'll turn into a '<function name>_<variable name>'
212                  */
213                 var_ident[0] = '\0';
214                 strncat(var_ident, var_name, sizeof(var_ident) - 1);
215                 sanitize_identifier(var_ident);
216
217                 printf("\t\t");
218                 err = btf_dump__emit_type_decl(d, var_type_id, &opts);
219                 if (err)
220                         return err;
221                 printf(";\n");
222
223                 off = sec_var->offset + sec_var->size;
224         }
225         printf("        } *%s;\n", sec_ident);
226         return 0;
227 }
228
229 static const struct btf_type *find_type_for_map(struct btf *btf, const char *map_ident)
230 {
231         int n = btf__type_cnt(btf), i;
232         char sec_ident[256];
233
234         for (i = 1; i < n; i++) {
235                 const struct btf_type *t = btf__type_by_id(btf, i);
236                 const char *name;
237
238                 if (!btf_is_datasec(t))
239                         continue;
240
241                 name = btf__str_by_offset(btf, t->name_off);
242                 if (!get_datasec_ident(name, sec_ident, sizeof(sec_ident)))
243                         continue;
244
245                 if (strcmp(sec_ident, map_ident) == 0)
246                         return t;
247         }
248         return NULL;
249 }
250
251 static bool is_mmapable_map(const struct bpf_map *map, char *buf, size_t sz)
252 {
253         if (!bpf_map__is_internal(map) || !(bpf_map__map_flags(map) & BPF_F_MMAPABLE))
254                 return false;
255
256         if (!get_map_ident(map, buf, sz))
257                 return false;
258
259         return true;
260 }
261
262 static int codegen_datasecs(struct bpf_object *obj, const char *obj_name)
263 {
264         struct btf *btf = bpf_object__btf(obj);
265         struct btf_dump *d;
266         struct bpf_map *map;
267         const struct btf_type *sec;
268         char map_ident[256];
269         int err = 0;
270
271         d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
272         if (!d)
273                 return -errno;
274
275         bpf_object__for_each_map(map, obj) {
276                 /* only generate definitions for memory-mapped internal maps */
277                 if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
278                         continue;
279
280                 sec = find_type_for_map(btf, map_ident);
281
282                 /* In some cases (e.g., sections like .rodata.cst16 containing
283                  * compiler allocated string constants only) there will be
284                  * special internal maps with no corresponding DATASEC BTF
285                  * type. In such case, generate empty structs for each such
286                  * map. It will still be memory-mapped and its contents
287                  * accessible from user-space through BPF skeleton.
288                  */
289                 if (!sec) {
290                         printf("        struct %s__%s {\n", obj_name, map_ident);
291                         printf("        } *%s;\n", map_ident);
292                 } else {
293                         err = codegen_datasec_def(obj, btf, d, sec, obj_name);
294                         if (err)
295                                 goto out;
296                 }
297         }
298
299
300 out:
301         btf_dump__free(d);
302         return err;
303 }
304
305 static bool btf_is_ptr_to_func_proto(const struct btf *btf,
306                                      const struct btf_type *v)
307 {
308         return btf_is_ptr(v) && btf_is_func_proto(btf__type_by_id(btf, v->type));
309 }
310
311 static int codegen_subskel_datasecs(struct bpf_object *obj, const char *obj_name)
312 {
313         struct btf *btf = bpf_object__btf(obj);
314         struct btf_dump *d;
315         struct bpf_map *map;
316         const struct btf_type *sec, *var;
317         const struct btf_var_secinfo *sec_var;
318         int i, err = 0, vlen;
319         char map_ident[256], sec_ident[256];
320         bool strip_mods = false, needs_typeof = false;
321         const char *sec_name, *var_name;
322         __u32 var_type_id;
323
324         d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
325         if (!d)
326                 return -errno;
327
328         bpf_object__for_each_map(map, obj) {
329                 /* only generate definitions for memory-mapped internal maps */
330                 if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
331                         continue;
332
333                 sec = find_type_for_map(btf, map_ident);
334                 if (!sec)
335                         continue;
336
337                 sec_name = btf__name_by_offset(btf, sec->name_off);
338                 if (!get_datasec_ident(sec_name, sec_ident, sizeof(sec_ident)))
339                         continue;
340
341                 strip_mods = strcmp(sec_name, ".kconfig") != 0;
342                 printf("        struct %s__%s {\n", obj_name, sec_ident);
343
344                 sec_var = btf_var_secinfos(sec);
345                 vlen = btf_vlen(sec);
346                 for (i = 0; i < vlen; i++, sec_var++) {
347                         DECLARE_LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts,
348                                 .indent_level = 2,
349                                 .strip_mods = strip_mods,
350                                 /* we'll print the name separately */
351                                 .field_name = "",
352                         );
353
354                         var = btf__type_by_id(btf, sec_var->type);
355                         var_name = btf__name_by_offset(btf, var->name_off);
356                         var_type_id = var->type;
357
358                         /* static variables are not exposed through BPF skeleton */
359                         if (btf_var(var)->linkage == BTF_VAR_STATIC)
360                                 continue;
361
362                         /* The datasec member has KIND_VAR but we want the
363                          * underlying type of the variable (e.g. KIND_INT).
364                          */
365                         var = skip_mods_and_typedefs(btf, var->type, NULL);
366
367                         printf("\t\t");
368                         /* Func and array members require special handling.
369                          * Instead of producing `typename *var`, they produce
370                          * `typeof(typename) *var`. This allows us to keep a
371                          * similar syntax where the identifier is just prefixed
372                          * by *, allowing us to ignore C declaration minutiae.
373                          */
374                         needs_typeof = btf_is_array(var) || btf_is_ptr_to_func_proto(btf, var);
375                         if (needs_typeof)
376                                 printf("typeof(");
377
378                         err = btf_dump__emit_type_decl(d, var_type_id, &opts);
379                         if (err)
380                                 goto out;
381
382                         if (needs_typeof)
383                                 printf(")");
384
385                         printf(" *%s;\n", var_name);
386                 }
387                 printf("        } %s;\n", sec_ident);
388         }
389
390 out:
391         btf_dump__free(d);
392         return err;
393 }
394
395 static void codegen(const char *template, ...)
396 {
397         const char *src, *end;
398         int skip_tabs = 0, n;
399         char *s, *dst;
400         va_list args;
401         char c;
402
403         n = strlen(template);
404         s = malloc(n + 1);
405         if (!s)
406                 exit(-1);
407         src = template;
408         dst = s;
409
410         /* find out "baseline" indentation to skip */
411         while ((c = *src++)) {
412                 if (c == '\t') {
413                         skip_tabs++;
414                 } else if (c == '\n') {
415                         break;
416                 } else {
417                         p_err("unrecognized character at pos %td in template '%s': '%c'",
418                               src - template - 1, template, c);
419                         free(s);
420                         exit(-1);
421                 }
422         }
423
424         while (*src) {
425                 /* skip baseline indentation tabs */
426                 for (n = skip_tabs; n > 0; n--, src++) {
427                         if (*src != '\t') {
428                                 p_err("not enough tabs at pos %td in template '%s'",
429                                       src - template - 1, template);
430                                 free(s);
431                                 exit(-1);
432                         }
433                 }
434                 /* trim trailing whitespace */
435                 end = strchrnul(src, '\n');
436                 for (n = end - src; n > 0 && isspace(src[n - 1]); n--)
437                         ;
438                 memcpy(dst, src, n);
439                 dst += n;
440                 if (*end)
441                         *dst++ = '\n';
442                 src = *end ? end + 1 : end;
443         }
444         *dst++ = '\0';
445
446         /* print out using adjusted template */
447         va_start(args, template);
448         n = vprintf(s, args);
449         va_end(args);
450
451         free(s);
452 }
453
454 static void print_hex(const char *data, int data_sz)
455 {
456         int i, len;
457
458         for (i = 0, len = 0; i < data_sz; i++) {
459                 int w = data[i] ? 4 : 2;
460
461                 len += w;
462                 if (len > 78) {
463                         printf("\\\n");
464                         len = w;
465                 }
466                 if (!data[i])
467                         printf("\\0");
468                 else
469                         printf("\\x%02x", (unsigned char)data[i]);
470         }
471 }
472
473 static size_t bpf_map_mmap_sz(const struct bpf_map *map)
474 {
475         long page_sz = sysconf(_SC_PAGE_SIZE);
476         size_t map_sz;
477
478         map_sz = (size_t)roundup(bpf_map__value_size(map), 8) * bpf_map__max_entries(map);
479         map_sz = roundup(map_sz, page_sz);
480         return map_sz;
481 }
482
483 /* Emit type size asserts for all top-level fields in memory-mapped internal maps. */
484 static void codegen_asserts(struct bpf_object *obj, const char *obj_name)
485 {
486         struct btf *btf = bpf_object__btf(obj);
487         struct bpf_map *map;
488         struct btf_var_secinfo *sec_var;
489         int i, vlen;
490         const struct btf_type *sec;
491         char map_ident[256], var_ident[256];
492
493         if (!btf)
494                 return;
495
496         codegen("\
497                 \n\
498                 __attribute__((unused)) static void                         \n\
499                 %1$s__assert(struct %1$s *s __attribute__((unused)))        \n\
500                 {                                                           \n\
501                 #ifdef __cplusplus                                          \n\
502                 #define _Static_assert static_assert                        \n\
503                 #endif                                                      \n\
504                 ", obj_name);
505
506         bpf_object__for_each_map(map, obj) {
507                 if (!is_mmapable_map(map, map_ident, sizeof(map_ident)))
508                         continue;
509
510                 sec = find_type_for_map(btf, map_ident);
511                 if (!sec) {
512                         /* best effort, couldn't find the type for this map */
513                         continue;
514                 }
515
516                 sec_var = btf_var_secinfos(sec);
517                 vlen =  btf_vlen(sec);
518
519                 for (i = 0; i < vlen; i++, sec_var++) {
520                         const struct btf_type *var = btf__type_by_id(btf, sec_var->type);
521                         const char *var_name = btf__name_by_offset(btf, var->name_off);
522                         long var_size;
523
524                         /* static variables are not exposed through BPF skeleton */
525                         if (btf_var(var)->linkage == BTF_VAR_STATIC)
526                                 continue;
527
528                         var_size = btf__resolve_size(btf, var->type);
529                         if (var_size < 0)
530                                 continue;
531
532                         var_ident[0] = '\0';
533                         strncat(var_ident, var_name, sizeof(var_ident) - 1);
534                         sanitize_identifier(var_ident);
535
536                         printf("\t_Static_assert(sizeof(s->%s->%s) == %ld, \"unexpected size of '%s'\");\n",
537                                map_ident, var_ident, var_size, var_ident);
538                 }
539         }
540         codegen("\
541                 \n\
542                 #ifdef __cplusplus                                          \n\
543                 #undef _Static_assert                                       \n\
544                 #endif                                                      \n\
545                 }                                                           \n\
546                 ");
547 }
548
549 static void codegen_attach_detach(struct bpf_object *obj, const char *obj_name)
550 {
551         struct bpf_program *prog;
552
553         bpf_object__for_each_program(prog, obj) {
554                 const char *tp_name;
555
556                 codegen("\
557                         \n\
558                         \n\
559                         static inline int                                           \n\
560                         %1$s__%2$s__attach(struct %1$s *skel)                       \n\
561                         {                                                           \n\
562                                 int prog_fd = skel->progs.%2$s.prog_fd;             \n\
563                         ", obj_name, bpf_program__name(prog));
564
565                 switch (bpf_program__type(prog)) {
566                 case BPF_PROG_TYPE_RAW_TRACEPOINT:
567                         tp_name = strchr(bpf_program__section_name(prog), '/') + 1;
568                         printf("\tint fd = skel_raw_tracepoint_open(\"%s\", prog_fd);\n", tp_name);
569                         break;
570                 case BPF_PROG_TYPE_TRACING:
571                 case BPF_PROG_TYPE_LSM:
572                         if (bpf_program__expected_attach_type(prog) == BPF_TRACE_ITER)
573                                 printf("\tint fd = skel_link_create(prog_fd, 0, BPF_TRACE_ITER);\n");
574                         else
575                                 printf("\tint fd = skel_raw_tracepoint_open(NULL, prog_fd);\n");
576                         break;
577                 default:
578                         printf("\tint fd = ((void)prog_fd, 0); /* auto-attach not supported */\n");
579                         break;
580                 }
581                 codegen("\
582                         \n\
583                                                                                     \n\
584                                 if (fd > 0)                                         \n\
585                                         skel->links.%1$s_fd = fd;                   \n\
586                                 return fd;                                          \n\
587                         }                                                           \n\
588                         ", bpf_program__name(prog));
589         }
590
591         codegen("\
592                 \n\
593                                                                             \n\
594                 static inline int                                           \n\
595                 %1$s__attach(struct %1$s *skel)                             \n\
596                 {                                                           \n\
597                         int ret = 0;                                        \n\
598                                                                             \n\
599                 ", obj_name);
600
601         bpf_object__for_each_program(prog, obj) {
602                 codegen("\
603                         \n\
604                                 ret = ret < 0 ? ret : %1$s__%2$s__attach(skel);   \n\
605                         ", obj_name, bpf_program__name(prog));
606         }
607
608         codegen("\
609                 \n\
610                         return ret < 0 ? ret : 0;                           \n\
611                 }                                                           \n\
612                                                                             \n\
613                 static inline void                                          \n\
614                 %1$s__detach(struct %1$s *skel)                             \n\
615                 {                                                           \n\
616                 ", obj_name);
617
618         bpf_object__for_each_program(prog, obj) {
619                 codegen("\
620                         \n\
621                                 skel_closenz(skel->links.%1$s_fd);          \n\
622                         ", bpf_program__name(prog));
623         }
624
625         codegen("\
626                 \n\
627                 }                                                           \n\
628                 ");
629 }
630
631 static void codegen_destroy(struct bpf_object *obj, const char *obj_name)
632 {
633         struct bpf_program *prog;
634         struct bpf_map *map;
635         char ident[256];
636
637         codegen("\
638                 \n\
639                 static void                                                 \n\
640                 %1$s__destroy(struct %1$s *skel)                            \n\
641                 {                                                           \n\
642                         if (!skel)                                          \n\
643                                 return;                                     \n\
644                         %1$s__detach(skel);                                 \n\
645                 ",
646                 obj_name);
647
648         bpf_object__for_each_program(prog, obj) {
649                 codegen("\
650                         \n\
651                                 skel_closenz(skel->progs.%1$s.prog_fd);     \n\
652                         ", bpf_program__name(prog));
653         }
654
655         bpf_object__for_each_map(map, obj) {
656                 if (!get_map_ident(map, ident, sizeof(ident)))
657                         continue;
658                 if (bpf_map__is_internal(map) &&
659                     (bpf_map__map_flags(map) & BPF_F_MMAPABLE))
660                         printf("\tskel_free_map_data(skel->%1$s, skel->maps.%1$s.initial_value, %2$zd);\n",
661                                ident, bpf_map_mmap_sz(map));
662                 codegen("\
663                         \n\
664                                 skel_closenz(skel->maps.%1$s.map_fd);       \n\
665                         ", ident);
666         }
667         codegen("\
668                 \n\
669                         skel_free(skel);                                    \n\
670                 }                                                           \n\
671                 ",
672                 obj_name);
673 }
674
675 static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *header_guard)
676 {
677         DECLARE_LIBBPF_OPTS(gen_loader_opts, opts);
678         struct bpf_map *map;
679         char ident[256];
680         int err = 0;
681
682         err = bpf_object__gen_loader(obj, &opts);
683         if (err)
684                 return err;
685
686         err = bpf_object__load(obj);
687         if (err) {
688                 p_err("failed to load object file");
689                 goto out;
690         }
691         /* If there was no error during load then gen_loader_opts
692          * are populated with the loader program.
693          */
694
695         /* finish generating 'struct skel' */
696         codegen("\
697                 \n\
698                 };                                                          \n\
699                 ", obj_name);
700
701
702         codegen_attach_detach(obj, obj_name);
703
704         codegen_destroy(obj, obj_name);
705
706         codegen("\
707                 \n\
708                 static inline struct %1$s *                                 \n\
709                 %1$s__open(void)                                            \n\
710                 {                                                           \n\
711                         struct %1$s *skel;                                  \n\
712                                                                             \n\
713                         skel = skel_alloc(sizeof(*skel));                   \n\
714                         if (!skel)                                          \n\
715                                 goto cleanup;                               \n\
716                         skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
717                 ",
718                 obj_name, opts.data_sz);
719         bpf_object__for_each_map(map, obj) {
720                 const void *mmap_data = NULL;
721                 size_t mmap_size = 0;
722
723                 if (!is_mmapable_map(map, ident, sizeof(ident)))
724                         continue;
725
726                 codegen("\
727                 \n\
728                         {                                                   \n\
729                                 static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
730                 ");
731                 mmap_data = bpf_map__initial_value(map, &mmap_size);
732                 print_hex(mmap_data, mmap_size);
733                 codegen("\
734                 \n\
735                 \";                                                         \n\
736                                                                             \n\
737                                 skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\
738                                                                 sizeof(data) - 1);\n\
739                                 if (!skel->%1$s)                            \n\
740                                         goto cleanup;                       \n\
741                                 skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\
742                         }                                                   \n\
743                         ", ident, bpf_map_mmap_sz(map));
744         }
745         codegen("\
746                 \n\
747                         return skel;                                        \n\
748                 cleanup:                                                    \n\
749                         %1$s__destroy(skel);                                \n\
750                         return NULL;                                        \n\
751                 }                                                           \n\
752                                                                             \n\
753                 static inline int                                           \n\
754                 %1$s__load(struct %1$s *skel)                               \n\
755                 {                                                           \n\
756                         struct bpf_load_and_run_opts opts = {};             \n\
757                         int err;                                            \n\
758                         static const char opts_data[] __attribute__((__aligned__(8))) = \"\\\n\
759                 ",
760                 obj_name);
761         print_hex(opts.data, opts.data_sz);
762         codegen("\
763                 \n\
764                 \";                                                         \n\
765                         static const char opts_insn[] __attribute__((__aligned__(8))) = \"\\\n\
766                 ");
767         print_hex(opts.insns, opts.insns_sz);
768         codegen("\
769                 \n\
770                 \";                                                         \n\
771                                                                             \n\
772                         opts.ctx = (struct bpf_loader_ctx *)skel;           \n\
773                         opts.data_sz = sizeof(opts_data) - 1;               \n\
774                         opts.data = (void *)opts_data;                      \n\
775                         opts.insns_sz = sizeof(opts_insn) - 1;              \n\
776                         opts.insns = (void *)opts_insn;                     \n\
777                                                                             \n\
778                         err = bpf_load_and_run(&opts);                      \n\
779                         if (err < 0)                                        \n\
780                                 return err;                                 \n\
781                 ");
782         bpf_object__for_each_map(map, obj) {
783                 const char *mmap_flags;
784
785                 if (!is_mmapable_map(map, ident, sizeof(ident)))
786                         continue;
787
788                 if (bpf_map__map_flags(map) & BPF_F_RDONLY_PROG)
789                         mmap_flags = "PROT_READ";
790                 else
791                         mmap_flags = "PROT_READ | PROT_WRITE";
792
793                 codegen("\
794                 \n\
795                         skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value,  \n\
796                                                         %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\
797                         if (!skel->%1$s)                                    \n\
798                                 return -ENOMEM;                             \n\
799                         ",
800                        ident, bpf_map_mmap_sz(map), mmap_flags);
801         }
802         codegen("\
803                 \n\
804                         return 0;                                           \n\
805                 }                                                           \n\
806                                                                             \n\
807                 static inline struct %1$s *                                 \n\
808                 %1$s__open_and_load(void)                                   \n\
809                 {                                                           \n\
810                         struct %1$s *skel;                                  \n\
811                                                                             \n\
812                         skel = %1$s__open();                                \n\
813                         if (!skel)                                          \n\
814                                 return NULL;                                \n\
815                         if (%1$s__load(skel)) {                             \n\
816                                 %1$s__destroy(skel);                        \n\
817                                 return NULL;                                \n\
818                         }                                                   \n\
819                         return skel;                                        \n\
820                 }                                                           \n\
821                                                                             \n\
822                 ", obj_name);
823
824         codegen_asserts(obj, obj_name);
825
826         codegen("\
827                 \n\
828                                                                             \n\
829                 #endif /* %s */                                             \n\
830                 ",
831                 header_guard);
832         err = 0;
833 out:
834         return err;
835 }
836
837 static void
838 codegen_maps_skeleton(struct bpf_object *obj, size_t map_cnt, bool mmaped)
839 {
840         struct bpf_map *map;
841         char ident[256];
842         size_t i;
843
844         if (!map_cnt)
845                 return;
846
847         codegen("\
848                 \n\
849                                                                         \n\
850                         /* maps */                                  \n\
851                         s->map_cnt = %zu;                           \n\
852                         s->map_skel_sz = sizeof(*s->maps);          \n\
853                         s->maps = (struct bpf_map_skeleton *)calloc(s->map_cnt, s->map_skel_sz);\n\
854                         if (!s->maps) {                             \n\
855                                 err = -ENOMEM;                      \n\
856                                 goto err;                           \n\
857                         }                                           \n\
858                 ",
859                 map_cnt
860         );
861         i = 0;
862         bpf_object__for_each_map(map, obj) {
863                 if (!get_map_ident(map, ident, sizeof(ident)))
864                         continue;
865
866                 codegen("\
867                         \n\
868                                                                         \n\
869                                 s->maps[%zu].name = \"%s\";         \n\
870                                 s->maps[%zu].map = &obj->maps.%s;   \n\
871                         ",
872                         i, bpf_map__name(map), i, ident);
873                 /* memory-mapped internal maps */
874                 if (mmaped && is_mmapable_map(map, ident, sizeof(ident))) {
875                         printf("\ts->maps[%zu].mmaped = (void **)&obj->%s;\n",
876                                 i, ident);
877                 }
878                 i++;
879         }
880 }
881
882 static void
883 codegen_progs_skeleton(struct bpf_object *obj, size_t prog_cnt, bool populate_links)
884 {
885         struct bpf_program *prog;
886         int i;
887
888         if (!prog_cnt)
889                 return;
890
891         codegen("\
892                 \n\
893                                                                         \n\
894                         /* programs */                              \n\
895                         s->prog_cnt = %zu;                          \n\
896                         s->prog_skel_sz = sizeof(*s->progs);        \n\
897                         s->progs = (struct bpf_prog_skeleton *)calloc(s->prog_cnt, s->prog_skel_sz);\n\
898                         if (!s->progs) {                            \n\
899                                 err = -ENOMEM;                      \n\
900                                 goto err;                           \n\
901                         }                                           \n\
902                 ",
903                 prog_cnt
904         );
905         i = 0;
906         bpf_object__for_each_program(prog, obj) {
907                 codegen("\
908                         \n\
909                                                                         \n\
910                                 s->progs[%1$zu].name = \"%2$s\";    \n\
911                                 s->progs[%1$zu].prog = &obj->progs.%2$s;\n\
912                         ",
913                         i, bpf_program__name(prog));
914
915                 if (populate_links) {
916                         codegen("\
917                                 \n\
918                                         s->progs[%1$zu].link = &obj->links.%2$s;\n\
919                                 ",
920                                 i, bpf_program__name(prog));
921                 }
922                 i++;
923         }
924 }
925
926 static int walk_st_ops_shadow_vars(struct btf *btf, const char *ident,
927                                    const struct btf_type *map_type, __u32 map_type_id)
928 {
929         LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts, .indent_level = 3);
930         const struct btf_type *member_type;
931         __u32 offset, next_offset = 0;
932         const struct btf_member *m;
933         struct btf_dump *d = NULL;
934         const char *member_name;
935         __u32 member_type_id;
936         int i, err = 0, n;
937         int size;
938
939         d = btf_dump__new(btf, codegen_btf_dump_printf, NULL, NULL);
940         if (!d)
941                 return -errno;
942
943         n = btf_vlen(map_type);
944         for (i = 0, m = btf_members(map_type); i < n; i++, m++) {
945                 member_type = skip_mods_and_typedefs(btf, m->type, &member_type_id);
946                 member_name = btf__name_by_offset(btf, m->name_off);
947
948                 offset = m->offset / 8;
949                 if (next_offset < offset)
950                         printf("\t\t\tchar __padding_%d[%d];\n", i, offset - next_offset);
951
952                 switch (btf_kind(member_type)) {
953                 case BTF_KIND_INT:
954                 case BTF_KIND_FLOAT:
955                 case BTF_KIND_ENUM:
956                 case BTF_KIND_ENUM64:
957                         /* scalar type */
958                         printf("\t\t\t");
959                         opts.field_name = member_name;
960                         err = btf_dump__emit_type_decl(d, member_type_id, &opts);
961                         if (err) {
962                                 p_err("Failed to emit type declaration for %s: %d", member_name, err);
963                                 goto out;
964                         }
965                         printf(";\n");
966
967                         size = btf__resolve_size(btf, member_type_id);
968                         if (size < 0) {
969                                 p_err("Failed to resolve size of %s: %d\n", member_name, size);
970                                 err = size;
971                                 goto out;
972                         }
973
974                         next_offset = offset + size;
975                         break;
976
977                 case BTF_KIND_PTR:
978                         if (resolve_func_ptr(btf, m->type, NULL)) {
979                                 /* Function pointer */
980                                 printf("\t\t\tstruct bpf_program *%s;\n", member_name);
981
982                                 next_offset = offset + sizeof(void *);
983                                 break;
984                         }
985                         /* All pointer types are unsupported except for
986                          * function pointers.
987                          */
988                         fallthrough;
989
990                 default:
991                         /* Unsupported types
992                          *
993                          * Types other than scalar types and function
994                          * pointers are currently not supported in order to
995                          * prevent conflicts in the generated code caused
996                          * by multiple definitions. For instance, if the
997                          * struct type FOO is used in a struct_ops map,
998                          * bpftool has to generate definitions for FOO,
999                          * which may result in conflicts if FOO is defined
1000                          * in different skeleton files.
1001                          */
1002                         size = btf__resolve_size(btf, member_type_id);
1003                         if (size < 0) {
1004                                 p_err("Failed to resolve size of %s: %d\n", member_name, size);
1005                                 err = size;
1006                                 goto out;
1007                         }
1008                         printf("\t\t\tchar __unsupported_%d[%d];\n", i, size);
1009
1010                         next_offset = offset + size;
1011                         break;
1012                 }
1013         }
1014
1015         /* Cannot fail since it must be a struct type */
1016         size = btf__resolve_size(btf, map_type_id);
1017         if (next_offset < (__u32)size)
1018                 printf("\t\t\tchar __padding_end[%d];\n", size - next_offset);
1019
1020 out:
1021         btf_dump__free(d);
1022
1023         return err;
1024 }
1025
1026 /* Generate the pointer of the shadow type for a struct_ops map.
1027  *
1028  * This function adds a pointer of the shadow type for a struct_ops map.
1029  * The members of a struct_ops map can be exported through a pointer to a
1030  * shadow type. The user can access these members through the pointer.
1031  *
1032  * A shadow type includes not all members, only members of some types.
1033  * They are scalar types and function pointers. The function pointers are
1034  * translated to the pointer of the struct bpf_program. The scalar types
1035  * are translated to the original type without any modifiers.
1036  *
1037  * Unsupported types will be translated to a char array to occupy the same
1038  * space as the original field, being renamed as __unsupported_*.  The user
1039  * should treat these fields as opaque data.
1040  */
1041 static int gen_st_ops_shadow_type(const char *obj_name, struct btf *btf, const char *ident,
1042                                   const struct bpf_map *map)
1043 {
1044         const struct btf_type *map_type;
1045         const char *type_name;
1046         __u32 map_type_id;
1047         int err;
1048
1049         map_type_id = bpf_map__btf_value_type_id(map);
1050         if (map_type_id == 0)
1051                 return -EINVAL;
1052         map_type = btf__type_by_id(btf, map_type_id);
1053         if (!map_type)
1054                 return -EINVAL;
1055
1056         type_name = btf__name_by_offset(btf, map_type->name_off);
1057
1058         printf("\t\tstruct %s__%s__%s {\n", obj_name, ident, type_name);
1059
1060         err = walk_st_ops_shadow_vars(btf, ident, map_type, map_type_id);
1061         if (err)
1062                 return err;
1063
1064         printf("\t\t} *%s;\n", ident);
1065
1066         return 0;
1067 }
1068
1069 static int gen_st_ops_shadow(const char *obj_name, struct btf *btf, struct bpf_object *obj)
1070 {
1071         int err, st_ops_cnt = 0;
1072         struct bpf_map *map;
1073         char ident[256];
1074
1075         if (!btf)
1076                 return 0;
1077
1078         /* Generate the pointers to shadow types of
1079          * struct_ops maps.
1080          */
1081         bpf_object__for_each_map(map, obj) {
1082                 if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
1083                         continue;
1084                 if (!get_map_ident(map, ident, sizeof(ident)))
1085                         continue;
1086
1087                 if (st_ops_cnt == 0) /* first struct_ops map */
1088                         printf("\tstruct {\n");
1089                 st_ops_cnt++;
1090
1091                 err = gen_st_ops_shadow_type(obj_name, btf, ident, map);
1092                 if (err)
1093                         return err;
1094         }
1095
1096         if (st_ops_cnt)
1097                 printf("\t} struct_ops;\n");
1098
1099         return 0;
1100 }
1101
1102 /* Generate the code to initialize the pointers of shadow types. */
1103 static void gen_st_ops_shadow_init(struct btf *btf, struct bpf_object *obj)
1104 {
1105         struct bpf_map *map;
1106         char ident[256];
1107
1108         if (!btf)
1109                 return;
1110
1111         /* Initialize the pointers to_ops shadow types of
1112          * struct_ops maps.
1113          */
1114         bpf_object__for_each_map(map, obj) {
1115                 if (bpf_map__type(map) != BPF_MAP_TYPE_STRUCT_OPS)
1116                         continue;
1117                 if (!get_map_ident(map, ident, sizeof(ident)))
1118                         continue;
1119                 codegen("\
1120                         \n\
1121                                 obj->struct_ops.%1$s = bpf_map__initial_value(obj->maps.%1$s, NULL);\n\
1122                         \n\
1123                         ", ident);
1124         }
1125 }
1126
1127 static int do_skeleton(int argc, char **argv)
1128 {
1129         char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
1130         size_t map_cnt = 0, prog_cnt = 0, file_sz, mmap_sz;
1131         DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
1132         char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
1133         struct bpf_object *obj = NULL;
1134         const char *file;
1135         char ident[256];
1136         struct bpf_program *prog;
1137         int fd, err = -1;
1138         struct bpf_map *map;
1139         struct btf *btf;
1140         struct stat st;
1141
1142         if (!REQ_ARGS(1)) {
1143                 usage();
1144                 return -1;
1145         }
1146         file = GET_ARG();
1147
1148         while (argc) {
1149                 if (!REQ_ARGS(2))
1150                         return -1;
1151
1152                 if (is_prefix(*argv, "name")) {
1153                         NEXT_ARG();
1154
1155                         if (obj_name[0] != '\0') {
1156                                 p_err("object name already specified");
1157                                 return -1;
1158                         }
1159
1160                         strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
1161                         obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
1162                 } else {
1163                         p_err("unknown arg %s", *argv);
1164                         return -1;
1165                 }
1166
1167                 NEXT_ARG();
1168         }
1169
1170         if (argc) {
1171                 p_err("extra unknown arguments");
1172                 return -1;
1173         }
1174
1175         if (stat(file, &st)) {
1176                 p_err("failed to stat() %s: %s", file, strerror(errno));
1177                 return -1;
1178         }
1179         file_sz = st.st_size;
1180         mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
1181         fd = open(file, O_RDONLY);
1182         if (fd < 0) {
1183                 p_err("failed to open() %s: %s", file, strerror(errno));
1184                 return -1;
1185         }
1186         obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
1187         if (obj_data == MAP_FAILED) {
1188                 obj_data = NULL;
1189                 p_err("failed to mmap() %s: %s", file, strerror(errno));
1190                 goto out;
1191         }
1192         if (obj_name[0] == '\0')
1193                 get_obj_name(obj_name, file);
1194         opts.object_name = obj_name;
1195         if (verifier_logs)
1196                 /* log_level1 + log_level2 + stats, but not stable UAPI */
1197                 opts.kernel_log_level = 1 + 2 + 4;
1198         obj = bpf_object__open_mem(obj_data, file_sz, &opts);
1199         if (!obj) {
1200                 char err_buf[256];
1201
1202                 err = -errno;
1203                 libbpf_strerror(err, err_buf, sizeof(err_buf));
1204                 p_err("failed to open BPF object file: %s", err_buf);
1205                 goto out;
1206         }
1207
1208         bpf_object__for_each_map(map, obj) {
1209                 if (!get_map_ident(map, ident, sizeof(ident))) {
1210                         p_err("ignoring unrecognized internal map '%s'...",
1211                               bpf_map__name(map));
1212                         continue;
1213                 }
1214                 map_cnt++;
1215         }
1216         bpf_object__for_each_program(prog, obj) {
1217                 prog_cnt++;
1218         }
1219
1220         get_header_guard(header_guard, obj_name, "SKEL_H");
1221         if (use_loader) {
1222                 codegen("\
1223                 \n\
1224                 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
1225                 /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */                \n\
1226                 #ifndef %2$s                                                \n\
1227                 #define %2$s                                                \n\
1228                                                                             \n\
1229                 #include <bpf/skel_internal.h>                              \n\
1230                                                                             \n\
1231                 struct %1$s {                                               \n\
1232                         struct bpf_loader_ctx ctx;                          \n\
1233                 ",
1234                 obj_name, header_guard
1235                 );
1236         } else {
1237                 codegen("\
1238                 \n\
1239                 /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */   \n\
1240                                                                             \n\
1241                 /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */                \n\
1242                 #ifndef %2$s                                                \n\
1243                 #define %2$s                                                \n\
1244                                                                             \n\
1245                 #include <errno.h>                                          \n\
1246                 #include <stdlib.h>                                         \n\
1247                 #include <bpf/libbpf.h>                                     \n\
1248                                                                             \n\
1249                 struct %1$s {                                               \n\
1250                         struct bpf_object_skeleton *skeleton;               \n\
1251                         struct bpf_object *obj;                             \n\
1252                 ",
1253                 obj_name, header_guard
1254                 );
1255         }
1256
1257         if (map_cnt) {
1258                 printf("\tstruct {\n");
1259                 bpf_object__for_each_map(map, obj) {
1260                         if (!get_map_ident(map, ident, sizeof(ident)))
1261                                 continue;
1262                         if (use_loader)
1263                                 printf("\t\tstruct bpf_map_desc %s;\n", ident);
1264                         else
1265                                 printf("\t\tstruct bpf_map *%s;\n", ident);
1266                 }
1267                 printf("\t} maps;\n");
1268         }
1269
1270         btf = bpf_object__btf(obj);
1271         err = gen_st_ops_shadow(obj_name, btf, obj);
1272         if (err)
1273                 goto out;
1274
1275         if (prog_cnt) {
1276                 printf("\tstruct {\n");
1277                 bpf_object__for_each_program(prog, obj) {
1278                         if (use_loader)
1279                                 printf("\t\tstruct bpf_prog_desc %s;\n",
1280                                        bpf_program__name(prog));
1281                         else
1282                                 printf("\t\tstruct bpf_program *%s;\n",
1283                                        bpf_program__name(prog));
1284                 }
1285                 printf("\t} progs;\n");
1286                 printf("\tstruct {\n");
1287                 bpf_object__for_each_program(prog, obj) {
1288                         if (use_loader)
1289                                 printf("\t\tint %s_fd;\n",
1290                                        bpf_program__name(prog));
1291                         else
1292                                 printf("\t\tstruct bpf_link *%s;\n",
1293                                        bpf_program__name(prog));
1294                 }
1295                 printf("\t} links;\n");
1296         }
1297
1298         if (btf) {
1299                 err = codegen_datasecs(obj, obj_name);
1300                 if (err)
1301                         goto out;
1302         }
1303         if (use_loader) {
1304                 err = gen_trace(obj, obj_name, header_guard);
1305                 goto out;
1306         }
1307
1308         codegen("\
1309                 \n\
1310                                                                             \n\
1311                 #ifdef __cplusplus                                          \n\
1312                         static inline struct %1$s *open(const struct bpf_object_open_opts *opts = nullptr);\n\
1313                         static inline struct %1$s *open_and_load();         \n\
1314                         static inline int load(struct %1$s *skel);          \n\
1315                         static inline int attach(struct %1$s *skel);        \n\
1316                         static inline void detach(struct %1$s *skel);       \n\
1317                         static inline void destroy(struct %1$s *skel);      \n\
1318                         static inline const void *elf_bytes(size_t *sz);    \n\
1319                 #endif /* __cplusplus */                                    \n\
1320                 };                                                          \n\
1321                                                                             \n\
1322                 static void                                                 \n\
1323                 %1$s__destroy(struct %1$s *obj)                             \n\
1324                 {                                                           \n\
1325                         if (!obj)                                           \n\
1326                                 return;                                     \n\
1327                         if (obj->skeleton)                                  \n\
1328                                 bpf_object__destroy_skeleton(obj->skeleton);\n\
1329                         free(obj);                                          \n\
1330                 }                                                           \n\
1331                                                                             \n\
1332                 static inline int                                           \n\
1333                 %1$s__create_skeleton(struct %1$s *obj);                    \n\
1334                                                                             \n\
1335                 static inline struct %1$s *                                 \n\
1336                 %1$s__open_opts(const struct bpf_object_open_opts *opts)    \n\
1337                 {                                                           \n\
1338                         struct %1$s *obj;                                   \n\
1339                         int err;                                            \n\
1340                                                                             \n\
1341                         obj = (struct %1$s *)calloc(1, sizeof(*obj));       \n\
1342                         if (!obj) {                                         \n\
1343                                 errno = ENOMEM;                             \n\
1344                                 return NULL;                                \n\
1345                         }                                                   \n\
1346                                                                             \n\
1347                         err = %1$s__create_skeleton(obj);                   \n\
1348                         if (err)                                            \n\
1349                                 goto err_out;                               \n\
1350                                                                             \n\
1351                         err = bpf_object__open_skeleton(obj->skeleton, opts);\n\
1352                         if (err)                                            \n\
1353                                 goto err_out;                               \n\
1354                                                                             \n\
1355                 ", obj_name);
1356
1357         gen_st_ops_shadow_init(btf, obj);
1358
1359         codegen("\
1360                 \n\
1361                         return obj;                                         \n\
1362                 err_out:                                                    \n\
1363                         %1$s__destroy(obj);                                 \n\
1364                         errno = -err;                                       \n\
1365                         return NULL;                                        \n\
1366                 }                                                           \n\
1367                                                                             \n\
1368                 static inline struct %1$s *                                 \n\
1369                 %1$s__open(void)                                            \n\
1370                 {                                                           \n\
1371                         return %1$s__open_opts(NULL);                       \n\
1372                 }                                                           \n\
1373                                                                             \n\
1374                 static inline int                                           \n\
1375                 %1$s__load(struct %1$s *obj)                                \n\
1376                 {                                                           \n\
1377                         return bpf_object__load_skeleton(obj->skeleton);    \n\
1378                 }                                                           \n\
1379                                                                             \n\
1380                 static inline struct %1$s *                                 \n\
1381                 %1$s__open_and_load(void)                                   \n\
1382                 {                                                           \n\
1383                         struct %1$s *obj;                                   \n\
1384                         int err;                                            \n\
1385                                                                             \n\
1386                         obj = %1$s__open();                                 \n\
1387                         if (!obj)                                           \n\
1388                                 return NULL;                                \n\
1389                         err = %1$s__load(obj);                              \n\
1390                         if (err) {                                          \n\
1391                                 %1$s__destroy(obj);                         \n\
1392                                 errno = -err;                               \n\
1393                                 return NULL;                                \n\
1394                         }                                                   \n\
1395                         return obj;                                         \n\
1396                 }                                                           \n\
1397                                                                             \n\
1398                 static inline int                                           \n\
1399                 %1$s__attach(struct %1$s *obj)                              \n\
1400                 {                                                           \n\
1401                         return bpf_object__attach_skeleton(obj->skeleton);  \n\
1402                 }                                                           \n\
1403                                                                             \n\
1404                 static inline void                                          \n\
1405                 %1$s__detach(struct %1$s *obj)                              \n\
1406                 {                                                           \n\
1407                         bpf_object__detach_skeleton(obj->skeleton);         \n\
1408                 }                                                           \n\
1409                 ",
1410                 obj_name
1411         );
1412
1413         codegen("\
1414                 \n\
1415                                                                             \n\
1416                 static inline const void *%1$s__elf_bytes(size_t *sz);      \n\
1417                                                                             \n\
1418                 static inline int                                           \n\
1419                 %1$s__create_skeleton(struct %1$s *obj)                     \n\
1420                 {                                                           \n\
1421                         struct bpf_object_skeleton *s;                      \n\
1422                         int err;                                            \n\
1423                                                                             \n\
1424                         s = (struct bpf_object_skeleton *)calloc(1, sizeof(*s));\n\
1425                         if (!s) {                                           \n\
1426                                 err = -ENOMEM;                              \n\
1427                                 goto err;                                   \n\
1428                         }                                                   \n\
1429                                                                             \n\
1430                         s->sz = sizeof(*s);                                 \n\
1431                         s->name = \"%1$s\";                                 \n\
1432                         s->obj = &obj->obj;                                 \n\
1433                 ",
1434                 obj_name
1435         );
1436
1437         codegen_maps_skeleton(obj, map_cnt, true /*mmaped*/);
1438         codegen_progs_skeleton(obj, prog_cnt, true /*populate_links*/);
1439
1440         codegen("\
1441                 \n\
1442                                                                             \n\
1443                         s->data = %1$s__elf_bytes(&s->data_sz);             \n\
1444                                                                             \n\
1445                         obj->skeleton = s;                                  \n\
1446                         return 0;                                           \n\
1447                 err:                                                        \n\
1448                         bpf_object__destroy_skeleton(s);                    \n\
1449                         return err;                                         \n\
1450                 }                                                           \n\
1451                                                                             \n\
1452                 static inline const void *%1$s__elf_bytes(size_t *sz)       \n\
1453                 {                                                           \n\
1454                         static const char data[] __attribute__((__aligned__(8))) = \"\\\n\
1455                 ",
1456                 obj_name
1457         );
1458
1459         /* embed contents of BPF object file */
1460         print_hex(obj_data, file_sz);
1461
1462         codegen("\
1463                 \n\
1464                 \";                                                         \n\
1465                                                                             \n\
1466                         *sz = sizeof(data) - 1;                             \n\
1467                         return (const void *)data;                          \n\
1468                 }                                                           \n\
1469                                                                             \n\
1470                 #ifdef __cplusplus                                          \n\
1471                 struct %1$s *%1$s::open(const struct bpf_object_open_opts *opts) { return %1$s__open_opts(opts); }\n\
1472                 struct %1$s *%1$s::open_and_load() { return %1$s__open_and_load(); }    \n\
1473                 int %1$s::load(struct %1$s *skel) { return %1$s__load(skel); }          \n\
1474                 int %1$s::attach(struct %1$s *skel) { return %1$s__attach(skel); }      \n\
1475                 void %1$s::detach(struct %1$s *skel) { %1$s__detach(skel); }            \n\
1476                 void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }          \n\
1477                 const void *%1$s::elf_bytes(size_t *sz) { return %1$s__elf_bytes(sz); } \n\
1478                 #endif /* __cplusplus */                                    \n\
1479                                                                             \n\
1480                 ",
1481                 obj_name);
1482
1483         codegen_asserts(obj, obj_name);
1484
1485         codegen("\
1486                 \n\
1487                                                                             \n\
1488                 #endif /* %1$s */                                           \n\
1489                 ",
1490                 header_guard);
1491         err = 0;
1492 out:
1493         bpf_object__close(obj);
1494         if (obj_data)
1495                 munmap(obj_data, mmap_sz);
1496         close(fd);
1497         return err;
1498 }
1499
1500 /* Subskeletons are like skeletons, except they don't own the bpf_object,
1501  * associated maps, links, etc. Instead, they know about the existence of
1502  * variables, maps, programs and are able to find their locations
1503  * _at runtime_ from an already loaded bpf_object.
1504  *
1505  * This allows for library-like BPF objects to have userspace counterparts
1506  * with access to their own items without having to know anything about the
1507  * final BPF object that the library was linked into.
1508  */
1509 static int do_subskeleton(int argc, char **argv)
1510 {
1511         char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SUBSKEL_H__")];
1512         size_t i, len, file_sz, map_cnt = 0, prog_cnt = 0, mmap_sz, var_cnt = 0, var_idx = 0;
1513         DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts);
1514         char obj_name[MAX_OBJ_NAME_LEN] = "", *obj_data;
1515         struct bpf_object *obj = NULL;
1516         const char *file, *var_name;
1517         char ident[256];
1518         int fd, err = -1, map_type_id;
1519         const struct bpf_map *map;
1520         struct bpf_program *prog;
1521         struct btf *btf;
1522         const struct btf_type *map_type, *var_type;
1523         const struct btf_var_secinfo *var;
1524         struct stat st;
1525
1526         if (!REQ_ARGS(1)) {
1527                 usage();
1528                 return -1;
1529         }
1530         file = GET_ARG();
1531
1532         while (argc) {
1533                 if (!REQ_ARGS(2))
1534                         return -1;
1535
1536                 if (is_prefix(*argv, "name")) {
1537                         NEXT_ARG();
1538
1539                         if (obj_name[0] != '\0') {
1540                                 p_err("object name already specified");
1541                                 return -1;
1542                         }
1543
1544                         strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
1545                         obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
1546                 } else {
1547                         p_err("unknown arg %s", *argv);
1548                         return -1;
1549                 }
1550
1551                 NEXT_ARG();
1552         }
1553
1554         if (argc) {
1555                 p_err("extra unknown arguments");
1556                 return -1;
1557         }
1558
1559         if (use_loader) {
1560                 p_err("cannot use loader for subskeletons");
1561                 return -1;
1562         }
1563
1564         if (stat(file, &st)) {
1565                 p_err("failed to stat() %s: %s", file, strerror(errno));
1566                 return -1;
1567         }
1568         file_sz = st.st_size;
1569         mmap_sz = roundup(file_sz, sysconf(_SC_PAGE_SIZE));
1570         fd = open(file, O_RDONLY);
1571         if (fd < 0) {
1572                 p_err("failed to open() %s: %s", file, strerror(errno));
1573                 return -1;
1574         }
1575         obj_data = mmap(NULL, mmap_sz, PROT_READ, MAP_PRIVATE, fd, 0);
1576         if (obj_data == MAP_FAILED) {
1577                 obj_data = NULL;
1578                 p_err("failed to mmap() %s: %s", file, strerror(errno));
1579                 goto out;
1580         }
1581         if (obj_name[0] == '\0')
1582                 get_obj_name(obj_name, file);
1583
1584         /* The empty object name allows us to use bpf_map__name and produce
1585          * ELF section names out of it. (".data" instead of "obj.data")
1586          */
1587         opts.object_name = "";
1588         obj = bpf_object__open_mem(obj_data, file_sz, &opts);
1589         if (!obj) {
1590                 char err_buf[256];
1591
1592                 libbpf_strerror(errno, err_buf, sizeof(err_buf));
1593                 p_err("failed to open BPF object file: %s", err_buf);
1594                 obj = NULL;
1595                 goto out;
1596         }
1597
1598         btf = bpf_object__btf(obj);
1599         if (!btf) {
1600                 err = -1;
1601                 p_err("need btf type information for %s", obj_name);
1602                 goto out;
1603         }
1604
1605         bpf_object__for_each_program(prog, obj) {
1606                 prog_cnt++;
1607         }
1608
1609         /* First, count how many variables we have to find.
1610          * We need this in advance so the subskel can allocate the right
1611          * amount of storage.
1612          */
1613         bpf_object__for_each_map(map, obj) {
1614                 if (!get_map_ident(map, ident, sizeof(ident)))
1615                         continue;
1616
1617                 /* Also count all maps that have a name */
1618                 map_cnt++;
1619
1620                 if (!is_mmapable_map(map, ident, sizeof(ident)))
1621                         continue;
1622
1623                 map_type_id = bpf_map__btf_value_type_id(map);
1624                 if (map_type_id <= 0) {
1625                         err = map_type_id;
1626                         goto out;
1627                 }
1628                 map_type = btf__type_by_id(btf, map_type_id);
1629
1630                 var = btf_var_secinfos(map_type);
1631                 len = btf_vlen(map_type);
1632                 for (i = 0; i < len; i++, var++) {
1633                         var_type = btf__type_by_id(btf, var->type);
1634
1635                         if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
1636                                 continue;
1637
1638                         var_cnt++;
1639                 }
1640         }
1641
1642         get_header_guard(header_guard, obj_name, "SUBSKEL_H");
1643         codegen("\
1644         \n\
1645         /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */           \n\
1646                                                                             \n\
1647         /* THIS FILE IS AUTOGENERATED! */                                   \n\
1648         #ifndef %2$s                                                        \n\
1649         #define %2$s                                                        \n\
1650                                                                             \n\
1651         #include <errno.h>                                                  \n\
1652         #include <stdlib.h>                                                 \n\
1653         #include <bpf/libbpf.h>                                             \n\
1654                                                                             \n\
1655         struct %1$s {                                                       \n\
1656                 struct bpf_object *obj;                                     \n\
1657                 struct bpf_object_subskeleton *subskel;                     \n\
1658         ", obj_name, header_guard);
1659
1660         if (map_cnt) {
1661                 printf("\tstruct {\n");
1662                 bpf_object__for_each_map(map, obj) {
1663                         if (!get_map_ident(map, ident, sizeof(ident)))
1664                                 continue;
1665                         printf("\t\tstruct bpf_map *%s;\n", ident);
1666                 }
1667                 printf("\t} maps;\n");
1668         }
1669
1670         err = gen_st_ops_shadow(obj_name, btf, obj);
1671         if (err)
1672                 goto out;
1673
1674         if (prog_cnt) {
1675                 printf("\tstruct {\n");
1676                 bpf_object__for_each_program(prog, obj) {
1677                         printf("\t\tstruct bpf_program *%s;\n",
1678                                 bpf_program__name(prog));
1679                 }
1680                 printf("\t} progs;\n");
1681         }
1682
1683         err = codegen_subskel_datasecs(obj, obj_name);
1684         if (err)
1685                 goto out;
1686
1687         /* emit code that will allocate enough storage for all symbols */
1688         codegen("\
1689                 \n\
1690                                                                             \n\
1691                 #ifdef __cplusplus                                          \n\
1692                         static inline struct %1$s *open(const struct bpf_object *src);\n\
1693                         static inline void destroy(struct %1$s *skel);      \n\
1694                 #endif /* __cplusplus */                                    \n\
1695                 };                                                          \n\
1696                                                                             \n\
1697                 static inline void                                          \n\
1698                 %1$s__destroy(struct %1$s *skel)                            \n\
1699                 {                                                           \n\
1700                         if (!skel)                                          \n\
1701                                 return;                                     \n\
1702                         if (skel->subskel)                                  \n\
1703                                 bpf_object__destroy_subskeleton(skel->subskel);\n\
1704                         free(skel);                                         \n\
1705                 }                                                           \n\
1706                                                                             \n\
1707                 static inline struct %1$s *                                 \n\
1708                 %1$s__open(const struct bpf_object *src)                    \n\
1709                 {                                                           \n\
1710                         struct %1$s *obj;                                   \n\
1711                         struct bpf_object_subskeleton *s;                   \n\
1712                         int err;                                            \n\
1713                                                                             \n\
1714                         obj = (struct %1$s *)calloc(1, sizeof(*obj));       \n\
1715                         if (!obj) {                                         \n\
1716                                 err = -ENOMEM;                              \n\
1717                                 goto err;                                   \n\
1718                         }                                                   \n\
1719                         s = (struct bpf_object_subskeleton *)calloc(1, sizeof(*s));\n\
1720                         if (!s) {                                           \n\
1721                                 err = -ENOMEM;                              \n\
1722                                 goto err;                                   \n\
1723                         }                                                   \n\
1724                         s->sz = sizeof(*s);                                 \n\
1725                         s->obj = src;                                       \n\
1726                         s->var_skel_sz = sizeof(*s->vars);                  \n\
1727                         obj->subskel = s;                                   \n\
1728                                                                             \n\
1729                         /* vars */                                          \n\
1730                         s->var_cnt = %2$d;                                  \n\
1731                         s->vars = (struct bpf_var_skeleton *)calloc(%2$d, sizeof(*s->vars));\n\
1732                         if (!s->vars) {                                     \n\
1733                                 err = -ENOMEM;                              \n\
1734                                 goto err;                                   \n\
1735                         }                                                   \n\
1736                 ",
1737                 obj_name, var_cnt
1738         );
1739
1740         /* walk through each symbol and emit the runtime representation */
1741         bpf_object__for_each_map(map, obj) {
1742                 if (!is_mmapable_map(map, ident, sizeof(ident)))
1743                         continue;
1744
1745                 map_type_id = bpf_map__btf_value_type_id(map);
1746                 if (map_type_id <= 0)
1747                         /* skip over internal maps with no type*/
1748                         continue;
1749
1750                 map_type = btf__type_by_id(btf, map_type_id);
1751                 var = btf_var_secinfos(map_type);
1752                 len = btf_vlen(map_type);
1753                 for (i = 0; i < len; i++, var++) {
1754                         var_type = btf__type_by_id(btf, var->type);
1755                         var_name = btf__name_by_offset(btf, var_type->name_off);
1756
1757                         if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
1758                                 continue;
1759
1760                         /* Note that we use the dot prefix in .data as the
1761                          * field access operator i.e. maps%s becomes maps.data
1762                          */
1763                         codegen("\
1764                         \n\
1765                                                                             \n\
1766                                 s->vars[%3$d].name = \"%1$s\";              \n\
1767                                 s->vars[%3$d].map = &obj->maps.%2$s;        \n\
1768                                 s->vars[%3$d].addr = (void **) &obj->%2$s.%1$s;\n\
1769                         ", var_name, ident, var_idx);
1770
1771                         var_idx++;
1772                 }
1773         }
1774
1775         codegen_maps_skeleton(obj, map_cnt, false /*mmaped*/);
1776         codegen_progs_skeleton(obj, prog_cnt, false /*links*/);
1777
1778         codegen("\
1779                 \n\
1780                                                                             \n\
1781                         err = bpf_object__open_subskeleton(s);              \n\
1782                         if (err)                                            \n\
1783                                 goto err;                                   \n\
1784                                                                             \n\
1785                 ");
1786
1787         gen_st_ops_shadow_init(btf, obj);
1788
1789         codegen("\
1790                 \n\
1791                         return obj;                                         \n\
1792                 err:                                                        \n\
1793                         %1$s__destroy(obj);                                 \n\
1794                         errno = -err;                                       \n\
1795                         return NULL;                                        \n\
1796                 }                                                           \n\
1797                                                                             \n\
1798                 #ifdef __cplusplus                                          \n\
1799                 struct %1$s *%1$s::open(const struct bpf_object *src) { return %1$s__open(src); }\n\
1800                 void %1$s::destroy(struct %1$s *skel) { %1$s__destroy(skel); }\n\
1801                 #endif /* __cplusplus */                                    \n\
1802                                                                             \n\
1803                 #endif /* %2$s */                                           \n\
1804                 ",
1805                 obj_name, header_guard);
1806         err = 0;
1807 out:
1808         bpf_object__close(obj);
1809         if (obj_data)
1810                 munmap(obj_data, mmap_sz);
1811         close(fd);
1812         return err;
1813 }
1814
1815 static int do_object(int argc, char **argv)
1816 {
1817         struct bpf_linker *linker;
1818         const char *output_file, *file;
1819         int err = 0;
1820
1821         if (!REQ_ARGS(2)) {
1822                 usage();
1823                 return -1;
1824         }
1825
1826         output_file = GET_ARG();
1827
1828         linker = bpf_linker__new(output_file, NULL);
1829         if (!linker) {
1830                 p_err("failed to create BPF linker instance");
1831                 return -1;
1832         }
1833
1834         while (argc) {
1835                 file = GET_ARG();
1836
1837                 err = bpf_linker__add_file(linker, file, NULL);
1838                 if (err) {
1839                         p_err("failed to link '%s': %s (%d)", file, strerror(errno), errno);
1840                         goto out;
1841                 }
1842         }
1843
1844         err = bpf_linker__finalize(linker);
1845         if (err) {
1846                 p_err("failed to finalize ELF file: %s (%d)", strerror(errno), errno);
1847                 goto out;
1848         }
1849
1850         err = 0;
1851 out:
1852         bpf_linker__free(linker);
1853         return err;
1854 }
1855
1856 static int do_help(int argc, char **argv)
1857 {
1858         if (json_output) {
1859                 jsonw_null(json_wtr);
1860                 return 0;
1861         }
1862
1863         fprintf(stderr,
1864                 "Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
1865                 "       %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
1866                 "       %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
1867                 "       %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
1868                 "       %1$s %2$s help\n"
1869                 "\n"
1870                 "       " HELP_SPEC_OPTIONS " |\n"
1871                 "                    {-L|--use-loader} }\n"
1872                 "",
1873                 bin_name, "gen");
1874
1875         return 0;
1876 }
1877
1878 static int btf_save_raw(const struct btf *btf, const char *path)
1879 {
1880         const void *data;
1881         FILE *f = NULL;
1882         __u32 data_sz;
1883         int err = 0;
1884
1885         data = btf__raw_data(btf, &data_sz);
1886         if (!data)
1887                 return -ENOMEM;
1888
1889         f = fopen(path, "wb");
1890         if (!f)
1891                 return -errno;
1892
1893         if (fwrite(data, 1, data_sz, f) != data_sz)
1894                 err = -errno;
1895
1896         fclose(f);
1897         return err;
1898 }
1899
1900 struct btfgen_info {
1901         struct btf *src_btf;
1902         struct btf *marked_btf; /* btf structure used to mark used types */
1903 };
1904
1905 static size_t btfgen_hash_fn(long key, void *ctx)
1906 {
1907         return key;
1908 }
1909
1910 static bool btfgen_equal_fn(long k1, long k2, void *ctx)
1911 {
1912         return k1 == k2;
1913 }
1914
1915 static void btfgen_free_info(struct btfgen_info *info)
1916 {
1917         if (!info)
1918                 return;
1919
1920         btf__free(info->src_btf);
1921         btf__free(info->marked_btf);
1922
1923         free(info);
1924 }
1925
1926 static struct btfgen_info *
1927 btfgen_new_info(const char *targ_btf_path)
1928 {
1929         struct btfgen_info *info;
1930         int err;
1931
1932         info = calloc(1, sizeof(*info));
1933         if (!info)
1934                 return NULL;
1935
1936         info->src_btf = btf__parse(targ_btf_path, NULL);
1937         if (!info->src_btf) {
1938                 err = -errno;
1939                 p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
1940                 goto err_out;
1941         }
1942
1943         info->marked_btf = btf__parse(targ_btf_path, NULL);
1944         if (!info->marked_btf) {
1945                 err = -errno;
1946                 p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
1947                 goto err_out;
1948         }
1949
1950         return info;
1951
1952 err_out:
1953         btfgen_free_info(info);
1954         errno = -err;
1955         return NULL;
1956 }
1957
1958 #define MARKED UINT32_MAX
1959
1960 static void btfgen_mark_member(struct btfgen_info *info, int type_id, int idx)
1961 {
1962         const struct btf_type *t = btf__type_by_id(info->marked_btf, type_id);
1963         struct btf_member *m = btf_members(t) + idx;
1964
1965         m->name_off = MARKED;
1966 }
1967
1968 static int
1969 btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_pointers)
1970 {
1971         const struct btf_type *btf_type = btf__type_by_id(info->src_btf, type_id);
1972         struct btf_type *cloned_type;
1973         struct btf_param *param;
1974         struct btf_array *array;
1975         int err, i;
1976
1977         if (type_id == 0)
1978                 return 0;
1979
1980         /* mark type on cloned BTF as used */
1981         cloned_type = (struct btf_type *) btf__type_by_id(info->marked_btf, type_id);
1982         cloned_type->name_off = MARKED;
1983
1984         /* recursively mark other types needed by it */
1985         switch (btf_kind(btf_type)) {
1986         case BTF_KIND_UNKN:
1987         case BTF_KIND_INT:
1988         case BTF_KIND_FLOAT:
1989         case BTF_KIND_ENUM:
1990         case BTF_KIND_ENUM64:
1991         case BTF_KIND_STRUCT:
1992         case BTF_KIND_UNION:
1993                 break;
1994         case BTF_KIND_PTR:
1995                 if (follow_pointers) {
1996                         err = btfgen_mark_type(info, btf_type->type, follow_pointers);
1997                         if (err)
1998                                 return err;
1999                 }
2000                 break;
2001         case BTF_KIND_CONST:
2002         case BTF_KIND_RESTRICT:
2003         case BTF_KIND_VOLATILE:
2004         case BTF_KIND_TYPEDEF:
2005                 err = btfgen_mark_type(info, btf_type->type, follow_pointers);
2006                 if (err)
2007                         return err;
2008                 break;
2009         case BTF_KIND_ARRAY:
2010                 array = btf_array(btf_type);
2011
2012                 /* mark array type */
2013                 err = btfgen_mark_type(info, array->type, follow_pointers);
2014                 /* mark array's index type */
2015                 err = err ? : btfgen_mark_type(info, array->index_type, follow_pointers);
2016                 if (err)
2017                         return err;
2018                 break;
2019         case BTF_KIND_FUNC_PROTO:
2020                 /* mark ret type */
2021                 err = btfgen_mark_type(info, btf_type->type, follow_pointers);
2022                 if (err)
2023                         return err;
2024
2025                 /* mark parameters types */
2026                 param = btf_params(btf_type);
2027                 for (i = 0; i < btf_vlen(btf_type); i++) {
2028                         err = btfgen_mark_type(info, param->type, follow_pointers);
2029                         if (err)
2030                                 return err;
2031                         param++;
2032                 }
2033                 break;
2034         /* tells if some other type needs to be handled */
2035         default:
2036                 p_err("unsupported kind: %s (%d)", btf_kind_str(btf_type), type_id);
2037                 return -EINVAL;
2038         }
2039
2040         return 0;
2041 }
2042
2043 static int btfgen_record_field_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2044 {
2045         struct btf *btf = info->src_btf;
2046         const struct btf_type *btf_type;
2047         struct btf_member *btf_member;
2048         struct btf_array *array;
2049         unsigned int type_id = targ_spec->root_type_id;
2050         int idx, err;
2051
2052         /* mark root type */
2053         btf_type = btf__type_by_id(btf, type_id);
2054         err = btfgen_mark_type(info, type_id, false);
2055         if (err)
2056                 return err;
2057
2058         /* mark types for complex types (arrays, unions, structures) */
2059         for (int i = 1; i < targ_spec->raw_len; i++) {
2060                 /* skip typedefs and mods */
2061                 while (btf_is_mod(btf_type) || btf_is_typedef(btf_type)) {
2062                         type_id = btf_type->type;
2063                         btf_type = btf__type_by_id(btf, type_id);
2064                 }
2065
2066                 switch (btf_kind(btf_type)) {
2067                 case BTF_KIND_STRUCT:
2068                 case BTF_KIND_UNION:
2069                         idx = targ_spec->raw_spec[i];
2070                         btf_member = btf_members(btf_type) + idx;
2071
2072                         /* mark member */
2073                         btfgen_mark_member(info, type_id, idx);
2074
2075                         /* mark member's type */
2076                         type_id = btf_member->type;
2077                         btf_type = btf__type_by_id(btf, type_id);
2078                         err = btfgen_mark_type(info, type_id, false);
2079                         if (err)
2080                                 return err;
2081                         break;
2082                 case BTF_KIND_ARRAY:
2083                         array = btf_array(btf_type);
2084                         type_id = array->type;
2085                         btf_type = btf__type_by_id(btf, type_id);
2086                         break;
2087                 default:
2088                         p_err("unsupported kind: %s (%d)",
2089                               btf_kind_str(btf_type), btf_type->type);
2090                         return -EINVAL;
2091                 }
2092         }
2093
2094         return 0;
2095 }
2096
2097 /* Mark types, members, and member types. Compared to btfgen_record_field_relo,
2098  * this function does not rely on the target spec for inferring members, but
2099  * uses the associated BTF.
2100  *
2101  * The `behind_ptr` argument is used to stop marking of composite types reached
2102  * through a pointer. This way, we can keep BTF size in check while providing
2103  * reasonable match semantics.
2104  */
2105 static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool behind_ptr)
2106 {
2107         const struct btf_type *btf_type;
2108         struct btf *btf = info->src_btf;
2109         struct btf_type *cloned_type;
2110         int i, err;
2111
2112         if (type_id == 0)
2113                 return 0;
2114
2115         btf_type = btf__type_by_id(btf, type_id);
2116         /* mark type on cloned BTF as used */
2117         cloned_type = (struct btf_type *)btf__type_by_id(info->marked_btf, type_id);
2118         cloned_type->name_off = MARKED;
2119
2120         switch (btf_kind(btf_type)) {
2121         case BTF_KIND_UNKN:
2122         case BTF_KIND_INT:
2123         case BTF_KIND_FLOAT:
2124         case BTF_KIND_ENUM:
2125         case BTF_KIND_ENUM64:
2126                 break;
2127         case BTF_KIND_STRUCT:
2128         case BTF_KIND_UNION: {
2129                 struct btf_member *m = btf_members(btf_type);
2130                 __u16 vlen = btf_vlen(btf_type);
2131
2132                 if (behind_ptr)
2133                         break;
2134
2135                 for (i = 0; i < vlen; i++, m++) {
2136                         /* mark member */
2137                         btfgen_mark_member(info, type_id, i);
2138
2139                         /* mark member's type */
2140                         err = btfgen_mark_type_match(info, m->type, false);
2141                         if (err)
2142                                 return err;
2143                 }
2144                 break;
2145         }
2146         case BTF_KIND_CONST:
2147         case BTF_KIND_FWD:
2148         case BTF_KIND_RESTRICT:
2149         case BTF_KIND_TYPEDEF:
2150         case BTF_KIND_VOLATILE:
2151                 return btfgen_mark_type_match(info, btf_type->type, behind_ptr);
2152         case BTF_KIND_PTR:
2153                 return btfgen_mark_type_match(info, btf_type->type, true);
2154         case BTF_KIND_ARRAY: {
2155                 struct btf_array *array;
2156
2157                 array = btf_array(btf_type);
2158                 /* mark array type */
2159                 err = btfgen_mark_type_match(info, array->type, false);
2160                 /* mark array's index type */
2161                 err = err ? : btfgen_mark_type_match(info, array->index_type, false);
2162                 if (err)
2163                         return err;
2164                 break;
2165         }
2166         case BTF_KIND_FUNC_PROTO: {
2167                 __u16 vlen = btf_vlen(btf_type);
2168                 struct btf_param *param;
2169
2170                 /* mark ret type */
2171                 err = btfgen_mark_type_match(info, btf_type->type, false);
2172                 if (err)
2173                         return err;
2174
2175                 /* mark parameters types */
2176                 param = btf_params(btf_type);
2177                 for (i = 0; i < vlen; i++) {
2178                         err = btfgen_mark_type_match(info, param->type, false);
2179                         if (err)
2180                                 return err;
2181                         param++;
2182                 }
2183                 break;
2184         }
2185         /* tells if some other type needs to be handled */
2186         default:
2187                 p_err("unsupported kind: %s (%d)", btf_kind_str(btf_type), type_id);
2188                 return -EINVAL;
2189         }
2190
2191         return 0;
2192 }
2193
2194 /* Mark types, members, and member types. Compared to btfgen_record_field_relo,
2195  * this function does not rely on the target spec for inferring members, but
2196  * uses the associated BTF.
2197  */
2198 static int btfgen_record_type_match_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2199 {
2200         return btfgen_mark_type_match(info, targ_spec->root_type_id, false);
2201 }
2202
2203 static int btfgen_record_type_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2204 {
2205         return btfgen_mark_type(info, targ_spec->root_type_id, true);
2206 }
2207
2208 static int btfgen_record_enumval_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec)
2209 {
2210         return btfgen_mark_type(info, targ_spec->root_type_id, false);
2211 }
2212
2213 static int btfgen_record_reloc(struct btfgen_info *info, struct bpf_core_spec *res)
2214 {
2215         switch (res->relo_kind) {
2216         case BPF_CORE_FIELD_BYTE_OFFSET:
2217         case BPF_CORE_FIELD_BYTE_SIZE:
2218         case BPF_CORE_FIELD_EXISTS:
2219         case BPF_CORE_FIELD_SIGNED:
2220         case BPF_CORE_FIELD_LSHIFT_U64:
2221         case BPF_CORE_FIELD_RSHIFT_U64:
2222                 return btfgen_record_field_relo(info, res);
2223         case BPF_CORE_TYPE_ID_LOCAL: /* BPF_CORE_TYPE_ID_LOCAL doesn't require kernel BTF */
2224                 return 0;
2225         case BPF_CORE_TYPE_ID_TARGET:
2226         case BPF_CORE_TYPE_EXISTS:
2227         case BPF_CORE_TYPE_SIZE:
2228                 return btfgen_record_type_relo(info, res);
2229         case BPF_CORE_TYPE_MATCHES:
2230                 return btfgen_record_type_match_relo(info, res);
2231         case BPF_CORE_ENUMVAL_EXISTS:
2232         case BPF_CORE_ENUMVAL_VALUE:
2233                 return btfgen_record_enumval_relo(info, res);
2234         default:
2235                 return -EINVAL;
2236         }
2237 }
2238
2239 static struct bpf_core_cand_list *
2240 btfgen_find_cands(const struct btf *local_btf, const struct btf *targ_btf, __u32 local_id)
2241 {
2242         const struct btf_type *local_type;
2243         struct bpf_core_cand_list *cands = NULL;
2244         struct bpf_core_cand local_cand = {};
2245         size_t local_essent_len;
2246         const char *local_name;
2247         int err;
2248
2249         local_cand.btf = local_btf;
2250         local_cand.id = local_id;
2251
2252         local_type = btf__type_by_id(local_btf, local_id);
2253         if (!local_type) {
2254                 err = -EINVAL;
2255                 goto err_out;
2256         }
2257
2258         local_name = btf__name_by_offset(local_btf, local_type->name_off);
2259         if (!local_name) {
2260                 err = -EINVAL;
2261                 goto err_out;
2262         }
2263         local_essent_len = bpf_core_essential_name_len(local_name);
2264
2265         cands = calloc(1, sizeof(*cands));
2266         if (!cands)
2267                 return NULL;
2268
2269         err = bpf_core_add_cands(&local_cand, local_essent_len, targ_btf, "vmlinux", 1, cands);
2270         if (err)
2271                 goto err_out;
2272
2273         return cands;
2274
2275 err_out:
2276         bpf_core_free_cands(cands);
2277         errno = -err;
2278         return NULL;
2279 }
2280
2281 /* Record relocation information for a single BPF object */
2282 static int btfgen_record_obj(struct btfgen_info *info, const char *obj_path)
2283 {
2284         const struct btf_ext_info_sec *sec;
2285         const struct bpf_core_relo *relo;
2286         const struct btf_ext_info *seg;
2287         struct hashmap_entry *entry;
2288         struct hashmap *cand_cache = NULL;
2289         struct btf_ext *btf_ext = NULL;
2290         unsigned int relo_idx;
2291         struct btf *btf = NULL;
2292         size_t i;
2293         int err;
2294
2295         btf = btf__parse(obj_path, &btf_ext);
2296         if (!btf) {
2297                 err = -errno;
2298                 p_err("failed to parse BPF object '%s': %s", obj_path, strerror(errno));
2299                 return err;
2300         }
2301
2302         if (!btf_ext) {
2303                 p_err("failed to parse BPF object '%s': section %s not found",
2304                       obj_path, BTF_EXT_ELF_SEC);
2305                 err = -EINVAL;
2306                 goto out;
2307         }
2308
2309         if (btf_ext->core_relo_info.len == 0) {
2310                 err = 0;
2311                 goto out;
2312         }
2313
2314         cand_cache = hashmap__new(btfgen_hash_fn, btfgen_equal_fn, NULL);
2315         if (IS_ERR(cand_cache)) {
2316                 err = PTR_ERR(cand_cache);
2317                 goto out;
2318         }
2319
2320         seg = &btf_ext->core_relo_info;
2321         for_each_btf_ext_sec(seg, sec) {
2322                 for_each_btf_ext_rec(seg, sec, relo_idx, relo) {
2323                         struct bpf_core_spec specs_scratch[3] = {};
2324                         struct bpf_core_relo_res targ_res = {};
2325                         struct bpf_core_cand_list *cands = NULL;
2326                         const char *sec_name = btf__name_by_offset(btf, sec->sec_name_off);
2327
2328                         if (relo->kind != BPF_CORE_TYPE_ID_LOCAL &&
2329                             !hashmap__find(cand_cache, relo->type_id, &cands)) {
2330                                 cands = btfgen_find_cands(btf, info->src_btf, relo->type_id);
2331                                 if (!cands) {
2332                                         err = -errno;
2333                                         goto out;
2334                                 }
2335
2336                                 err = hashmap__set(cand_cache, relo->type_id, cands,
2337                                                    NULL, NULL);
2338                                 if (err)
2339                                         goto out;
2340                         }
2341
2342                         err = bpf_core_calc_relo_insn(sec_name, relo, relo_idx, btf, cands,
2343                                                       specs_scratch, &targ_res);
2344                         if (err)
2345                                 goto out;
2346
2347                         /* specs_scratch[2] is the target spec */
2348                         err = btfgen_record_reloc(info, &specs_scratch[2]);
2349                         if (err)
2350                                 goto out;
2351                 }
2352         }
2353
2354 out:
2355         btf__free(btf);
2356         btf_ext__free(btf_ext);
2357
2358         if (!IS_ERR_OR_NULL(cand_cache)) {
2359                 hashmap__for_each_entry(cand_cache, entry, i) {
2360                         bpf_core_free_cands(entry->pvalue);
2361                 }
2362                 hashmap__free(cand_cache);
2363         }
2364
2365         return err;
2366 }
2367
2368 static int btfgen_remap_id(__u32 *type_id, void *ctx)
2369 {
2370         unsigned int *ids = ctx;
2371
2372         *type_id = ids[*type_id];
2373
2374         return 0;
2375 }
2376
2377 /* Generate BTF from relocation information previously recorded */
2378 static struct btf *btfgen_get_btf(struct btfgen_info *info)
2379 {
2380         struct btf *btf_new = NULL;
2381         unsigned int *ids = NULL;
2382         unsigned int i, n = btf__type_cnt(info->marked_btf);
2383         int err = 0;
2384
2385         btf_new = btf__new_empty();
2386         if (!btf_new) {
2387                 err = -errno;
2388                 goto err_out;
2389         }
2390
2391         ids = calloc(n, sizeof(*ids));
2392         if (!ids) {
2393                 err = -errno;
2394                 goto err_out;
2395         }
2396
2397         /* first pass: add all marked types to btf_new and add their new ids to the ids map */
2398         for (i = 1; i < n; i++) {
2399                 const struct btf_type *cloned_type, *type;
2400                 const char *name;
2401                 int new_id;
2402
2403                 cloned_type = btf__type_by_id(info->marked_btf, i);
2404
2405                 if (cloned_type->name_off != MARKED)
2406                         continue;
2407
2408                 type = btf__type_by_id(info->src_btf, i);
2409
2410                 /* add members for struct and union */
2411                 if (btf_is_composite(type)) {
2412                         struct btf_member *cloned_m, *m;
2413                         unsigned short vlen;
2414                         int idx_src;
2415
2416                         name = btf__str_by_offset(info->src_btf, type->name_off);
2417
2418                         if (btf_is_struct(type))
2419                                 err = btf__add_struct(btf_new, name, type->size);
2420                         else
2421                                 err = btf__add_union(btf_new, name, type->size);
2422
2423                         if (err < 0)
2424                                 goto err_out;
2425                         new_id = err;
2426
2427                         cloned_m = btf_members(cloned_type);
2428                         m = btf_members(type);
2429                         vlen = btf_vlen(cloned_type);
2430                         for (idx_src = 0; idx_src < vlen; idx_src++, cloned_m++, m++) {
2431                                 /* add only members that are marked as used */
2432                                 if (cloned_m->name_off != MARKED)
2433                                         continue;
2434
2435                                 name = btf__str_by_offset(info->src_btf, m->name_off);
2436                                 err = btf__add_field(btf_new, name, m->type,
2437                                                      btf_member_bit_offset(cloned_type, idx_src),
2438                                                      btf_member_bitfield_size(cloned_type, idx_src));
2439                                 if (err < 0)
2440                                         goto err_out;
2441                         }
2442                 } else {
2443                         err = btf__add_type(btf_new, info->src_btf, type);
2444                         if (err < 0)
2445                                 goto err_out;
2446                         new_id = err;
2447                 }
2448
2449                 /* add ID mapping */
2450                 ids[i] = new_id;
2451         }
2452
2453         /* second pass: fix up type ids */
2454         for (i = 1; i < btf__type_cnt(btf_new); i++) {
2455                 struct btf_type *btf_type = (struct btf_type *) btf__type_by_id(btf_new, i);
2456
2457                 err = btf_type_visit_type_ids(btf_type, btfgen_remap_id, ids);
2458                 if (err)
2459                         goto err_out;
2460         }
2461
2462         free(ids);
2463         return btf_new;
2464
2465 err_out:
2466         btf__free(btf_new);
2467         free(ids);
2468         errno = -err;
2469         return NULL;
2470 }
2471
2472 /* Create minimized BTF file for a set of BPF objects.
2473  *
2474  * The BTFGen algorithm is divided in two main parts: (1) collect the
2475  * BTF types that are involved in relocations and (2) generate the BTF
2476  * object using the collected types.
2477  *
2478  * In order to collect the types involved in the relocations, we parse
2479  * the BTF and BTF.ext sections of the BPF objects and use
2480  * bpf_core_calc_relo_insn() to get the target specification, this
2481  * indicates how the types and fields are used in a relocation.
2482  *
2483  * Types are recorded in different ways according to the kind of the
2484  * relocation. For field-based relocations only the members that are
2485  * actually used are saved in order to reduce the size of the generated
2486  * BTF file. For type-based relocations empty struct / unions are
2487  * generated and for enum-based relocations the whole type is saved.
2488  *
2489  * The second part of the algorithm generates the BTF object. It creates
2490  * an empty BTF object and fills it with the types recorded in the
2491  * previous step. This function takes care of only adding the structure
2492  * and union members that were marked as used and it also fixes up the
2493  * type IDs on the generated BTF object.
2494  */
2495 static int minimize_btf(const char *src_btf, const char *dst_btf, const char *objspaths[])
2496 {
2497         struct btfgen_info *info;
2498         struct btf *btf_new = NULL;
2499         int err, i;
2500
2501         info = btfgen_new_info(src_btf);
2502         if (!info) {
2503                 err = -errno;
2504                 p_err("failed to allocate info structure: %s", strerror(errno));
2505                 goto out;
2506         }
2507
2508         for (i = 0; objspaths[i] != NULL; i++) {
2509                 err = btfgen_record_obj(info, objspaths[i]);
2510                 if (err) {
2511                         p_err("error recording relocations for %s: %s", objspaths[i],
2512                               strerror(errno));
2513                         goto out;
2514                 }
2515         }
2516
2517         btf_new = btfgen_get_btf(info);
2518         if (!btf_new) {
2519                 err = -errno;
2520                 p_err("error generating BTF: %s", strerror(errno));
2521                 goto out;
2522         }
2523
2524         err = btf_save_raw(btf_new, dst_btf);
2525         if (err) {
2526                 p_err("error saving btf file: %s", strerror(errno));
2527                 goto out;
2528         }
2529
2530 out:
2531         btf__free(btf_new);
2532         btfgen_free_info(info);
2533
2534         return err;
2535 }
2536
2537 static int do_min_core_btf(int argc, char **argv)
2538 {
2539         const char *input, *output, **objs;
2540         int i, err;
2541
2542         if (!REQ_ARGS(3)) {
2543                 usage();
2544                 return -1;
2545         }
2546
2547         input = GET_ARG();
2548         output = GET_ARG();
2549
2550         objs = (const char **) calloc(argc + 1, sizeof(*objs));
2551         if (!objs) {
2552                 p_err("failed to allocate array for object names");
2553                 return -ENOMEM;
2554         }
2555
2556         i = 0;
2557         while (argc)
2558                 objs[i++] = GET_ARG();
2559
2560         err = minimize_btf(input, output, objs);
2561         free(objs);
2562         return err;
2563 }
2564
2565 static const struct cmd cmds[] = {
2566         { "object",             do_object },
2567         { "skeleton",           do_skeleton },
2568         { "subskeleton",        do_subskeleton },
2569         { "min_core_btf",       do_min_core_btf},
2570         { "help",               do_help },
2571         { 0 }
2572 };
2573
2574 int do_gen(int argc, char **argv)
2575 {
2576         return cmd_select(cmds, argc, argv, do_help);
2577 }