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 /* Use name of the first element for anonymous enums if allowed */ 565 if (!from_ref && !t->name_off && btf_vlen(t)) 566 name_off = btf_enum(t)->name_off; 567 568 return btf__name_by_offset(btf, name_off); 569 } 570 case BTF_KIND_ARRAY: 571 return btf_type_sort_name(btf, btf_array(t)->type, true); 572 case BTF_KIND_TYPE_TAG: 573 case BTF_KIND_CONST: 574 case BTF_KIND_PTR: 575 case BTF_KIND_VOLATILE: 576 case BTF_KIND_RESTRICT: 577 case BTF_KIND_TYPEDEF: 578 case BTF_KIND_DECL_TAG: 579 return btf_type_sort_name(btf, t->type, true); 580 default: 581 return btf__name_by_offset(btf, t->name_off); 582 } 583 return NULL; 584 } 585 586 static int btf_type_compare(const void *left, const void *right) 587 { 588 const struct sort_datum *d1 = (const struct sort_datum *)left; 589 const struct sort_datum *d2 = (const struct sort_datum *)right; 590 int r; 591 592 if (d1->type_rank != d2->type_rank) 593 return d1->type_rank < d2->type_rank ? -1 : 1; 594 595 r = strcmp(d1->sort_name, d2->sort_name); 596 if (r) 597 return r; 598 599 return strcmp(d1->own_name, d2->own_name); 600 } 601 602 static struct sort_datum *sort_btf_c(const struct btf *btf) 603 { 604 struct sort_datum *datums; 605 int n; 606 607 n = btf__type_cnt(btf); 608 datums = malloc(sizeof(struct sort_datum) * n); 609 if (!datums) 610 return NULL; 611 612 for (int i = 0; i < n; ++i) { 613 struct sort_datum *d = datums + i; 614 const struct btf_type *t = btf__type_by_id(btf, i); 615 616 d->index = i; 617 d->type_rank = btf_type_rank(btf, i, false); 618 d->sort_name = btf_type_sort_name(btf, i, false); 619 d->own_name = btf__name_by_offset(btf, t->name_off); 620 } 621 622 qsort(datums, n, sizeof(struct sort_datum), btf_type_compare); 623 624 return datums; 625 } 626 627 static int dump_btf_c(const struct btf *btf, 628 __u32 *root_type_ids, int root_type_cnt, bool sort_dump) 629 { 630 struct sort_datum *datums = NULL; 631 struct btf_dump *d; 632 int err = 0, i; 633 634 d = btf_dump__new(btf, btf_dump_printf, NULL, NULL); 635 if (!d) 636 return -errno; 637 638 printf("#ifndef __VMLINUX_H__\n"); 639 printf("#define __VMLINUX_H__\n"); 640 printf("\n"); 641 printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n"); 642 printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n"); 643 printf("#endif\n\n"); 644 printf("#ifndef __ksym\n"); 645 printf("#define __ksym __attribute__((section(\".ksyms\")))\n"); 646 printf("#endif\n\n"); 647 printf("#ifndef __weak\n"); 648 printf("#define __weak __attribute__((weak))\n"); 649 printf("#endif\n\n"); 650 651 if (root_type_cnt) { 652 for (i = 0; i < root_type_cnt; i++) { 653 err = btf_dump__dump_type(d, root_type_ids[i]); 654 if (err) 655 goto done; 656 } 657 } else { 658 int cnt = btf__type_cnt(btf); 659 660 if (sort_dump) 661 datums = sort_btf_c(btf); 662 for (i = 1; i < cnt; i++) { 663 int idx = datums ? datums[i].index : i; 664 665 err = btf_dump__dump_type(d, idx); 666 if (err) 667 goto done; 668 } 669 670 err = dump_btf_kfuncs(d, btf); 671 if (err) 672 goto done; 673 } 674 675 printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n"); 676 printf("#pragma clang attribute pop\n"); 677 printf("#endif\n"); 678 printf("\n"); 679 printf("#endif /* __VMLINUX_H__ */\n"); 680 681 done: 682 free(datums); 683 btf_dump__free(d); 684 return err; 685 } 686 687 static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux"; 688 689 static struct btf *get_vmlinux_btf_from_sysfs(void) 690 { 691 struct btf *base; 692 693 base = btf__parse(sysfs_vmlinux, NULL); 694 if (!base) 695 p_err("failed to parse vmlinux BTF at '%s': %d\n", 696 sysfs_vmlinux, -errno); 697 698 return base; 699 } 700 701 #define BTF_NAME_BUFF_LEN 64 702 703 static bool btf_is_kernel_module(__u32 btf_id) 704 { 705 struct bpf_btf_info btf_info = {}; 706 char btf_name[BTF_NAME_BUFF_LEN]; 707 int btf_fd; 708 __u32 len; 709 int err; 710 711 btf_fd = bpf_btf_get_fd_by_id(btf_id); 712 if (btf_fd < 0) { 713 p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno)); 714 return false; 715 } 716 717 len = sizeof(btf_info); 718 btf_info.name = ptr_to_u64(btf_name); 719 btf_info.name_len = sizeof(btf_name); 720 err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len); 721 close(btf_fd); 722 if (err) { 723 p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno)); 724 return false; 725 } 726 727 return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0; 728 } 729 730 static int do_dump(int argc, char **argv) 731 { 732 bool dump_c = false, sort_dump_c = true; 733 struct btf *btf = NULL, *base = NULL; 734 __u32 root_type_ids[2]; 735 int root_type_cnt = 0; 736 __u32 btf_id = -1; 737 const char *src; 738 int fd = -1; 739 int err = 0; 740 741 if (!REQ_ARGS(2)) { 742 usage(); 743 return -1; 744 } 745 src = GET_ARG(); 746 if (is_prefix(src, "map")) { 747 struct bpf_map_info info = {}; 748 __u32 len = sizeof(info); 749 750 if (!REQ_ARGS(2)) { 751 usage(); 752 return -1; 753 } 754 755 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 756 if (fd < 0) 757 return -1; 758 759 btf_id = info.btf_id; 760 if (argc && is_prefix(*argv, "key")) { 761 root_type_ids[root_type_cnt++] = info.btf_key_type_id; 762 NEXT_ARG(); 763 } else if (argc && is_prefix(*argv, "value")) { 764 root_type_ids[root_type_cnt++] = info.btf_value_type_id; 765 NEXT_ARG(); 766 } else if (argc && is_prefix(*argv, "all")) { 767 NEXT_ARG(); 768 } else if (argc && is_prefix(*argv, "kv")) { 769 root_type_ids[root_type_cnt++] = info.btf_key_type_id; 770 root_type_ids[root_type_cnt++] = info.btf_value_type_id; 771 NEXT_ARG(); 772 } else { 773 root_type_ids[root_type_cnt++] = info.btf_key_type_id; 774 root_type_ids[root_type_cnt++] = info.btf_value_type_id; 775 } 776 } else if (is_prefix(src, "prog")) { 777 struct bpf_prog_info info = {}; 778 __u32 len = sizeof(info); 779 780 if (!REQ_ARGS(2)) { 781 usage(); 782 return -1; 783 } 784 785 fd = prog_parse_fd(&argc, &argv); 786 if (fd < 0) 787 return -1; 788 789 err = bpf_prog_get_info_by_fd(fd, &info, &len); 790 if (err) { 791 p_err("can't get prog info: %s", strerror(errno)); 792 goto done; 793 } 794 795 btf_id = info.btf_id; 796 } else if (is_prefix(src, "id")) { 797 char *endptr; 798 799 btf_id = strtoul(*argv, &endptr, 0); 800 if (*endptr) { 801 p_err("can't parse %s as ID", *argv); 802 return -1; 803 } 804 NEXT_ARG(); 805 } else if (is_prefix(src, "file")) { 806 const char sysfs_prefix[] = "/sys/kernel/btf/"; 807 808 if (!base_btf && 809 strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 && 810 strcmp(*argv, sysfs_vmlinux) != 0) 811 base = get_vmlinux_btf_from_sysfs(); 812 813 btf = btf__parse_split(*argv, base ?: base_btf); 814 if (!btf) { 815 err = -errno; 816 p_err("failed to load BTF from %s: %s", 817 *argv, strerror(errno)); 818 goto done; 819 } 820 NEXT_ARG(); 821 } else { 822 err = -1; 823 p_err("unrecognized BTF source specifier: '%s'", src); 824 goto done; 825 } 826 827 while (argc) { 828 if (is_prefix(*argv, "format")) { 829 NEXT_ARG(); 830 if (argc < 1) { 831 p_err("expecting value for 'format' option\n"); 832 err = -EINVAL; 833 goto done; 834 } 835 if (strcmp(*argv, "c") == 0) { 836 dump_c = true; 837 } else if (strcmp(*argv, "raw") == 0) { 838 dump_c = false; 839 } else { 840 p_err("unrecognized format specifier: '%s', possible values: raw, c", 841 *argv); 842 err = -EINVAL; 843 goto done; 844 } 845 NEXT_ARG(); 846 } else if (is_prefix(*argv, "unsorted")) { 847 sort_dump_c = false; 848 NEXT_ARG(); 849 } else { 850 p_err("unrecognized option: '%s'", *argv); 851 err = -EINVAL; 852 goto done; 853 } 854 } 855 856 if (!btf) { 857 if (!base_btf && btf_is_kernel_module(btf_id)) { 858 p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)", 859 sysfs_vmlinux); 860 base_btf = get_vmlinux_btf_from_sysfs(); 861 } 862 863 btf = btf__load_from_kernel_by_id_split(btf_id, base_btf); 864 if (!btf) { 865 err = -errno; 866 p_err("get btf by id (%u): %s", btf_id, strerror(errno)); 867 goto done; 868 } 869 } 870 871 if (dump_c) { 872 if (json_output) { 873 p_err("JSON output for C-syntax dump is not supported"); 874 err = -ENOTSUP; 875 goto done; 876 } 877 err = dump_btf_c(btf, root_type_ids, root_type_cnt, sort_dump_c); 878 } else { 879 err = dump_btf_raw(btf, root_type_ids, root_type_cnt); 880 } 881 882 done: 883 close(fd); 884 btf__free(btf); 885 btf__free(base); 886 return err; 887 } 888 889 static int btf_parse_fd(int *argc, char ***argv) 890 { 891 unsigned int id; 892 char *endptr; 893 int fd; 894 895 if (!is_prefix(*argv[0], "id")) { 896 p_err("expected 'id', got: '%s'?", **argv); 897 return -1; 898 } 899 NEXT_ARGP(); 900 901 id = strtoul(**argv, &endptr, 0); 902 if (*endptr) { 903 p_err("can't parse %s as ID", **argv); 904 return -1; 905 } 906 NEXT_ARGP(); 907 908 fd = bpf_btf_get_fd_by_id(id); 909 if (fd < 0) 910 p_err("can't get BTF object by id (%u): %s", 911 id, strerror(errno)); 912 913 return fd; 914 } 915 916 static int 917 build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type, 918 void *info, __u32 *len) 919 { 920 static const char * const names[] = { 921 [BPF_OBJ_UNKNOWN] = "unknown", 922 [BPF_OBJ_PROG] = "prog", 923 [BPF_OBJ_MAP] = "map", 924 }; 925 __u32 btf_id, id = 0; 926 int err; 927 int fd; 928 929 while (true) { 930 switch (type) { 931 case BPF_OBJ_PROG: 932 err = bpf_prog_get_next_id(id, &id); 933 break; 934 case BPF_OBJ_MAP: 935 err = bpf_map_get_next_id(id, &id); 936 break; 937 default: 938 err = -1; 939 p_err("unexpected object type: %d", type); 940 goto err_free; 941 } 942 if (err) { 943 if (errno == ENOENT) { 944 err = 0; 945 break; 946 } 947 p_err("can't get next %s: %s%s", names[type], 948 strerror(errno), 949 errno == EINVAL ? " -- kernel too old?" : ""); 950 goto err_free; 951 } 952 953 switch (type) { 954 case BPF_OBJ_PROG: 955 fd = bpf_prog_get_fd_by_id(id); 956 break; 957 case BPF_OBJ_MAP: 958 fd = bpf_map_get_fd_by_id(id); 959 break; 960 default: 961 err = -1; 962 p_err("unexpected object type: %d", type); 963 goto err_free; 964 } 965 if (fd < 0) { 966 if (errno == ENOENT) 967 continue; 968 p_err("can't get %s by id (%u): %s", names[type], id, 969 strerror(errno)); 970 err = -1; 971 goto err_free; 972 } 973 974 memset(info, 0, *len); 975 if (type == BPF_OBJ_PROG) 976 err = bpf_prog_get_info_by_fd(fd, info, len); 977 else 978 err = bpf_map_get_info_by_fd(fd, info, len); 979 close(fd); 980 if (err) { 981 p_err("can't get %s info: %s", names[type], 982 strerror(errno)); 983 goto err_free; 984 } 985 986 switch (type) { 987 case BPF_OBJ_PROG: 988 btf_id = ((struct bpf_prog_info *)info)->btf_id; 989 break; 990 case BPF_OBJ_MAP: 991 btf_id = ((struct bpf_map_info *)info)->btf_id; 992 break; 993 default: 994 err = -1; 995 p_err("unexpected object type: %d", type); 996 goto err_free; 997 } 998 if (!btf_id) 999 continue; 1000 1001 err = hashmap__append(tab, btf_id, id); 1002 if (err) { 1003 p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s", 1004 btf_id, id, strerror(-err)); 1005 goto err_free; 1006 } 1007 } 1008 1009 return 0; 1010 1011 err_free: 1012 hashmap__free(tab); 1013 return err; 1014 } 1015 1016 static int 1017 build_btf_tables(struct hashmap *btf_prog_table, 1018 struct hashmap *btf_map_table) 1019 { 1020 struct bpf_prog_info prog_info; 1021 __u32 prog_len = sizeof(prog_info); 1022 struct bpf_map_info map_info; 1023 __u32 map_len = sizeof(map_info); 1024 int err = 0; 1025 1026 err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info, 1027 &prog_len); 1028 if (err) 1029 return err; 1030 1031 err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info, 1032 &map_len); 1033 if (err) { 1034 hashmap__free(btf_prog_table); 1035 return err; 1036 } 1037 1038 return 0; 1039 } 1040 1041 static void 1042 show_btf_plain(struct bpf_btf_info *info, int fd, 1043 struct hashmap *btf_prog_table, 1044 struct hashmap *btf_map_table) 1045 { 1046 struct hashmap_entry *entry; 1047 const char *name = u64_to_ptr(info->name); 1048 int n; 1049 1050 printf("%u: ", info->id); 1051 if (info->kernel_btf) 1052 printf("name [%s] ", name); 1053 else if (name && name[0]) 1054 printf("name %s ", name); 1055 else 1056 printf("name <anon> "); 1057 printf("size %uB", info->btf_size); 1058 1059 n = 0; 1060 hashmap__for_each_key_entry(btf_prog_table, entry, info->id) { 1061 printf("%s%lu", n++ == 0 ? " prog_ids " : ",", entry->value); 1062 } 1063 1064 n = 0; 1065 hashmap__for_each_key_entry(btf_map_table, entry, info->id) { 1066 printf("%s%lu", n++ == 0 ? " map_ids " : ",", entry->value); 1067 } 1068 1069 emit_obj_refs_plain(refs_table, info->id, "\n\tpids "); 1070 1071 printf("\n"); 1072 } 1073 1074 static void 1075 show_btf_json(struct bpf_btf_info *info, int fd, 1076 struct hashmap *btf_prog_table, 1077 struct hashmap *btf_map_table) 1078 { 1079 struct hashmap_entry *entry; 1080 const char *name = u64_to_ptr(info->name); 1081 1082 jsonw_start_object(json_wtr); /* btf object */ 1083 jsonw_uint_field(json_wtr, "id", info->id); 1084 jsonw_uint_field(json_wtr, "size", info->btf_size); 1085 1086 jsonw_name(json_wtr, "prog_ids"); 1087 jsonw_start_array(json_wtr); /* prog_ids */ 1088 hashmap__for_each_key_entry(btf_prog_table, entry, info->id) { 1089 jsonw_uint(json_wtr, entry->value); 1090 } 1091 jsonw_end_array(json_wtr); /* prog_ids */ 1092 1093 jsonw_name(json_wtr, "map_ids"); 1094 jsonw_start_array(json_wtr); /* map_ids */ 1095 hashmap__for_each_key_entry(btf_map_table, entry, info->id) { 1096 jsonw_uint(json_wtr, entry->value); 1097 } 1098 jsonw_end_array(json_wtr); /* map_ids */ 1099 1100 emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */ 1101 1102 jsonw_bool_field(json_wtr, "kernel", info->kernel_btf); 1103 1104 if (name && name[0]) 1105 jsonw_string_field(json_wtr, "name", name); 1106 1107 jsonw_end_object(json_wtr); /* btf object */ 1108 } 1109 1110 static int 1111 show_btf(int fd, struct hashmap *btf_prog_table, 1112 struct hashmap *btf_map_table) 1113 { 1114 struct bpf_btf_info info; 1115 __u32 len = sizeof(info); 1116 char name[64]; 1117 int err; 1118 1119 memset(&info, 0, sizeof(info)); 1120 err = bpf_btf_get_info_by_fd(fd, &info, &len); 1121 if (err) { 1122 p_err("can't get BTF object info: %s", strerror(errno)); 1123 return -1; 1124 } 1125 /* if kernel support emitting BTF object name, pass name pointer */ 1126 if (info.name_len) { 1127 memset(&info, 0, sizeof(info)); 1128 info.name_len = sizeof(name); 1129 info.name = ptr_to_u64(name); 1130 len = sizeof(info); 1131 1132 err = bpf_btf_get_info_by_fd(fd, &info, &len); 1133 if (err) { 1134 p_err("can't get BTF object info: %s", strerror(errno)); 1135 return -1; 1136 } 1137 } 1138 1139 if (json_output) 1140 show_btf_json(&info, fd, btf_prog_table, btf_map_table); 1141 else 1142 show_btf_plain(&info, fd, btf_prog_table, btf_map_table); 1143 1144 return 0; 1145 } 1146 1147 static int do_show(int argc, char **argv) 1148 { 1149 struct hashmap *btf_prog_table; 1150 struct hashmap *btf_map_table; 1151 int err, fd = -1; 1152 __u32 id = 0; 1153 1154 if (argc == 2) { 1155 fd = btf_parse_fd(&argc, &argv); 1156 if (fd < 0) 1157 return -1; 1158 } 1159 1160 if (argc) { 1161 if (fd >= 0) 1162 close(fd); 1163 return BAD_ARG(); 1164 } 1165 1166 btf_prog_table = hashmap__new(hash_fn_for_key_as_id, 1167 equal_fn_for_key_as_id, NULL); 1168 btf_map_table = hashmap__new(hash_fn_for_key_as_id, 1169 equal_fn_for_key_as_id, NULL); 1170 if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) { 1171 hashmap__free(btf_prog_table); 1172 hashmap__free(btf_map_table); 1173 if (fd >= 0) 1174 close(fd); 1175 p_err("failed to create hashmap for object references"); 1176 return -1; 1177 } 1178 err = build_btf_tables(btf_prog_table, btf_map_table); 1179 if (err) { 1180 if (fd >= 0) 1181 close(fd); 1182 return err; 1183 } 1184 build_obj_refs_table(&refs_table, BPF_OBJ_BTF); 1185 1186 if (fd >= 0) { 1187 err = show_btf(fd, btf_prog_table, btf_map_table); 1188 close(fd); 1189 goto exit_free; 1190 } 1191 1192 if (json_output) 1193 jsonw_start_array(json_wtr); /* root array */ 1194 1195 while (true) { 1196 err = bpf_btf_get_next_id(id, &id); 1197 if (err) { 1198 if (errno == ENOENT) { 1199 err = 0; 1200 break; 1201 } 1202 p_err("can't get next BTF object: %s%s", 1203 strerror(errno), 1204 errno == EINVAL ? " -- kernel too old?" : ""); 1205 err = -1; 1206 break; 1207 } 1208 1209 fd = bpf_btf_get_fd_by_id(id); 1210 if (fd < 0) { 1211 if (errno == ENOENT) 1212 continue; 1213 p_err("can't get BTF object by id (%u): %s", 1214 id, strerror(errno)); 1215 err = -1; 1216 break; 1217 } 1218 1219 err = show_btf(fd, btf_prog_table, btf_map_table); 1220 close(fd); 1221 if (err) 1222 break; 1223 } 1224 1225 if (json_output) 1226 jsonw_end_array(json_wtr); /* root array */ 1227 1228 exit_free: 1229 hashmap__free(btf_prog_table); 1230 hashmap__free(btf_map_table); 1231 delete_obj_refs_table(refs_table); 1232 1233 return err; 1234 } 1235 1236 static int do_help(int argc, char **argv) 1237 { 1238 if (json_output) { 1239 jsonw_null(json_wtr); 1240 return 0; 1241 } 1242 1243 fprintf(stderr, 1244 "Usage: %1$s %2$s { show | list } [id BTF_ID]\n" 1245 " %1$s %2$s dump BTF_SRC [format FORMAT]\n" 1246 " %1$s %2$s help\n" 1247 "\n" 1248 " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n" 1249 " FORMAT := { raw | c [unsorted] }\n" 1250 " " HELP_SPEC_MAP "\n" 1251 " " HELP_SPEC_PROGRAM "\n" 1252 " " HELP_SPEC_OPTIONS " |\n" 1253 " {-B|--base-btf} }\n" 1254 "", 1255 bin_name, "btf"); 1256 1257 return 0; 1258 } 1259 1260 static const struct cmd cmds[] = { 1261 { "show", do_show }, 1262 { "list", do_show }, 1263 { "help", do_help }, 1264 { "dump", do_dump }, 1265 { 0 } 1266 }; 1267 1268 int do_btf(int argc, char **argv) 1269 { 1270 return cmd_select(cmds, argc, argv, do_help); 1271 } 1272