1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 3 /* 4 * resolve_btfids scans ELF object for .BTF_ids section and resolves 5 * its symbols with BTF ID values. 6 * 7 * Each symbol points to 4 bytes data and is expected to have 8 * following name syntax: 9 * 10 * __BTF_ID__<type>__<symbol>[__<id>] 11 * 12 * type is: 13 * 14 * func - lookup BTF_KIND_FUNC symbol with <symbol> name 15 * and store its ID into the data: 16 * 17 * __BTF_ID__func__vfs_close__1: 18 * .zero 4 19 * 20 * struct - lookup BTF_KIND_STRUCT symbol with <symbol> name 21 * and store its ID into the data: 22 * 23 * __BTF_ID__struct__sk_buff__1: 24 * .zero 4 25 * 26 * union - lookup BTF_KIND_UNION symbol with <symbol> name 27 * and store its ID into the data: 28 * 29 * __BTF_ID__union__thread_union__1: 30 * .zero 4 31 * 32 * typedef - lookup BTF_KIND_TYPEDEF symbol with <symbol> name 33 * and store its ID into the data: 34 * 35 * __BTF_ID__typedef__pid_t__1: 36 * .zero 4 37 * 38 * set - store symbol size into first 4 bytes and sort following 39 * ID list 40 * 41 * __BTF_ID__set__list: 42 * .zero 4 43 * list: 44 * __BTF_ID__func__vfs_getattr__3: 45 * .zero 4 46 * __BTF_ID__func__vfs_fallocate__4: 47 * .zero 4 48 * 49 * set8 - store symbol size into first 4 bytes and sort following 50 * ID list 51 * 52 * __BTF_ID__set8__list: 53 * .zero 8 54 * list: 55 * __BTF_ID__func__vfs_getattr__3: 56 * .zero 4 57 * .word (1 << 0) | (1 << 2) 58 * __BTF_ID__func__vfs_fallocate__5: 59 * .zero 4 60 * .word (1 << 3) | (1 << 1) | (1 << 2) 61 */ 62 63 #define _GNU_SOURCE 64 #include <stdio.h> 65 #include <string.h> 66 #include <unistd.h> 67 #include <stdlib.h> 68 #include <libelf.h> 69 #include <gelf.h> 70 #include <sys/stat.h> 71 #include <fcntl.h> 72 #include <errno.h> 73 #include <linux/btf_ids.h> 74 #include <linux/rbtree.h> 75 #include <linux/zalloc.h> 76 #include <linux/err.h> 77 #include <bpf/btf.h> 78 #include <bpf/libbpf.h> 79 #include <subcmd/parse-options.h> 80 81 #define BTF_IDS_SECTION ".BTF_ids" 82 #define BTF_ID_PREFIX "__BTF_ID__" 83 84 #define BTF_STRUCT "struct" 85 #define BTF_UNION "union" 86 #define BTF_TYPEDEF "typedef" 87 #define BTF_FUNC "func" 88 #define BTF_SET "set" 89 #define BTF_SET8 "set8" 90 91 #define ADDR_CNT 100 92 93 #if __BYTE_ORDER == __LITTLE_ENDIAN 94 # define ELFDATANATIVE ELFDATA2LSB 95 #elif __BYTE_ORDER == __BIG_ENDIAN 96 # define ELFDATANATIVE ELFDATA2MSB 97 #else 98 # error "Unknown machine endianness!" 99 #endif 100 101 struct btf_id { 102 struct rb_node rb_node; 103 char *name; 104 union { 105 int id; 106 int cnt; 107 }; 108 int addr_cnt; 109 bool is_set; 110 bool is_set8; 111 Elf64_Addr addr[ADDR_CNT]; 112 }; 113 114 struct object { 115 const char *path; 116 const char *btf; 117 const char *base_btf_path; 118 119 struct { 120 int fd; 121 Elf *elf; 122 Elf_Data *symbols; 123 Elf_Data *idlist; 124 int symbols_shndx; 125 int idlist_shndx; 126 size_t strtabidx; 127 unsigned long idlist_addr; 128 int encoding; 129 } efile; 130 131 struct rb_root sets; 132 struct rb_root structs; 133 struct rb_root unions; 134 struct rb_root typedefs; 135 struct rb_root funcs; 136 137 int nr_funcs; 138 int nr_structs; 139 int nr_unions; 140 int nr_typedefs; 141 }; 142 143 static int verbose; 144 145 static int eprintf(int level, int var, const char *fmt, ...) 146 { 147 va_list args; 148 int ret = 0; 149 150 if (var >= level) { 151 va_start(args, fmt); 152 ret = vfprintf(stderr, fmt, args); 153 va_end(args); 154 } 155 return ret; 156 } 157 158 #ifndef pr_fmt 159 #define pr_fmt(fmt) fmt 160 #endif 161 162 #define pr_debug(fmt, ...) \ 163 eprintf(1, verbose, pr_fmt(fmt), ##__VA_ARGS__) 164 #define pr_debugN(n, fmt, ...) \ 165 eprintf(n, verbose, pr_fmt(fmt), ##__VA_ARGS__) 166 #define pr_debug2(fmt, ...) pr_debugN(2, pr_fmt(fmt), ##__VA_ARGS__) 167 #define pr_err(fmt, ...) \ 168 eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__) 169 #define pr_info(fmt, ...) \ 170 eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__) 171 172 static bool is_btf_id(const char *name) 173 { 174 return name && !strncmp(name, BTF_ID_PREFIX, sizeof(BTF_ID_PREFIX) - 1); 175 } 176 177 static struct btf_id *btf_id__find(struct rb_root *root, const char *name) 178 { 179 struct rb_node *p = root->rb_node; 180 struct btf_id *id; 181 int cmp; 182 183 while (p) { 184 id = rb_entry(p, struct btf_id, rb_node); 185 cmp = strcmp(id->name, name); 186 if (cmp < 0) 187 p = p->rb_left; 188 else if (cmp > 0) 189 p = p->rb_right; 190 else 191 return id; 192 } 193 return NULL; 194 } 195 196 static struct btf_id * 197 btf_id__add(struct rb_root *root, char *name, bool unique) 198 { 199 struct rb_node **p = &root->rb_node; 200 struct rb_node *parent = NULL; 201 struct btf_id *id; 202 int cmp; 203 204 while (*p != NULL) { 205 parent = *p; 206 id = rb_entry(parent, struct btf_id, rb_node); 207 cmp = strcmp(id->name, name); 208 if (cmp < 0) 209 p = &(*p)->rb_left; 210 else if (cmp > 0) 211 p = &(*p)->rb_right; 212 else 213 return unique ? NULL : id; 214 } 215 216 id = zalloc(sizeof(*id)); 217 if (id) { 218 pr_debug("adding symbol %s\n", name); 219 id->name = name; 220 rb_link_node(&id->rb_node, parent, p); 221 rb_insert_color(&id->rb_node, root); 222 } 223 return id; 224 } 225 226 static char *get_id(const char *prefix_end) 227 { 228 /* 229 * __BTF_ID__func__vfs_truncate__0 230 * prefix_end = ^ 231 * pos = ^ 232 */ 233 int len = strlen(prefix_end); 234 int pos = sizeof("__") - 1; 235 char *p, *id; 236 237 if (pos >= len) 238 return NULL; 239 240 id = strdup(prefix_end + pos); 241 if (id) { 242 /* 243 * __BTF_ID__func__vfs_truncate__0 244 * id = ^ 245 * 246 * cut the unique id part 247 */ 248 p = strrchr(id, '_'); 249 p--; 250 if (*p != '_') { 251 free(id); 252 return NULL; 253 } 254 *p = '\0'; 255 } 256 return id; 257 } 258 259 static struct btf_id *add_set(struct object *obj, char *name, bool is_set8) 260 { 261 /* 262 * __BTF_ID__set__name 263 * name = ^ 264 * id = ^ 265 */ 266 char *id = name + (is_set8 ? sizeof(BTF_SET8 "__") : sizeof(BTF_SET "__")) - 1; 267 int len = strlen(name); 268 269 if (id >= name + len) { 270 pr_err("FAILED to parse set name: %s\n", name); 271 return NULL; 272 } 273 274 return btf_id__add(&obj->sets, id, true); 275 } 276 277 static struct btf_id *add_symbol(struct rb_root *root, char *name, size_t size) 278 { 279 char *id; 280 281 id = get_id(name + size); 282 if (!id) { 283 pr_err("FAILED to parse symbol name: %s\n", name); 284 return NULL; 285 } 286 287 return btf_id__add(root, id, false); 288 } 289 290 /* Older libelf.h and glibc elf.h might not yet define the ELF compression types. */ 291 #ifndef SHF_COMPRESSED 292 #define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */ 293 #endif 294 295 /* 296 * The data of compressed section should be aligned to 4 297 * (for 32bit) or 8 (for 64 bit) bytes. The binutils ld 298 * sets sh_addralign to 1, which makes libelf fail with 299 * misaligned section error during the update: 300 * FAILED elf_update(WRITE): invalid section alignment 301 * 302 * While waiting for ld fix, we fix the compressed sections 303 * sh_addralign value manualy. 304 */ 305 static int compressed_section_fix(Elf *elf, Elf_Scn *scn, GElf_Shdr *sh) 306 { 307 int expected = gelf_getclass(elf) == ELFCLASS32 ? 4 : 8; 308 309 if (!(sh->sh_flags & SHF_COMPRESSED)) 310 return 0; 311 312 if (sh->sh_addralign == expected) 313 return 0; 314 315 pr_debug2(" - fixing wrong alignment sh_addralign %u, expected %u\n", 316 sh->sh_addralign, expected); 317 318 sh->sh_addralign = expected; 319 320 if (gelf_update_shdr(scn, sh) == 0) { 321 pr_err("FAILED cannot update section header: %s\n", 322 elf_errmsg(-1)); 323 return -1; 324 } 325 return 0; 326 } 327 328 static int elf_collect(struct object *obj) 329 { 330 Elf_Scn *scn = NULL; 331 size_t shdrstrndx; 332 GElf_Ehdr ehdr; 333 int idx = 0; 334 Elf *elf; 335 int fd; 336 337 fd = open(obj->path, O_RDWR, 0666); 338 if (fd == -1) { 339 pr_err("FAILED cannot open %s: %s\n", 340 obj->path, strerror(errno)); 341 return -1; 342 } 343 344 elf_version(EV_CURRENT); 345 346 elf = elf_begin(fd, ELF_C_RDWR_MMAP, NULL); 347 if (!elf) { 348 close(fd); 349 pr_err("FAILED cannot create ELF descriptor: %s\n", 350 elf_errmsg(-1)); 351 return -1; 352 } 353 354 obj->efile.fd = fd; 355 obj->efile.elf = elf; 356 357 elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT); 358 359 if (elf_getshdrstrndx(elf, &shdrstrndx) != 0) { 360 pr_err("FAILED cannot get shdr str ndx\n"); 361 return -1; 362 } 363 364 if (gelf_getehdr(obj->efile.elf, &ehdr) == NULL) { 365 pr_err("FAILED cannot get ELF header: %s\n", 366 elf_errmsg(-1)); 367 return -1; 368 } 369 obj->efile.encoding = ehdr.e_ident[EI_DATA]; 370 371 /* 372 * Scan all the elf sections and look for save data 373 * from .BTF_ids section and symbols. 374 */ 375 while ((scn = elf_nextscn(elf, scn)) != NULL) { 376 Elf_Data *data; 377 GElf_Shdr sh; 378 char *name; 379 380 idx++; 381 if (gelf_getshdr(scn, &sh) != &sh) { 382 pr_err("FAILED get section(%d) header\n", idx); 383 return -1; 384 } 385 386 name = elf_strptr(elf, shdrstrndx, sh.sh_name); 387 if (!name) { 388 pr_err("FAILED get section(%d) name\n", idx); 389 return -1; 390 } 391 392 data = elf_getdata(scn, 0); 393 if (!data) { 394 pr_err("FAILED to get section(%d) data from %s\n", 395 idx, name); 396 return -1; 397 } 398 399 pr_debug2("section(%d) %s, size %ld, link %d, flags %lx, type=%d\n", 400 idx, name, (unsigned long) data->d_size, 401 (int) sh.sh_link, (unsigned long) sh.sh_flags, 402 (int) sh.sh_type); 403 404 if (sh.sh_type == SHT_SYMTAB) { 405 obj->efile.symbols = data; 406 obj->efile.symbols_shndx = idx; 407 obj->efile.strtabidx = sh.sh_link; 408 } else if (!strcmp(name, BTF_IDS_SECTION)) { 409 obj->efile.idlist = data; 410 obj->efile.idlist_shndx = idx; 411 obj->efile.idlist_addr = sh.sh_addr; 412 } else if (!strcmp(name, BTF_BASE_ELF_SEC)) { 413 /* If a .BTF.base section is found, do not resolve 414 * BTF ids relative to vmlinux; resolve relative 415 * to the .BTF.base section instead. btf__parse_split() 416 * will take care of this once the base BTF it is 417 * passed is NULL. 418 */ 419 obj->base_btf_path = NULL; 420 } 421 422 if (compressed_section_fix(elf, scn, &sh)) 423 return -1; 424 } 425 426 return 0; 427 } 428 429 static int symbols_collect(struct object *obj) 430 { 431 Elf_Scn *scn = NULL; 432 int n, i; 433 GElf_Shdr sh; 434 char *name; 435 436 scn = elf_getscn(obj->efile.elf, obj->efile.symbols_shndx); 437 if (!scn) 438 return -1; 439 440 if (gelf_getshdr(scn, &sh) != &sh) 441 return -1; 442 443 n = sh.sh_size / sh.sh_entsize; 444 445 /* 446 * Scan symbols and look for the ones starting with 447 * __BTF_ID__* over .BTF_ids section. 448 */ 449 for (i = 0; i < n; i++) { 450 char *prefix; 451 struct btf_id *id; 452 GElf_Sym sym; 453 454 if (!gelf_getsym(obj->efile.symbols, i, &sym)) 455 return -1; 456 457 if (sym.st_shndx != obj->efile.idlist_shndx) 458 continue; 459 460 name = elf_strptr(obj->efile.elf, obj->efile.strtabidx, 461 sym.st_name); 462 463 if (!is_btf_id(name)) 464 continue; 465 466 /* 467 * __BTF_ID__TYPE__vfs_truncate__0 468 * prefix = ^ 469 */ 470 prefix = name + sizeof(BTF_ID_PREFIX) - 1; 471 472 /* struct */ 473 if (!strncmp(prefix, BTF_STRUCT, sizeof(BTF_STRUCT) - 1)) { 474 obj->nr_structs++; 475 id = add_symbol(&obj->structs, prefix, sizeof(BTF_STRUCT) - 1); 476 /* union */ 477 } else if (!strncmp(prefix, BTF_UNION, sizeof(BTF_UNION) - 1)) { 478 obj->nr_unions++; 479 id = add_symbol(&obj->unions, prefix, sizeof(BTF_UNION) - 1); 480 /* typedef */ 481 } else if (!strncmp(prefix, BTF_TYPEDEF, sizeof(BTF_TYPEDEF) - 1)) { 482 obj->nr_typedefs++; 483 id = add_symbol(&obj->typedefs, prefix, sizeof(BTF_TYPEDEF) - 1); 484 /* func */ 485 } else if (!strncmp(prefix, BTF_FUNC, sizeof(BTF_FUNC) - 1)) { 486 obj->nr_funcs++; 487 id = add_symbol(&obj->funcs, prefix, sizeof(BTF_FUNC) - 1); 488 /* set8 */ 489 } else if (!strncmp(prefix, BTF_SET8, sizeof(BTF_SET8) - 1)) { 490 id = add_set(obj, prefix, true); 491 /* 492 * SET8 objects store list's count, which is encoded 493 * in symbol's size, together with 'cnt' field hence 494 * that - 1. 495 */ 496 if (id) { 497 id->cnt = sym.st_size / sizeof(uint64_t) - 1; 498 id->is_set8 = true; 499 } 500 /* set */ 501 } else if (!strncmp(prefix, BTF_SET, sizeof(BTF_SET) - 1)) { 502 id = add_set(obj, prefix, false); 503 /* 504 * SET objects store list's count, which is encoded 505 * in symbol's size, together with 'cnt' field hence 506 * that - 1. 507 */ 508 if (id) { 509 id->cnt = sym.st_size / sizeof(int) - 1; 510 id->is_set = true; 511 } 512 } else { 513 pr_err("FAILED unsupported prefix %s\n", prefix); 514 return -1; 515 } 516 517 if (!id) 518 return -ENOMEM; 519 520 if (id->addr_cnt >= ADDR_CNT) { 521 pr_err("FAILED symbol %s crossed the number of allowed lists\n", 522 id->name); 523 return -1; 524 } 525 id->addr[id->addr_cnt++] = sym.st_value; 526 } 527 528 return 0; 529 } 530 531 static int symbols_resolve(struct object *obj) 532 { 533 int nr_typedefs = obj->nr_typedefs; 534 int nr_structs = obj->nr_structs; 535 int nr_unions = obj->nr_unions; 536 int nr_funcs = obj->nr_funcs; 537 struct btf *base_btf = NULL; 538 int err, type_id; 539 struct btf *btf; 540 __u32 nr_types; 541 542 if (obj->base_btf_path) { 543 base_btf = btf__parse(obj->base_btf_path, NULL); 544 err = libbpf_get_error(base_btf); 545 if (err) { 546 pr_err("FAILED: load base BTF from %s: %s\n", 547 obj->base_btf_path, strerror(-err)); 548 return -1; 549 } 550 } 551 552 btf = btf__parse_split(obj->btf ?: obj->path, base_btf); 553 err = libbpf_get_error(btf); 554 if (err) { 555 pr_err("FAILED: load BTF from %s: %s\n", 556 obj->btf ?: obj->path, strerror(-err)); 557 goto out; 558 } 559 560 err = -1; 561 nr_types = btf__type_cnt(btf); 562 563 /* 564 * Iterate all the BTF types and search for collected symbol IDs. 565 */ 566 for (type_id = 1; type_id < nr_types; type_id++) { 567 const struct btf_type *type; 568 struct rb_root *root; 569 struct btf_id *id; 570 const char *str; 571 int *nr; 572 573 type = btf__type_by_id(btf, type_id); 574 if (!type) { 575 pr_err("FAILED: malformed BTF, can't resolve type for ID %d\n", 576 type_id); 577 goto out; 578 } 579 580 if (btf_is_func(type) && nr_funcs) { 581 nr = &nr_funcs; 582 root = &obj->funcs; 583 } else if (btf_is_struct(type) && nr_structs) { 584 nr = &nr_structs; 585 root = &obj->structs; 586 } else if (btf_is_union(type) && nr_unions) { 587 nr = &nr_unions; 588 root = &obj->unions; 589 } else if (btf_is_typedef(type) && nr_typedefs) { 590 nr = &nr_typedefs; 591 root = &obj->typedefs; 592 } else 593 continue; 594 595 str = btf__name_by_offset(btf, type->name_off); 596 if (!str) { 597 pr_err("FAILED: malformed BTF, can't resolve name for ID %d\n", 598 type_id); 599 goto out; 600 } 601 602 id = btf_id__find(root, str); 603 if (id) { 604 if (id->id) { 605 pr_info("WARN: multiple IDs found for '%s': %d, %d - using %d\n", 606 str, id->id, type_id, id->id); 607 } else { 608 id->id = type_id; 609 (*nr)--; 610 } 611 } 612 } 613 614 err = 0; 615 out: 616 btf__free(base_btf); 617 btf__free(btf); 618 return err; 619 } 620 621 static int id_patch(struct object *obj, struct btf_id *id) 622 { 623 Elf_Data *data = obj->efile.idlist; 624 int *ptr = data->d_buf; 625 int i; 626 627 /* For set, set8, id->id may be 0 */ 628 if (!id->id && !id->is_set && !id->is_set8) 629 pr_err("WARN: resolve_btfids: unresolved symbol %s\n", id->name); 630 631 for (i = 0; i < id->addr_cnt; i++) { 632 unsigned long addr = id->addr[i]; 633 unsigned long idx = addr - obj->efile.idlist_addr; 634 635 pr_debug("patching addr %5lu: ID %7d [%s]\n", 636 idx, id->id, id->name); 637 638 if (idx >= data->d_size) { 639 pr_err("FAILED patching index %lu out of bounds %lu\n", 640 idx, data->d_size); 641 return -1; 642 } 643 644 idx = idx / sizeof(int); 645 ptr[idx] = id->id; 646 } 647 648 return 0; 649 } 650 651 static int __symbols_patch(struct object *obj, struct rb_root *root) 652 { 653 struct rb_node *next; 654 struct btf_id *id; 655 656 next = rb_first(root); 657 while (next) { 658 id = rb_entry(next, struct btf_id, rb_node); 659 660 if (id_patch(obj, id)) 661 return -1; 662 663 next = rb_next(next); 664 } 665 return 0; 666 } 667 668 static int cmp_id(const void *pa, const void *pb) 669 { 670 const int *a = pa, *b = pb; 671 672 return *a - *b; 673 } 674 675 static int sets_patch(struct object *obj) 676 { 677 Elf_Data *data = obj->efile.idlist; 678 struct rb_node *next; 679 680 next = rb_first(&obj->sets); 681 while (next) { 682 struct btf_id_set8 *set8; 683 struct btf_id_set *set; 684 unsigned long addr, off; 685 struct btf_id *id; 686 687 id = rb_entry(next, struct btf_id, rb_node); 688 addr = id->addr[0]; 689 off = addr - obj->efile.idlist_addr; 690 691 /* sets are unique */ 692 if (id->addr_cnt != 1) { 693 pr_err("FAILED malformed data for set '%s'\n", 694 id->name); 695 return -1; 696 } 697 698 if (id->is_set) { 699 set = data->d_buf + off; 700 qsort(set->ids, set->cnt, sizeof(set->ids[0]), cmp_id); 701 } else { 702 set8 = data->d_buf + off; 703 /* 704 * Make sure id is at the beginning of the pairs 705 * struct, otherwise the below qsort would not work. 706 */ 707 BUILD_BUG_ON((u32 *)set8->pairs != &set8->pairs[0].id); 708 qsort(set8->pairs, set8->cnt, sizeof(set8->pairs[0]), cmp_id); 709 710 /* 711 * When ELF endianness does not match endianness of the 712 * host, libelf will do the translation when updating 713 * the ELF. This, however, corrupts SET8 flags which are 714 * already in the target endianness. So, let's bswap 715 * them to the host endianness and libelf will then 716 * correctly translate everything. 717 */ 718 if (obj->efile.encoding != ELFDATANATIVE) { 719 int i; 720 721 set8->flags = bswap_32(set8->flags); 722 for (i = 0; i < set8->cnt; i++) { 723 set8->pairs[i].flags = 724 bswap_32(set8->pairs[i].flags); 725 } 726 } 727 } 728 729 pr_debug("sorting addr %5lu: cnt %6d [%s]\n", 730 off, id->is_set ? set->cnt : set8->cnt, id->name); 731 732 next = rb_next(next); 733 } 734 return 0; 735 } 736 737 static int symbols_patch(struct object *obj) 738 { 739 off_t err; 740 741 if (__symbols_patch(obj, &obj->structs) || 742 __symbols_patch(obj, &obj->unions) || 743 __symbols_patch(obj, &obj->typedefs) || 744 __symbols_patch(obj, &obj->funcs) || 745 __symbols_patch(obj, &obj->sets)) 746 return -1; 747 748 if (sets_patch(obj)) 749 return -1; 750 751 /* Set type to ensure endian translation occurs. */ 752 obj->efile.idlist->d_type = ELF_T_WORD; 753 754 elf_flagdata(obj->efile.idlist, ELF_C_SET, ELF_F_DIRTY); 755 756 err = elf_update(obj->efile.elf, ELF_C_WRITE); 757 if (err < 0) { 758 pr_err("FAILED elf_update(WRITE): %s\n", 759 elf_errmsg(-1)); 760 } 761 762 pr_debug("update %s for %s\n", 763 err >= 0 ? "ok" : "failed", obj->path); 764 return err < 0 ? -1 : 0; 765 } 766 767 static const char * const resolve_btfids_usage[] = { 768 "resolve_btfids [<options>] <ELF object>", 769 NULL 770 }; 771 772 int main(int argc, const char **argv) 773 { 774 struct object obj = { 775 .efile = { 776 .idlist_shndx = -1, 777 .symbols_shndx = -1, 778 }, 779 .structs = RB_ROOT, 780 .unions = RB_ROOT, 781 .typedefs = RB_ROOT, 782 .funcs = RB_ROOT, 783 .sets = RB_ROOT, 784 }; 785 struct option btfid_options[] = { 786 OPT_INCR('v', "verbose", &verbose, 787 "be more verbose (show errors, etc)"), 788 OPT_STRING(0, "btf", &obj.btf, "BTF data", 789 "BTF data"), 790 OPT_STRING('b', "btf_base", &obj.base_btf_path, "file", 791 "path of file providing base BTF"), 792 OPT_END() 793 }; 794 int err = -1; 795 796 argc = parse_options(argc, argv, btfid_options, resolve_btfids_usage, 797 PARSE_OPT_STOP_AT_NON_OPTION); 798 if (argc != 1) 799 usage_with_options(resolve_btfids_usage, btfid_options); 800 801 obj.path = argv[0]; 802 803 if (elf_collect(&obj)) 804 goto out; 805 806 /* 807 * We did not find .BTF_ids section or symbols section, 808 * nothing to do.. 809 */ 810 if (obj.efile.idlist_shndx == -1 || 811 obj.efile.symbols_shndx == -1) { 812 pr_debug("Cannot find .BTF_ids or symbols sections, nothing to do\n"); 813 err = 0; 814 goto out; 815 } 816 817 if (symbols_collect(&obj)) 818 goto out; 819 820 if (symbols_resolve(&obj)) 821 goto out; 822 823 if (symbols_patch(&obj)) 824 goto out; 825 826 err = 0; 827 out: 828 if (obj.efile.elf) { 829 elf_end(obj.efile.elf); 830 close(obj.efile.fd); 831 } 832 return err; 833 } 834
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.