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 <errno.h> 8 #include <fcntl.h> 9 #include <linux/err.h> 10 #include <stdbool.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <linux/btf.h> 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 19 #include <bpf/bpf.h> 20 #include <bpf/btf.h> 21 #include <bpf/hashmap.h> 22 #include <bpf/libbpf.h> 23 24 #include "json_writer.h" 25 #include "main.h" 26 27 #define KFUNC_DECL_TAG "bpf_kfunc" 28 #define FASTCALL_DECL_TAG "bpf_fastcall" 29 30 #define MAX_ROOT_IDS 16 31 #define MAX_BTF_FILES 64 32 33 static const char * const btf_kind_str[NR_BTF_KINDS] = { 34 [BTF_KIND_UNKN] = "UNKNOWN", 35 [BTF_KIND_INT] = "INT", 36 [BTF_KIND_PTR] = "PTR", 37 [BTF_KIND_ARRAY] = "ARRAY", 38 [BTF_KIND_STRUCT] = "STRUCT", 39 [BTF_KIND_UNION] = "UNION", 40 [BTF_KIND_ENUM] = "ENUM", 41 [BTF_KIND_FWD] = "FWD", 42 [BTF_KIND_TYPEDEF] = "TYPEDEF", 43 [BTF_KIND_VOLATILE] = "VOLATILE", 44 [BTF_KIND_CONST] = "CONST", 45 [BTF_KIND_RESTRICT] = "RESTRICT", 46 [BTF_KIND_FUNC] = "FUNC", 47 [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO", 48 [BTF_KIND_VAR] = "VAR", 49 [BTF_KIND_DATASEC] = "DATASEC", 50 [BTF_KIND_FLOAT] = "FLOAT", 51 [BTF_KIND_DECL_TAG] = "DECL_TAG", 52 [BTF_KIND_TYPE_TAG] = "TYPE_TAG", 53 [BTF_KIND_ENUM64] = "ENUM64", 54 }; 55 56 struct sort_datum { 57 int index; 58 int type_rank; 59 const char *sort_name; 60 const char *own_name; 61 __u64 disambig_hash; 62 }; 63 64 static const char *btf_int_enc_str(__u8 encoding) 65 { 66 switch (encoding) { 67 case 0: 68 return "(none)"; 69 case BTF_INT_SIGNED: 70 return "SIGNED"; 71 case BTF_INT_CHAR: 72 return "CHAR"; 73 case BTF_INT_BOOL: 74 return "BOOL"; 75 default: 76 return "UNKN"; 77 } 78 } 79 80 static const char *btf_var_linkage_str(__u32 linkage) 81 { 82 switch (linkage) { 83 case BTF_VAR_STATIC: 84 return "static"; 85 case BTF_VAR_GLOBAL_ALLOCATED: 86 return "global"; 87 case BTF_VAR_GLOBAL_EXTERN: 88 return "extern"; 89 default: 90 return "(unknown)"; 91 } 92 } 93 94 static const char *btf_func_linkage_str(const struct btf_type *t) 95 { 96 switch (btf_vlen(t)) { 97 case BTF_FUNC_STATIC: 98 return "static"; 99 case BTF_FUNC_GLOBAL: 100 return "global"; 101 case BTF_FUNC_EXTERN: 102 return "extern"; 103 default: 104 return "(unknown)"; 105 } 106 } 107 108 static const char *btf_str(const struct btf *btf, __u32 off) 109 { 110 if (!off) 111 return "(anon)"; 112 return btf__name_by_offset(btf, off) ? : "(invalid)"; 113 } 114 115 static int btf_kind_safe(int kind) 116 { 117 return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN; 118 } 119 120 static int dump_btf_type(const struct btf *btf, __u32 id, 121 const struct btf_type *t) 122 { 123 json_writer_t *w = json_wtr; 124 int kind = btf_kind(t); 125 126 if (json_output) { 127 jsonw_start_object(w); 128 jsonw_uint_field(w, "id", id); 129 jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]); 130 jsonw_string_field(w, "name", btf_str(btf, t->name_off)); 131 } else { 132 printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)], 133 btf_str(btf, t->name_off)); 134 } 135 136 switch (kind) { 137 case BTF_KIND_INT: { 138 __u32 v = *(__u32 *)(t + 1); 139 const char *enc; 140 141 enc = btf_int_enc_str(BTF_INT_ENCODING(v)); 142 143 if (json_output) { 144 jsonw_uint_field(w, "size", t->size); 145 jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v)); 146 jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v)); 147 jsonw_string_field(w, "encoding", enc); 148 } else { 149 printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s", 150 t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v), 151 enc); 152 } 153 break; 154 } 155 case BTF_KIND_PTR: 156 case BTF_KIND_CONST: 157 case BTF_KIND_VOLATILE: 158 case BTF_KIND_RESTRICT: 159 case BTF_KIND_TYPEDEF: 160 case BTF_KIND_TYPE_TAG: 161 if (json_output) 162 jsonw_uint_field(w, "type_id", t->type); 163 else 164 printf(" type_id=%u", t->type); 165 break; 166 case BTF_KIND_ARRAY: { 167 const struct btf_array *arr = (const void *)(t + 1); 168 169 if (json_output) { 170 jsonw_uint_field(w, "type_id", arr->type); 171 jsonw_uint_field(w, "index_type_id", arr->index_type); 172 jsonw_uint_field(w, "nr_elems", arr->nelems); 173 } else { 174 printf(" type_id=%u index_type_id=%u nr_elems=%u", 175 arr->type, arr->index_type, arr->nelems); 176 } 177 break; 178 } 179 case BTF_KIND_STRUCT: 180 case BTF_KIND_UNION: { 181 const struct btf_member *m = (const void *)(t + 1); 182 __u16 vlen = BTF_INFO_VLEN(t->info); 183 int i; 184 185 if (json_output) { 186 jsonw_uint_field(w, "size", t->size); 187 jsonw_uint_field(w, "vlen", vlen); 188 jsonw_name(w, "members"); 189 jsonw_start_array(w); 190 } else { 191 printf(" size=%u vlen=%u", t->size, vlen); 192 } 193 for (i = 0; i < vlen; i++, m++) { 194 const char *name = btf_str(btf, m->name_off); 195 __u32 bit_off, bit_sz; 196 197 if (BTF_INFO_KFLAG(t->info)) { 198 bit_off = BTF_MEMBER_BIT_OFFSET(m->offset); 199 bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset); 200 } else { 201 bit_off = m->offset; 202 bit_sz = 0; 203 } 204 205 if (json_output) { 206 jsonw_start_object(w); 207 jsonw_string_field(w, "name", name); 208 jsonw_uint_field(w, "type_id", m->type); 209 jsonw_uint_field(w, "bits_offset", bit_off); 210 if (bit_sz) { 211 jsonw_uint_field(w, "bitfield_size", 212 bit_sz); 213 } 214 jsonw_end_object(w); 215 } else { 216 printf("\n\t'%s' type_id=%u bits_offset=%u", 217 name, m->type, bit_off); 218 if (bit_sz) 219 printf(" bitfield_size=%u", bit_sz); 220 } 221 } 222 if (json_output) 223 jsonw_end_array(w); 224 break; 225 } 226 case BTF_KIND_ENUM: { 227 const struct btf_enum *v = (const void *)(t + 1); 228 __u16 vlen = BTF_INFO_VLEN(t->info); 229 const char *encoding; 230 int i; 231 232 encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED"; 233 if (json_output) { 234 jsonw_string_field(w, "encoding", encoding); 235 jsonw_uint_field(w, "size", t->size); 236 jsonw_uint_field(w, "vlen", vlen); 237 jsonw_name(w, "values"); 238 jsonw_start_array(w); 239 } else { 240 printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen); 241 } 242 for (i = 0; i < vlen; i++, v++) { 243 const char *name = btf_str(btf, v->name_off); 244 245 if (json_output) { 246 jsonw_start_object(w); 247 jsonw_string_field(w, "name", name); 248 if (btf_kflag(t)) 249 jsonw_int_field(w, "val", v->val); 250 else 251 jsonw_uint_field(w, "val", v->val); 252 jsonw_end_object(w); 253 } else { 254 if (btf_kflag(t)) 255 printf("\n\t'%s' val=%d", name, v->val); 256 else 257 printf("\n\t'%s' val=%u", name, (__u32)v->val); 258 } 259 } 260 if (json_output) 261 jsonw_end_array(w); 262 break; 263 } 264 case BTF_KIND_ENUM64: { 265 const struct btf_enum64 *v = btf_enum64(t); 266 __u16 vlen = btf_vlen(t); 267 const char *encoding; 268 int i; 269 270 encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED"; 271 if (json_output) { 272 jsonw_string_field(w, "encoding", encoding); 273 jsonw_uint_field(w, "size", t->size); 274 jsonw_uint_field(w, "vlen", vlen); 275 jsonw_name(w, "values"); 276 jsonw_start_array(w); 277 } else { 278 printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen); 279 } 280 for (i = 0; i < vlen; i++, v++) { 281 const char *name = btf_str(btf, v->name_off); 282 __u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32; 283 284 if (json_output) { 285 jsonw_start_object(w); 286 jsonw_string_field(w, "name", name); 287 if (btf_kflag(t)) 288 jsonw_int_field(w, "val", val); 289 else 290 jsonw_uint_field(w, "val", val); 291 jsonw_end_object(w); 292 } else { 293 if (btf_kflag(t)) 294 printf("\n\t'%s' val=%lldLL", name, 295 (long long)val); 296 else 297 printf("\n\t'%s' val=%lluULL", name, 298 (unsigned long long)val); 299 } 300 } 301 if (json_output) 302 jsonw_end_array(w); 303 break; 304 } 305 case BTF_KIND_FWD: { 306 const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union" 307 : "struct"; 308 309 if (json_output) 310 jsonw_string_field(w, "fwd_kind", fwd_kind); 311 else 312 printf(" fwd_kind=%s", fwd_kind); 313 break; 314 } 315 case BTF_KIND_FUNC: { 316 const char *linkage = btf_func_linkage_str(t); 317 318 if (json_output) { 319 jsonw_uint_field(w, "type_id", t->type); 320 jsonw_string_field(w, "linkage", linkage); 321 } else { 322 printf(" type_id=%u linkage=%s", t->type, linkage); 323 } 324 break; 325 } 326 case BTF_KIND_FUNC_PROTO: { 327 const struct btf_param *p = (const void *)(t + 1); 328 __u16 vlen = BTF_INFO_VLEN(t->info); 329 int i; 330 331 if (json_output) { 332 jsonw_uint_field(w, "ret_type_id", t->type); 333 jsonw_uint_field(w, "vlen", vlen); 334 jsonw_name(w, "params"); 335 jsonw_start_array(w); 336 } else { 337 printf(" ret_type_id=%u vlen=%u", t->type, vlen); 338 } 339 for (i = 0; i < vlen; i++, p++) { 340 const char *name = btf_str(btf, p->name_off); 341 342 if (json_output) { 343 jsonw_start_object(w); 344 jsonw_string_field(w, "name", name); 345 jsonw_uint_field(w, "type_id", p->type); 346 jsonw_end_object(w); 347 } else { 348 printf("\n\t'%s' type_id=%u", name, p->type); 349 } 350 } 351 if (json_output) 352 jsonw_end_array(w); 353 break; 354 } 355 case BTF_KIND_VAR: { 356 const struct btf_var *v = (const void *)(t + 1); 357 const char *linkage; 358 359 linkage = btf_var_linkage_str(v->linkage); 360 361 if (json_output) { 362 jsonw_uint_field(w, "type_id", t->type); 363 jsonw_string_field(w, "linkage", linkage); 364 } else { 365 printf(" type_id=%u, linkage=%s", t->type, linkage); 366 } 367 break; 368 } 369 case BTF_KIND_DATASEC: { 370 const struct btf_var_secinfo *v = (const void *)(t + 1); 371 const struct btf_type *vt; 372 __u16 vlen = BTF_INFO_VLEN(t->info); 373 int i; 374 375 if (json_output) { 376 jsonw_uint_field(w, "size", t->size); 377 jsonw_uint_field(w, "vlen", vlen); 378 jsonw_name(w, "vars"); 379 jsonw_start_array(w); 380 } else { 381 printf(" size=%u vlen=%u", t->size, vlen); 382 } 383 for (i = 0; i < vlen; i++, v++) { 384 if (json_output) { 385 jsonw_start_object(w); 386 jsonw_uint_field(w, "type_id", v->type); 387 jsonw_uint_field(w, "offset", v->offset); 388 jsonw_uint_field(w, "size", v->size); 389 jsonw_end_object(w); 390 } else { 391 printf("\n\ttype_id=%u offset=%u size=%u", 392 v->type, v->offset, v->size); 393 394 if (v->type < btf__type_cnt(btf)) { 395 vt = btf__type_by_id(btf, v->type); 396 printf(" (%s '%s')", 397 btf_kind_str[btf_kind_safe(btf_kind(vt))], 398 btf_str(btf, vt->name_off)); 399 } 400 } 401 } 402 if (json_output) 403 jsonw_end_array(w); 404 break; 405 } 406 case BTF_KIND_FLOAT: { 407 if (json_output) 408 jsonw_uint_field(w, "size", t->size); 409 else 410 printf(" size=%u", t->size); 411 break; 412 } 413 case BTF_KIND_DECL_TAG: { 414 const struct btf_decl_tag *tag = (const void *)(t + 1); 415 416 if (json_output) { 417 jsonw_uint_field(w, "type_id", t->type); 418 jsonw_int_field(w, "component_idx", tag->component_idx); 419 } else { 420 printf(" type_id=%u component_idx=%d", t->type, tag->component_idx); 421 } 422 break; 423 } 424 default: 425 break; 426 } 427 428 if (json_output) 429 jsonw_end_object(json_wtr); 430 else 431 printf("\n"); 432 433 return 0; 434 } 435 436 static int dump_btf_raw(const struct btf *btf, 437 __u32 *root_type_ids, int root_type_cnt) 438 { 439 const struct btf_type *t; 440 int i; 441 442 if (json_output) { 443 jsonw_start_object(json_wtr); 444 jsonw_name(json_wtr, "types"); 445 jsonw_start_array(json_wtr); 446 } 447 448 if (root_type_cnt) { 449 for (i = 0; i < root_type_cnt; i++) { 450 t = btf__type_by_id(btf, root_type_ids[i]); 451 dump_btf_type(btf, root_type_ids[i], t); 452 } 453 } else { 454 const struct btf *base; 455 int cnt = btf__type_cnt(btf); 456 int start_id = 1; 457 458 base = btf__base_btf(btf); 459 if (base) 460 start_id = btf__type_cnt(base); 461 462 for (i = start_id; i < cnt; i++) { 463 t = btf__type_by_id(btf, i); 464 dump_btf_type(btf, i, t); 465 } 466 } 467 468 if (json_output) { 469 jsonw_end_array(json_wtr); 470 jsonw_end_object(json_wtr); 471 } 472 return 0; 473 } 474 475 struct ptr_array { 476 __u32 cnt; 477 __u32 cap; 478 const void **elems; 479 }; 480 481 static int ptr_array_push(const void *ptr, struct ptr_array *arr) 482 { 483 __u32 new_cap; 484 void *tmp; 485 486 if (arr->cnt == arr->cap) { 487 new_cap = (arr->cap ?: 16) * 2; 488 tmp = realloc(arr->elems, sizeof(*arr->elems) * new_cap); 489 if (!tmp) 490 return -ENOMEM; 491 arr->elems = tmp; 492 arr->cap = new_cap; 493 } 494 arr->elems[arr->cnt++] = ptr; 495 return 0; 496 } 497 498 static void ptr_array_free(struct ptr_array *arr) 499 { 500 free(arr->elems); 501 } 502 503 static int cmp_kfuncs(const void *pa, const void *pb, void *ctx) 504 { 505 struct btf *btf = ctx; 506 const struct btf_type *a = *(void **)pa; 507 const struct btf_type *b = *(void **)pb; 508 509 return strcmp(btf__str_by_offset(btf, a->name_off), 510 btf__str_by_offset(btf, b->name_off)); 511 } 512 513 static int dump_btf_kfuncs(struct btf_dump *d, const struct btf *btf) 514 { 515 LIBBPF_OPTS(btf_dump_emit_type_decl_opts, opts); 516 __u32 cnt = btf__type_cnt(btf), i, j; 517 struct ptr_array fastcalls = {}; 518 struct ptr_array kfuncs = {}; 519 int err = 0; 520 521 printf("\n/* BPF kfuncs */\n"); 522 printf("#ifndef BPF_NO_KFUNC_PROTOTYPES\n"); 523 524 for (i = 1; i < cnt; i++) { 525 const struct btf_type *t = btf__type_by_id(btf, i); 526 const struct btf_type *ft; 527 const char *name; 528 529 if (!btf_is_decl_tag(t)) 530 continue; 531 532 if (btf_decl_tag(t)->component_idx != -1) 533 continue; 534 535 ft = btf__type_by_id(btf, t->type); 536 if (!btf_is_func(ft)) 537 continue; 538 539 name = btf__name_by_offset(btf, t->name_off); 540 if (strncmp(name, KFUNC_DECL_TAG, sizeof(KFUNC_DECL_TAG)) == 0) { 541 err = ptr_array_push(ft, &kfuncs); 542 if (err) 543 goto out; 544 } 545 546 if (strncmp(name, FASTCALL_DECL_TAG, sizeof(FASTCALL_DECL_TAG)) == 0) { 547 err = ptr_array_push(ft, &fastcalls); 548 if (err) 549 goto out; 550 } 551 } 552 553 /* Sort kfuncs by name for improved vmlinux.h stability */ 554 qsort_r(kfuncs.elems, kfuncs.cnt, sizeof(*kfuncs.elems), cmp_kfuncs, (void *)btf); 555 for (i = 0; i < kfuncs.cnt; i++) { 556 const struct btf_type *t = kfuncs.elems[i]; 557 558 printf("extern "); 559 560 /* Assume small amount of fastcall kfuncs */ 561 for (j = 0; j < fastcalls.cnt; j++) { 562 if (fastcalls.elems[j] == t) { 563 printf("__bpf_fastcall "); 564 break; 565 } 566 } 567 568 opts.field_name = btf__name_by_offset(btf, t->name_off); 569 err = btf_dump__emit_type_decl(d, t->type, &opts); 570 if (err) 571 goto out; 572 573 printf(" __weak __ksym;\n"); 574 } 575 576 printf("#endif\n\n"); 577 578 out: 579 ptr_array_free(&fastcalls); 580 ptr_array_free(&kfuncs); 581 return err; 582 } 583 584 static void __printf(2, 0) btf_dump_printf(void *ctx, 585 const char *fmt, va_list args) 586 { 587 vfprintf(stdout, fmt, args); 588 } 589 590 static int btf_type_rank(const struct btf *btf, __u32 index, bool has_name) 591 { 592 const struct btf_type *t = btf__type_by_id(btf, index); 593 const int kind = btf_kind(t); 594 const int max_rank = 10; 595 596 if (t->name_off) 597 has_name = true; 598 599 switch (kind) { 600 case BTF_KIND_ENUM: 601 case BTF_KIND_ENUM64: 602 return has_name ? 1 : 0; 603 case BTF_KIND_INT: 604 case BTF_KIND_FLOAT: 605 return 2; 606 case BTF_KIND_STRUCT: 607 case BTF_KIND_UNION: 608 return has_name ? 3 : max_rank; 609 case BTF_KIND_FUNC_PROTO: 610 return has_name ? 4 : max_rank; 611 case BTF_KIND_ARRAY: 612 if (has_name) 613 return btf_type_rank(btf, btf_array(t)->type, has_name); 614 return max_rank; 615 case BTF_KIND_TYPE_TAG: 616 case BTF_KIND_CONST: 617 case BTF_KIND_PTR: 618 case BTF_KIND_VOLATILE: 619 case BTF_KIND_RESTRICT: 620 case BTF_KIND_TYPEDEF: 621 case BTF_KIND_DECL_TAG: 622 if (has_name) 623 return btf_type_rank(btf, t->type, has_name); 624 return max_rank; 625 default: 626 return max_rank; 627 } 628 } 629 630 static const char *btf_type_sort_name(const struct btf *btf, __u32 index, bool from_ref) 631 { 632 const struct btf_type *t = btf__type_by_id(btf, index); 633 634 switch (btf_kind(t)) { 635 case BTF_KIND_ENUM: 636 case BTF_KIND_ENUM64: { 637 int name_off = t->name_off; 638 639 if (!from_ref && !name_off && btf_vlen(t)) 640 name_off = btf_kind(t) == BTF_KIND_ENUM64 ? 641 btf_enum64(t)->name_off : 642 btf_enum(t)->name_off; 643 644 return btf__name_by_offset(btf, name_off); 645 } 646 case BTF_KIND_ARRAY: 647 return btf_type_sort_name(btf, btf_array(t)->type, true); 648 case BTF_KIND_TYPE_TAG: 649 case BTF_KIND_CONST: 650 case BTF_KIND_PTR: 651 case BTF_KIND_VOLATILE: 652 case BTF_KIND_RESTRICT: 653 case BTF_KIND_TYPEDEF: 654 case BTF_KIND_DECL_TAG: 655 return btf_type_sort_name(btf, t->type, true); 656 default: 657 return btf__name_by_offset(btf, t->name_off); 658 } 659 return NULL; 660 } 661 662 static __u64 hasher(__u64 hash, __u64 val) 663 { 664 return hash * 31 + val; 665 } 666 667 static __u64 btf_name_hasher(__u64 hash, const struct btf *btf, __u32 name_off) 668 { 669 if (!name_off) 670 return hash; 671 672 return hasher(hash, str_hash(btf__name_by_offset(btf, name_off))); 673 } 674 675 static __u64 btf_type_disambig_hash(const struct btf *btf, __u32 id, bool include_members) 676 { 677 const struct btf_type *t = btf__type_by_id(btf, id); 678 int i; 679 size_t hash = 0; 680 681 hash = btf_name_hasher(hash, btf, t->name_off); 682 683 switch (btf_kind(t)) { 684 case BTF_KIND_ENUM: 685 case BTF_KIND_ENUM64: 686 for (i = 0; i < btf_vlen(t); i++) { 687 __u32 name_off = btf_is_enum(t) ? 688 btf_enum(t)[i].name_off : 689 btf_enum64(t)[i].name_off; 690 691 hash = btf_name_hasher(hash, btf, name_off); 692 } 693 break; 694 case BTF_KIND_STRUCT: 695 case BTF_KIND_UNION: 696 if (!include_members) 697 break; 698 for (i = 0; i < btf_vlen(t); i++) { 699 const struct btf_member *m = btf_members(t) + i; 700 701 hash = btf_name_hasher(hash, btf, m->name_off); 702 /* resolve field type's name and hash it as well */ 703 hash = hasher(hash, btf_type_disambig_hash(btf, m->type, false)); 704 } 705 break; 706 case BTF_KIND_TYPE_TAG: 707 case BTF_KIND_CONST: 708 case BTF_KIND_PTR: 709 case BTF_KIND_VOLATILE: 710 case BTF_KIND_RESTRICT: 711 case BTF_KIND_TYPEDEF: 712 case BTF_KIND_DECL_TAG: 713 hash = hasher(hash, btf_type_disambig_hash(btf, t->type, include_members)); 714 break; 715 case BTF_KIND_ARRAY: { 716 struct btf_array *arr = btf_array(t); 717 718 hash = hasher(hash, arr->nelems); 719 hash = hasher(hash, btf_type_disambig_hash(btf, arr->type, include_members)); 720 break; 721 } 722 default: 723 break; 724 } 725 return hash; 726 } 727 728 static int btf_type_compare(const void *left, const void *right) 729 { 730 const struct sort_datum *d1 = (const struct sort_datum *)left; 731 const struct sort_datum *d2 = (const struct sort_datum *)right; 732 int r; 733 734 r = d1->type_rank - d2->type_rank; 735 r = r ?: strcmp(d1->sort_name, d2->sort_name); 736 r = r ?: strcmp(d1->own_name, d2->own_name); 737 if (r) 738 return r; 739 740 if (d1->disambig_hash != d2->disambig_hash) 741 return d1->disambig_hash < d2->disambig_hash ? -1 : 1; 742 743 return d1->index - d2->index; 744 } 745 746 static struct sort_datum *sort_btf_c(const struct btf *btf) 747 { 748 struct sort_datum *datums; 749 int n; 750 751 n = btf__type_cnt(btf); 752 datums = malloc(sizeof(struct sort_datum) * n); 753 if (!datums) 754 return NULL; 755 756 for (int i = 0; i < n; ++i) { 757 struct sort_datum *d = datums + i; 758 const struct btf_type *t = btf__type_by_id(btf, i); 759 760 d->index = i; 761 d->type_rank = btf_type_rank(btf, i, false); 762 d->sort_name = btf_type_sort_name(btf, i, false); 763 d->own_name = btf__name_by_offset(btf, t->name_off); 764 d->disambig_hash = btf_type_disambig_hash(btf, i, true); 765 } 766 767 qsort(datums, n, sizeof(struct sort_datum), btf_type_compare); 768 769 return datums; 770 } 771 772 static int dump_btf_c(const struct btf *btf, 773 __u32 *root_type_ids, int root_type_cnt, bool sort_dump) 774 { 775 struct sort_datum *datums = NULL; 776 struct btf_dump *d; 777 int err = 0, i; 778 779 d = btf_dump__new(btf, btf_dump_printf, NULL, NULL); 780 if (!d) 781 return -errno; 782 783 printf("#ifndef __VMLINUX_H__\n"); 784 printf("#define __VMLINUX_H__\n"); 785 printf("\n"); 786 printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n"); 787 printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n"); 788 printf("#endif\n\n"); 789 printf("#ifndef __ksym\n"); 790 printf("#define __ksym __attribute__((section(\".ksyms\")))\n"); 791 printf("#endif\n\n"); 792 printf("#ifndef __weak\n"); 793 printf("#define __weak __attribute__((weak))\n"); 794 printf("#endif\n\n"); 795 printf("#ifndef __bpf_fastcall\n"); 796 printf("#if __has_attribute(bpf_fastcall)\n"); 797 printf("#define __bpf_fastcall __attribute__((bpf_fastcall))\n"); 798 printf("#else\n"); 799 printf("#define __bpf_fastcall\n"); 800 printf("#endif\n"); 801 printf("#endif\n\n"); 802 803 if (root_type_cnt) { 804 for (i = 0; i < root_type_cnt; i++) { 805 err = btf_dump__dump_type(d, root_type_ids[i]); 806 if (err) 807 goto done; 808 } 809 } else { 810 int cnt = btf__type_cnt(btf); 811 812 if (sort_dump) 813 datums = sort_btf_c(btf); 814 for (i = 1; i < cnt; i++) { 815 int idx = datums ? datums[i].index : i; 816 817 err = btf_dump__dump_type(d, idx); 818 if (err) 819 goto done; 820 } 821 822 err = dump_btf_kfuncs(d, btf); 823 if (err) 824 goto done; 825 } 826 827 printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n"); 828 printf("#pragma clang attribute pop\n"); 829 printf("#endif\n"); 830 printf("\n"); 831 printf("#endif /* __VMLINUX_H__ */\n"); 832 833 done: 834 free(datums); 835 btf_dump__free(d); 836 return err; 837 } 838 839 static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; 840 841 static struct btf *get_vmlinux_btf_from_sysfs(void) 842 { 843 struct btf *base; 844 845 base = btf__parse(sysfs_vmlinux, NULL); 846 if (!base) 847 p_err("failed to parse vmlinux BTF at '%s': %d\n", 848 sysfs_vmlinux, -errno); 849 850 return base; 851 } 852 853 #define BTF_NAME_BUFF_LEN 64 854 855 static bool btf_is_kernel_module(__u32 btf_id) 856 { 857 struct bpf_btf_info btf_info = {}; 858 char btf_name[BTF_NAME_BUFF_LEN]; 859 int btf_fd; 860 __u32 len; 861 int err; 862 863 btf_fd = bpf_btf_get_fd_by_id(btf_id); 864 if (btf_fd < 0) { 865 p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno)); 866 return false; 867 } 868 869 len = sizeof(btf_info); 870 btf_info.name = ptr_to_u64(btf_name); 871 btf_info.name_len = sizeof(btf_name); 872 err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len); 873 close(btf_fd); 874 if (err) { 875 p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno)); 876 return false; 877 } 878 879 return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0; 880 } 881 882 static struct btf *merge_btf_files(const char **files, int nr_files, 883 struct btf *vmlinux_base) 884 { 885 struct btf *combined, *mod; 886 int ret; 887 888 combined = btf__new_empty_split(vmlinux_base); 889 if (!combined) { 890 p_err("failed to create combined BTF: %s", strerror(errno)); 891 return NULL; 892 } 893 894 for (int j = 0; j < nr_files; j++) { 895 mod = btf__parse_split(files[j], vmlinux_base); 896 if (!mod) { 897 p_err("failed to load BTF from %s: %s", files[j], strerror(errno)); 898 btf__free(combined); 899 return NULL; 900 } 901 902 ret = btf__add_btf(combined, mod); 903 btf__free(mod); 904 if (ret < 0) { 905 p_err("failed to merge BTF from %s: %s", files[j], strerror(-ret)); 906 btf__free(combined); 907 return NULL; 908 } 909 } 910 911 ret = btf__dedup(combined, NULL); 912 if (ret) { 913 p_err("failed to dedup combined BTF: %s", strerror(-ret)); 914 btf__free(combined); 915 return NULL; 916 } 917 918 return combined; 919 } 920 921 static int do_dump(int argc, char **argv) 922 { 923 bool dump_c = false, sort_dump_c = true; 924 struct btf *btf = NULL, *base = NULL; 925 __u32 root_type_ids[MAX_ROOT_IDS]; 926 bool have_id_filtering; 927 int root_type_cnt = 0; 928 __u32 btf_id = -1; 929 const char *src; 930 int fd = -1; 931 int err = 0; 932 int i; 933 934 if (!REQ_ARGS(2)) { 935 usage(); 936 return -1; 937 } 938 src = GET_ARG(); 939 if (is_prefix(src, "map")) { 940 struct bpf_map_info info = {}; 941 __u32 len = sizeof(info); 942 943 if (!REQ_ARGS(2)) { 944 usage(); 945 return -1; 946 } 947 948 fd = map_parse_fd_and_info(&argc, &argv, &info, &len, 949 BPF_F_RDONLY); 950 if (fd < 0) 951 return -1; 952 953 btf_id = info.btf_id; 954 if (argc && is_prefix(*argv, "key")) { 955 root_type_ids[root_type_cnt++] = info.btf_key_type_id; 956 NEXT_ARG(); 957 } else if (argc && is_prefix(*argv, "value")) { 958 root_type_ids[root_type_cnt++] = info.btf_value_type_id; 959 NEXT_ARG(); 960 } else if (argc && is_prefix(*argv, "all")) { 961 NEXT_ARG(); 962 } else if (argc && is_prefix(*argv, "kv")) { 963 root_type_ids[root_type_cnt++] = info.btf_key_type_id; 964 root_type_ids[root_type_cnt++] = info.btf_value_type_id; 965 NEXT_ARG(); 966 } else { 967 root_type_ids[root_type_cnt++] = info.btf_key_type_id; 968 root_type_ids[root_type_cnt++] = info.btf_value_type_id; 969 } 970 } else if (is_prefix(src, "prog")) { 971 struct bpf_prog_info info = {}; 972 __u32 len = sizeof(info); 973 974 if (!REQ_ARGS(2)) { 975 usage(); 976 return -1; 977 } 978 979 fd = prog_parse_fd(&argc, &argv); 980 if (fd < 0) 981 return -1; 982 983 err = bpf_prog_get_info_by_fd(fd, &info, &len); 984 if (err) { 985 p_err("can't get prog info: %s", strerror(errno)); 986 goto done; 987 } 988 989 btf_id = info.btf_id; 990 } else if (is_prefix(src, "id")) { 991 char *endptr; 992 993 btf_id = strtoul(*argv, &endptr, 0); 994 if (*endptr) { 995 p_err("can't parse %s as ID", *argv); 996 return -1; 997 } 998 NEXT_ARG(); 999 } else if (is_prefix(src, "file")) { 1000 const char sysfs_prefix[] = "/sys/kernel/btf/"; 1001 struct btf *vmlinux_base = base_btf; 1002 const char *files[MAX_BTF_FILES]; 1003 int nr_files = 0; 1004 1005 /* First grab our argument, filtering out the sysfs_vmlinux. */ 1006 if (strcmp(*argv, sysfs_vmlinux) != 0) { 1007 files[nr_files++] = *argv; 1008 } else { 1009 p_info("skipping %s (will be loaded as base)", *argv); 1010 } 1011 NEXT_ARG(); 1012 1013 while (argc && is_prefix(*argv, "file")) { 1014 NEXT_ARG(); 1015 if (!REQ_ARGS(1)) { 1016 err = -EINVAL; 1017 goto done; 1018 } 1019 /* Filter out any sysfs vmlinux entries. */ 1020 if (strcmp(*argv, sysfs_vmlinux) == 0) { 1021 p_info("skipping %s (will be loaded as base)", *argv); 1022 NEXT_ARG(); 1023 continue; 1024 } 1025 if (nr_files >= MAX_BTF_FILES) { 1026 p_err("too many BTF files (max %d)", MAX_BTF_FILES); 1027 err = -E2BIG; 1028 goto done; 1029 } 1030 files[nr_files++] = *argv; 1031 NEXT_ARG(); 1032 } 1033 1034 /* Auto-detect vmlinux base if any file is from sysfs */ 1035 if (!vmlinux_base) { 1036 for (int j = 0; j < nr_files; j++) { 1037 if (strncmp(files[j], sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0) { 1038 base = get_vmlinux_btf_from_sysfs(); 1039 vmlinux_base = base; 1040 break; 1041 } 1042 } 1043 } 1044 1045 /* All files were the sysfs_vmlinux, handle it like we used to */ 1046 if (nr_files == 0) { 1047 nr_files = 1; 1048 files[0] = sysfs_vmlinux; 1049 } 1050 1051 if (nr_files == 1) { 1052 btf = btf__parse_split(files[0], base ?: base_btf); 1053 if (!btf) { 1054 err = -errno; 1055 p_err("failed to load BTF from %s: %s", files[0], strerror(errno)); 1056 goto done; 1057 } 1058 } else { 1059 if (!vmlinux_base) { 1060 p_err("base BTF is required when merging multiple BTF files; use -B/--base-btf or use sysfs paths"); 1061 err = -EINVAL; 1062 goto done; 1063 } 1064 1065 btf = merge_btf_files(files, nr_files, vmlinux_base); 1066 if (!btf) { 1067 err = -errno; 1068 goto done; 1069 } 1070 } 1071 } else { 1072 err = -1; 1073 p_err("unrecognized BTF source specifier: '%s'", src); 1074 goto done; 1075 } 1076 1077 have_id_filtering = !!root_type_cnt; 1078 1079 while (argc) { 1080 if (is_prefix(*argv, "format")) { 1081 NEXT_ARG(); 1082 if (argc < 1) { 1083 p_err("expecting value for 'format' option\n"); 1084 err = -EINVAL; 1085 goto done; 1086 } 1087 if (strcmp(*argv, "c") == 0) { 1088 dump_c = true; 1089 } else if (strcmp(*argv, "raw") == 0) { 1090 dump_c = false; 1091 } else { 1092 p_err("unrecognized format specifier: '%s', possible values: raw, c", 1093 *argv); 1094 err = -EINVAL; 1095 goto done; 1096 } 1097 NEXT_ARG(); 1098 } else if (is_prefix(*argv, "root_id")) { 1099 __u32 root_id; 1100 char *end; 1101 1102 if (have_id_filtering) { 1103 p_err("cannot use root_id with other type filtering"); 1104 err = -EINVAL; 1105 goto done; 1106 } else if (root_type_cnt == MAX_ROOT_IDS) { 1107 p_err("only %d root_id are supported", MAX_ROOT_IDS); 1108 err = -E2BIG; 1109 goto done; 1110 } 1111 1112 NEXT_ARG(); 1113 root_id = strtoul(*argv, &end, 0); 1114 if (*end) { 1115 err = -1; 1116 p_err("can't parse %s as root ID", *argv); 1117 goto done; 1118 } 1119 for (i = 0; i < root_type_cnt; i++) { 1120 if (root_type_ids[i] == root_id) { 1121 err = -EINVAL; 1122 p_err("duplicate root_id %u supplied", root_id); 1123 goto done; 1124 } 1125 } 1126 root_type_ids[root_type_cnt++] = root_id; 1127 NEXT_ARG(); 1128 } else if (is_prefix(*argv, "unsorted")) { 1129 sort_dump_c = false; 1130 NEXT_ARG(); 1131 } else { 1132 p_err("unrecognized option: '%s'", *argv); 1133 err = -EINVAL; 1134 goto done; 1135 } 1136 } 1137 1138 if (!btf) { 1139 if (!base_btf && btf_is_kernel_module(btf_id)) { 1140 p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)", 1141 sysfs_vmlinux); 1142 base_btf = get_vmlinux_btf_from_sysfs(); 1143 } 1144 1145 btf = btf__load_from_kernel_by_id_split(btf_id, base_btf); 1146 if (!btf) { 1147 err = -errno; 1148 p_err("get btf by id (%u): %s", btf_id, strerror(errno)); 1149 goto done; 1150 } 1151 } 1152 1153 /* Invalid root IDs causes half emitted boilerplate and then unclean 1154 * exit. It's an ugly user experience, so handle common error here. 1155 */ 1156 for (i = 0; i < root_type_cnt; i++) { 1157 if (root_type_ids[i] >= btf__type_cnt(btf)) { 1158 err = -EINVAL; 1159 p_err("invalid root ID: %u", root_type_ids[i]); 1160 goto done; 1161 } 1162 } 1163 1164 if (dump_c) { 1165 if (json_output) { 1166 p_err("JSON output for C-syntax dump is not supported"); 1167 err = -ENOTSUP; 1168 goto done; 1169 } 1170 err = dump_btf_c(btf, root_type_ids, root_type_cnt, sort_dump_c); 1171 } else { 1172 err = dump_btf_raw(btf, root_type_ids, root_type_cnt); 1173 } 1174 1175 done: 1176 close(fd); 1177 btf__free(btf); 1178 btf__free(base); 1179 return err; 1180 } 1181 1182 static int btf_parse_fd(int *argc, char ***argv) 1183 { 1184 unsigned int id; 1185 char *endptr; 1186 int fd; 1187 1188 if (!is_prefix(*argv[0], "id")) { 1189 p_err("expected 'id', got: '%s'?", **argv); 1190 return -1; 1191 } 1192 NEXT_ARGP(); 1193 1194 id = strtoul(**argv, &endptr, 0); 1195 if (*endptr) { 1196 p_err("can't parse %s as ID", **argv); 1197 return -1; 1198 } 1199 NEXT_ARGP(); 1200 1201 fd = bpf_btf_get_fd_by_id(id); 1202 if (fd < 0) 1203 p_err("can't get BTF object by id (%u): %s", 1204 id, strerror(errno)); 1205 1206 return fd; 1207 } 1208 1209 static int 1210 build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type, 1211 void *info, __u32 *len) 1212 { 1213 static const char * const names[] = { 1214 [BPF_OBJ_UNKNOWN] = "unknown", 1215 [BPF_OBJ_PROG] = "prog", 1216 [BPF_OBJ_MAP] = "map", 1217 }; 1218 LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts_ro); 1219 __u32 btf_id, id = 0; 1220 int err; 1221 int fd; 1222 1223 opts_ro.open_flags = BPF_F_RDONLY; 1224 1225 while (true) { 1226 switch (type) { 1227 case BPF_OBJ_PROG: 1228 err = bpf_prog_get_next_id(id, &id); 1229 break; 1230 case BPF_OBJ_MAP: 1231 err = bpf_map_get_next_id(id, &id); 1232 break; 1233 default: 1234 err = -1; 1235 p_err("unexpected object type: %u", type); 1236 goto err_free; 1237 } 1238 if (err) { 1239 if (errno == ENOENT) { 1240 err = 0; 1241 break; 1242 } 1243 p_err("can't get next %s: %s%s", names[type], 1244 strerror(errno), 1245 errno == EINVAL ? " -- kernel too old?" : ""); 1246 goto err_free; 1247 } 1248 1249 switch (type) { 1250 case BPF_OBJ_PROG: 1251 fd = bpf_prog_get_fd_by_id(id); 1252 break; 1253 case BPF_OBJ_MAP: 1254 fd = bpf_map_get_fd_by_id_opts(id, &opts_ro); 1255 break; 1256 default: 1257 err = -1; 1258 p_err("unexpected object type: %u", type); 1259 goto err_free; 1260 } 1261 if (fd < 0) { 1262 if (errno == ENOENT) 1263 continue; 1264 p_err("can't get %s by id (%u): %s", names[type], id, 1265 strerror(errno)); 1266 err = -1; 1267 goto err_free; 1268 } 1269 1270 memset(info, 0, *len); 1271 if (type == BPF_OBJ_PROG) 1272 err = bpf_prog_get_info_by_fd(fd, info, len); 1273 else 1274 err = bpf_map_get_info_by_fd(fd, info, len); 1275 close(fd); 1276 if (err) { 1277 p_err("can't get %s info: %s", names[type], 1278 strerror(errno)); 1279 goto err_free; 1280 } 1281 1282 switch (type) { 1283 case BPF_OBJ_PROG: 1284 btf_id = ((struct bpf_prog_info *)info)->btf_id; 1285 break; 1286 case BPF_OBJ_MAP: 1287 btf_id = ((struct bpf_map_info *)info)->btf_id; 1288 break; 1289 default: 1290 err = -1; 1291 p_err("unexpected object type: %u", type); 1292 goto err_free; 1293 } 1294 if (!btf_id) 1295 continue; 1296 1297 err = hashmap__append(tab, btf_id, id); 1298 if (err) { 1299 p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s", 1300 btf_id, id, strerror(-err)); 1301 goto err_free; 1302 } 1303 } 1304 1305 return 0; 1306 1307 err_free: 1308 hashmap__free(tab); 1309 return err; 1310 } 1311 1312 static int 1313 build_btf_tables(struct hashmap *btf_prog_table, 1314 struct hashmap *btf_map_table) 1315 { 1316 struct bpf_prog_info prog_info; 1317 __u32 prog_len = sizeof(prog_info); 1318 struct bpf_map_info map_info; 1319 __u32 map_len = sizeof(map_info); 1320 int err = 0; 1321 1322 err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info, 1323 &prog_len); 1324 if (err) 1325 return err; 1326 1327 err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info, 1328 &map_len); 1329 if (err) { 1330 hashmap__free(btf_prog_table); 1331 return err; 1332 } 1333 1334 return 0; 1335 } 1336 1337 static void 1338 show_btf_plain(struct bpf_btf_info *info, int fd, 1339 struct hashmap *btf_prog_table, 1340 struct hashmap *btf_map_table) 1341 { 1342 struct hashmap_entry *entry; 1343 const char *name = u64_to_ptr(info->name); 1344 int n; 1345 1346 printf("%u: ", info->id); 1347 if (info->kernel_btf) 1348 printf("name [%s] ", name); 1349 else if (name && name[0]) 1350 printf("name %s ", name); 1351 else 1352 printf("name <anon> "); 1353 printf("size %uB", info->btf_size); 1354 1355 n = 0; 1356 hashmap__for_each_key_entry(btf_prog_table, entry, info->id) { 1357 printf("%s%lu", n++ == 0 ? " prog_ids " : ",", (unsigned long)entry->value); 1358 } 1359 1360 n = 0; 1361 hashmap__for_each_key_entry(btf_map_table, entry, info->id) { 1362 printf("%s%lu", n++ == 0 ? " map_ids " : ",", (unsigned long)entry->value); 1363 } 1364 1365 emit_obj_refs_plain(refs_table, info->id, "\n\tpids "); 1366 1367 printf("\n"); 1368 } 1369 1370 static void 1371 show_btf_json(struct bpf_btf_info *info, int fd, 1372 struct hashmap *btf_prog_table, 1373 struct hashmap *btf_map_table) 1374 { 1375 struct hashmap_entry *entry; 1376 const char *name = u64_to_ptr(info->name); 1377 1378 jsonw_start_object(json_wtr); /* btf object */ 1379 jsonw_uint_field(json_wtr, "id", info->id); 1380 jsonw_uint_field(json_wtr, "size", info->btf_size); 1381 1382 jsonw_name(json_wtr, "prog_ids"); 1383 jsonw_start_array(json_wtr); /* prog_ids */ 1384 hashmap__for_each_key_entry(btf_prog_table, entry, info->id) { 1385 jsonw_uint(json_wtr, entry->value); 1386 } 1387 jsonw_end_array(json_wtr); /* prog_ids */ 1388 1389 jsonw_name(json_wtr, "map_ids"); 1390 jsonw_start_array(json_wtr); /* map_ids */ 1391 hashmap__for_each_key_entry(btf_map_table, entry, info->id) { 1392 jsonw_uint(json_wtr, entry->value); 1393 } 1394 jsonw_end_array(json_wtr); /* map_ids */ 1395 1396 emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */ 1397 1398 jsonw_bool_field(json_wtr, "kernel", info->kernel_btf); 1399 1400 if (name && name[0]) 1401 jsonw_string_field(json_wtr, "name", name); 1402 1403 jsonw_end_object(json_wtr); /* btf object */ 1404 } 1405 1406 static int 1407 show_btf(int fd, struct hashmap *btf_prog_table, 1408 struct hashmap *btf_map_table) 1409 { 1410 struct bpf_btf_info info; 1411 __u32 len = sizeof(info); 1412 char name[64]; 1413 int err; 1414 1415 memset(&info, 0, sizeof(info)); 1416 err = bpf_btf_get_info_by_fd(fd, &info, &len); 1417 if (err) { 1418 p_err("can't get BTF object info: %s", strerror(errno)); 1419 return -1; 1420 } 1421 /* if kernel support emitting BTF object name, pass name pointer */ 1422 if (info.name_len) { 1423 memset(&info, 0, sizeof(info)); 1424 info.name_len = sizeof(name); 1425 info.name = ptr_to_u64(name); 1426 len = sizeof(info); 1427 1428 err = bpf_btf_get_info_by_fd(fd, &info, &len); 1429 if (err) { 1430 p_err("can't get BTF object info: %s", strerror(errno)); 1431 return -1; 1432 } 1433 } 1434 1435 if (json_output) 1436 show_btf_json(&info, fd, btf_prog_table, btf_map_table); 1437 else 1438 show_btf_plain(&info, fd, btf_prog_table, btf_map_table); 1439 1440 return 0; 1441 } 1442 1443 static int do_show(int argc, char **argv) 1444 { 1445 struct hashmap *btf_prog_table; 1446 struct hashmap *btf_map_table; 1447 int err, fd = -1; 1448 __u32 id = 0; 1449 1450 if (argc == 2) { 1451 fd = btf_parse_fd(&argc, &argv); 1452 if (fd < 0) 1453 return -1; 1454 } 1455 1456 if (argc) { 1457 if (fd >= 0) 1458 close(fd); 1459 return BAD_ARG(); 1460 } 1461 1462 btf_prog_table = hashmap__new(hash_fn_for_key_as_id, 1463 equal_fn_for_key_as_id, NULL); 1464 btf_map_table = hashmap__new(hash_fn_for_key_as_id, 1465 equal_fn_for_key_as_id, NULL); 1466 if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) { 1467 hashmap__free(btf_prog_table); 1468 hashmap__free(btf_map_table); 1469 if (fd >= 0) 1470 close(fd); 1471 p_err("failed to create hashmap for object references"); 1472 return -1; 1473 } 1474 err = build_btf_tables(btf_prog_table, btf_map_table); 1475 if (err) { 1476 if (fd >= 0) 1477 close(fd); 1478 return err; 1479 } 1480 build_obj_refs_table(&refs_table, BPF_OBJ_BTF); 1481 1482 if (fd >= 0) { 1483 err = show_btf(fd, btf_prog_table, btf_map_table); 1484 close(fd); 1485 goto exit_free; 1486 } 1487 1488 if (json_output) 1489 jsonw_start_array(json_wtr); /* root array */ 1490 1491 while (true) { 1492 err = bpf_btf_get_next_id(id, &id); 1493 if (err) { 1494 if (errno == ENOENT) { 1495 err = 0; 1496 break; 1497 } 1498 p_err("can't get next BTF object: %s%s", 1499 strerror(errno), 1500 errno == EINVAL ? " -- kernel too old?" : ""); 1501 err = -1; 1502 break; 1503 } 1504 1505 fd = bpf_btf_get_fd_by_id(id); 1506 if (fd < 0) { 1507 if (errno == ENOENT) 1508 continue; 1509 p_err("can't get BTF object by id (%u): %s", 1510 id, strerror(errno)); 1511 err = -1; 1512 break; 1513 } 1514 1515 err = show_btf(fd, btf_prog_table, btf_map_table); 1516 close(fd); 1517 if (err) 1518 break; 1519 } 1520 1521 if (json_output) 1522 jsonw_end_array(json_wtr); /* root array */ 1523 1524 exit_free: 1525 hashmap__free(btf_prog_table); 1526 hashmap__free(btf_map_table); 1527 delete_obj_refs_table(refs_table); 1528 1529 return err; 1530 } 1531 1532 static int do_help(int argc, char **argv) 1533 { 1534 if (json_output) { 1535 jsonw_null(json_wtr); 1536 return 0; 1537 } 1538 1539 fprintf(stderr, 1540 "Usage: %1$s %2$s { show | list } [id BTF_ID]\n" 1541 " %1$s %2$s dump BTF_SRC [format FORMAT] [root_id ROOT_ID]\n" 1542 " %1$s %2$s help\n" 1543 "\n" 1544 " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] |\n" 1545 " file FILE [file FILE]... }\n" 1546 " FORMAT := { raw | c [unsorted] }\n" 1547 " " HELP_SPEC_MAP "\n" 1548 " " HELP_SPEC_PROGRAM "\n" 1549 " " HELP_SPEC_OPTIONS " |\n" 1550 " {-B|--base-btf} }\n" 1551 "", 1552 bin_name, "btf"); 1553 1554 return 0; 1555 } 1556 1557 static const struct cmd cmds[] = { 1558 { "show", do_show }, 1559 { "list", do_show }, 1560 { "help", do_help }, 1561 { "dump", do_dump }, 1562 { 0 } 1563 }; 1564 1565 int do_btf(int argc, char **argv) 1566 { 1567 return cmd_select(cmds, argc, argv, do_help); 1568 } 1569