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