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