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