1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * elf.c - ELF access library 4 * 5 * Adapted from kpatch (https://github.com/dynup/kpatch): 6 * Copyright (C) 2013-2015 Josh Poimboeuf <jpoimboe@redhat.com> 7 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com> 8 */ 9 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <fcntl.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <unistd.h> 17 #include <errno.h> 18 #include "builtin.h" 19 20 #include "elf.h" 21 #include "warn.h" 22 23 #define MAX_NAME_LEN 128 24 25 static inline u32 str_hash(const char *str) 26 { 27 return jhash(str, strlen(str), 0); 28 } 29 30 static inline int elf_hash_bits(void) 31 { 32 return vmlinux ? ELF_HASH_BITS : 16; 33 } 34 35 #define elf_hash_add(hashtable, node, key) \ 36 hlist_add_head(node, &hashtable[hash_min(key, elf_hash_bits())]) 37 38 static void elf_hash_init(struct hlist_head *table) 39 { 40 __hash_init(table, 1U << elf_hash_bits()); 41 } 42 43 #define elf_hash_for_each_possible(name, obj, member, key) \ 44 hlist_for_each_entry(obj, &name[hash_min(key, elf_hash_bits())], member) 45 46 static void rb_add(struct rb_root *tree, struct rb_node *node, 47 int (*cmp)(struct rb_node *, const struct rb_node *)) 48 { 49 struct rb_node **link = &tree->rb_node; 50 struct rb_node *parent = NULL; 51 52 while (*link) { 53 parent = *link; 54 if (cmp(node, parent) < 0) 55 link = &parent->rb_left; 56 else 57 link = &parent->rb_right; 58 } 59 60 rb_link_node(node, parent, link); 61 rb_insert_color(node, tree); 62 } 63 64 static struct rb_node *rb_find_first(const struct rb_root *tree, const void *key, 65 int (*cmp)(const void *key, const struct rb_node *)) 66 { 67 struct rb_node *node = tree->rb_node; 68 struct rb_node *match = NULL; 69 70 while (node) { 71 int c = cmp(key, node); 72 if (c <= 0) { 73 if (!c) 74 match = node; 75 node = node->rb_left; 76 } else if (c > 0) { 77 node = node->rb_right; 78 } 79 } 80 81 return match; 82 } 83 84 static struct rb_node *rb_next_match(struct rb_node *node, const void *key, 85 int (*cmp)(const void *key, const struct rb_node *)) 86 { 87 node = rb_next(node); 88 if (node && cmp(key, node)) 89 node = NULL; 90 return node; 91 } 92 93 #define rb_for_each(tree, node, key, cmp) \ 94 for ((node) = rb_find_first((tree), (key), (cmp)); \ 95 (node); (node) = rb_next_match((node), (key), (cmp))) 96 97 static int symbol_to_offset(struct rb_node *a, const struct rb_node *b) 98 { 99 struct symbol *sa = rb_entry(a, struct symbol, node); 100 struct symbol *sb = rb_entry(b, struct symbol, node); 101 102 if (sa->offset < sb->offset) 103 return -1; 104 if (sa->offset > sb->offset) 105 return 1; 106 107 if (sa->len < sb->len) 108 return -1; 109 if (sa->len > sb->len) 110 return 1; 111 112 sa->alias = sb; 113 114 return 0; 115 } 116 117 static int symbol_by_offset(const void *key, const struct rb_node *node) 118 { 119 const struct symbol *s = rb_entry(node, struct symbol, node); 120 const unsigned long *o = key; 121 122 if (*o < s->offset) 123 return -1; 124 if (*o >= s->offset + s->len) 125 return 1; 126 127 return 0; 128 } 129 130 struct section *find_section_by_name(const struct elf *elf, const char *name) 131 { 132 struct section *sec; 133 134 elf_hash_for_each_possible(elf->section_name_hash, sec, name_hash, str_hash(name)) 135 if (!strcmp(sec->name, name)) 136 return sec; 137 138 return NULL; 139 } 140 141 static struct section *find_section_by_index(struct elf *elf, 142 unsigned int idx) 143 { 144 struct section *sec; 145 146 elf_hash_for_each_possible(elf->section_hash, sec, hash, idx) 147 if (sec->idx == idx) 148 return sec; 149 150 return NULL; 151 } 152 153 static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx) 154 { 155 struct symbol *sym; 156 157 elf_hash_for_each_possible(elf->symbol_hash, sym, hash, idx) 158 if (sym->idx == idx) 159 return sym; 160 161 return NULL; 162 } 163 164 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset) 165 { 166 struct rb_node *node; 167 168 rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) { 169 struct symbol *s = rb_entry(node, struct symbol, node); 170 171 if (s->offset == offset && s->type != STT_SECTION) 172 return s; 173 } 174 175 return NULL; 176 } 177 178 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset) 179 { 180 struct rb_node *node; 181 182 rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) { 183 struct symbol *s = rb_entry(node, struct symbol, node); 184 185 if (s->offset == offset && s->type == STT_FUNC) 186 return s; 187 } 188 189 return NULL; 190 } 191 192 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset) 193 { 194 struct rb_node *node; 195 196 rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) { 197 struct symbol *s = rb_entry(node, struct symbol, node); 198 199 if (s->type != STT_SECTION) 200 return s; 201 } 202 203 return NULL; 204 } 205 206 struct symbol *find_func_containing(struct section *sec, unsigned long offset) 207 { 208 struct rb_node *node; 209 210 rb_for_each(&sec->symbol_tree, node, &offset, symbol_by_offset) { 211 struct symbol *s = rb_entry(node, struct symbol, node); 212 213 if (s->type == STT_FUNC) 214 return s; 215 } 216 217 return NULL; 218 } 219 220 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name) 221 { 222 struct symbol *sym; 223 224 elf_hash_for_each_possible(elf->symbol_name_hash, sym, name_hash, str_hash(name)) 225 if (!strcmp(sym->name, name)) 226 return sym; 227 228 return NULL; 229 } 230 231 struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec, 232 unsigned long offset, unsigned int len) 233 { 234 struct rela *rela, *r = NULL; 235 unsigned long o; 236 237 if (!sec->rela) 238 return NULL; 239 240 sec = sec->rela; 241 242 for_offset_range(o, offset, offset + len) { 243 elf_hash_for_each_possible(elf->rela_hash, rela, hash, 244 sec_offset_hash(sec, o)) { 245 if (rela->sec != sec) 246 continue; 247 248 if (rela->offset >= offset && rela->offset < offset + len) { 249 if (!r || rela->offset < r->offset) 250 r = rela; 251 } 252 } 253 if (r) 254 return r; 255 } 256 257 return NULL; 258 } 259 260 struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsigned long offset) 261 { 262 return find_rela_by_dest_range(elf, sec, offset, 1); 263 } 264 265 static int read_sections(struct elf *elf) 266 { 267 Elf_Scn *s = NULL; 268 struct section *sec; 269 size_t shstrndx, sections_nr; 270 int i; 271 272 if (elf_getshdrnum(elf->elf, §ions_nr)) { 273 WARN_ELF("elf_getshdrnum"); 274 return -1; 275 } 276 277 if (elf_getshdrstrndx(elf->elf, &shstrndx)) { 278 WARN_ELF("elf_getshdrstrndx"); 279 return -1; 280 } 281 282 for (i = 0; i < sections_nr; i++) { 283 sec = malloc(sizeof(*sec)); 284 if (!sec) { 285 perror("malloc"); 286 return -1; 287 } 288 memset(sec, 0, sizeof(*sec)); 289 290 INIT_LIST_HEAD(&sec->symbol_list); 291 INIT_LIST_HEAD(&sec->rela_list); 292 293 s = elf_getscn(elf->elf, i); 294 if (!s) { 295 WARN_ELF("elf_getscn"); 296 return -1; 297 } 298 299 sec->idx = elf_ndxscn(s); 300 301 if (!gelf_getshdr(s, &sec->sh)) { 302 WARN_ELF("gelf_getshdr"); 303 return -1; 304 } 305 306 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name); 307 if (!sec->name) { 308 WARN_ELF("elf_strptr"); 309 return -1; 310 } 311 312 if (sec->sh.sh_size != 0) { 313 sec->data = elf_getdata(s, NULL); 314 if (!sec->data) { 315 WARN_ELF("elf_getdata"); 316 return -1; 317 } 318 if (sec->data->d_off != 0 || 319 sec->data->d_size != sec->sh.sh_size) { 320 WARN("unexpected data attributes for %s", 321 sec->name); 322 return -1; 323 } 324 } 325 sec->len = sec->sh.sh_size; 326 327 list_add_tail(&sec->list, &elf->sections); 328 elf_hash_add(elf->section_hash, &sec->hash, sec->idx); 329 elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name)); 330 } 331 332 if (stats) 333 printf("nr_sections: %lu\n", (unsigned long)sections_nr); 334 335 /* sanity check, one more call to elf_nextscn() should return NULL */ 336 if (elf_nextscn(elf->elf, s)) { 337 WARN("section entry mismatch"); 338 return -1; 339 } 340 341 return 0; 342 } 343 344 static int read_symbols(struct elf *elf) 345 { 346 struct section *symtab, *symtab_shndx, *sec; 347 struct symbol *sym, *pfunc; 348 struct list_head *entry; 349 struct rb_node *pnode; 350 int symbols_nr, i; 351 char *coldstr; 352 Elf_Data *shndx_data = NULL; 353 Elf32_Word shndx; 354 355 symtab = find_section_by_name(elf, ".symtab"); 356 if (!symtab) { 357 WARN("missing symbol table"); 358 return -1; 359 } 360 361 symtab_shndx = find_section_by_name(elf, ".symtab_shndx"); 362 if (symtab_shndx) 363 shndx_data = symtab_shndx->data; 364 365 symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize; 366 367 for (i = 0; i < symbols_nr; i++) { 368 sym = malloc(sizeof(*sym)); 369 if (!sym) { 370 perror("malloc"); 371 return -1; 372 } 373 memset(sym, 0, sizeof(*sym)); 374 sym->alias = sym; 375 376 sym->idx = i; 377 378 if (!gelf_getsymshndx(symtab->data, shndx_data, i, &sym->sym, 379 &shndx)) { 380 WARN_ELF("gelf_getsymshndx"); 381 goto err; 382 } 383 384 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link, 385 sym->sym.st_name); 386 if (!sym->name) { 387 WARN_ELF("elf_strptr"); 388 goto err; 389 } 390 391 sym->type = GELF_ST_TYPE(sym->sym.st_info); 392 sym->bind = GELF_ST_BIND(sym->sym.st_info); 393 394 if ((sym->sym.st_shndx > SHN_UNDEF && 395 sym->sym.st_shndx < SHN_LORESERVE) || 396 (shndx_data && sym->sym.st_shndx == SHN_XINDEX)) { 397 if (sym->sym.st_shndx != SHN_XINDEX) 398 shndx = sym->sym.st_shndx; 399 400 sym->sec = find_section_by_index(elf, shndx); 401 if (!sym->sec) { 402 WARN("couldn't find section for symbol %s", 403 sym->name); 404 goto err; 405 } 406 if (sym->type == STT_SECTION) { 407 sym->name = sym->sec->name; 408 sym->sec->sym = sym; 409 } 410 } else 411 sym->sec = find_section_by_index(elf, 0); 412 413 sym->offset = sym->sym.st_value; 414 sym->len = sym->sym.st_size; 415 416 rb_add(&sym->sec->symbol_tree, &sym->node, symbol_to_offset); 417 pnode = rb_prev(&sym->node); 418 if (pnode) 419 entry = &rb_entry(pnode, struct symbol, node)->list; 420 else 421 entry = &sym->sec->symbol_list; 422 list_add(&sym->list, entry); 423 elf_hash_add(elf->symbol_hash, &sym->hash, sym->idx); 424 elf_hash_add(elf->symbol_name_hash, &sym->name_hash, str_hash(sym->name)); 425 } 426 427 if (stats) 428 printf("nr_symbols: %lu\n", (unsigned long)symbols_nr); 429 430 /* Create parent/child links for any cold subfunctions */ 431 list_for_each_entry(sec, &elf->sections, list) { 432 list_for_each_entry(sym, &sec->symbol_list, list) { 433 char pname[MAX_NAME_LEN + 1]; 434 size_t pnamelen; 435 if (sym->type != STT_FUNC) 436 continue; 437 sym->pfunc = sym->cfunc = sym; 438 coldstr = strstr(sym->name, ".cold"); 439 if (!coldstr) 440 continue; 441 442 pnamelen = coldstr - sym->name; 443 if (pnamelen > MAX_NAME_LEN) { 444 WARN("%s(): parent function name exceeds maximum length of %d characters", 445 sym->name, MAX_NAME_LEN); 446 return -1; 447 } 448 449 strncpy(pname, sym->name, pnamelen); 450 pname[pnamelen] = '\0'; 451 pfunc = find_symbol_by_name(elf, pname); 452 453 if (!pfunc) { 454 WARN("%s(): can't find parent function", 455 sym->name); 456 return -1; 457 } 458 459 sym->pfunc = pfunc; 460 pfunc->cfunc = sym; 461 462 /* 463 * Unfortunately, -fnoreorder-functions puts the child 464 * inside the parent. Remove the overlap so we can 465 * have sane assumptions. 466 * 467 * Note that pfunc->len now no longer matches 468 * pfunc->sym.st_size. 469 */ 470 if (sym->sec == pfunc->sec && 471 sym->offset >= pfunc->offset && 472 sym->offset + sym->len == pfunc->offset + pfunc->len) { 473 pfunc->len -= sym->len; 474 } 475 } 476 } 477 478 return 0; 479 480 err: 481 free(sym); 482 return -1; 483 } 484 485 void elf_add_rela(struct elf *elf, struct rela *rela) 486 { 487 struct section *sec = rela->sec; 488 489 list_add_tail(&rela->list, &sec->rela_list); 490 elf_hash_add(elf->rela_hash, &rela->hash, rela_hash(rela)); 491 } 492 493 static int read_relas(struct elf *elf) 494 { 495 struct section *sec; 496 struct rela *rela; 497 int i; 498 unsigned int symndx; 499 unsigned long nr_rela, max_rela = 0, tot_rela = 0; 500 501 list_for_each_entry(sec, &elf->sections, list) { 502 if (sec->sh.sh_type != SHT_RELA) 503 continue; 504 505 sec->base = find_section_by_name(elf, sec->name + 5); 506 if (!sec->base) { 507 WARN("can't find base section for rela section %s", 508 sec->name); 509 return -1; 510 } 511 512 sec->base->rela = sec; 513 514 nr_rela = 0; 515 for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) { 516 rela = malloc(sizeof(*rela)); 517 if (!rela) { 518 perror("malloc"); 519 return -1; 520 } 521 memset(rela, 0, sizeof(*rela)); 522 523 if (!gelf_getrela(sec->data, i, &rela->rela)) { 524 WARN_ELF("gelf_getrela"); 525 return -1; 526 } 527 528 rela->type = GELF_R_TYPE(rela->rela.r_info); 529 rela->addend = rela->rela.r_addend; 530 rela->offset = rela->rela.r_offset; 531 symndx = GELF_R_SYM(rela->rela.r_info); 532 rela->sym = find_symbol_by_index(elf, symndx); 533 rela->sec = sec; 534 if (!rela->sym) { 535 WARN("can't find rela entry symbol %d for %s", 536 symndx, sec->name); 537 return -1; 538 } 539 540 elf_add_rela(elf, rela); 541 nr_rela++; 542 } 543 max_rela = max(max_rela, nr_rela); 544 tot_rela += nr_rela; 545 } 546 547 if (stats) { 548 printf("max_rela: %lu\n", max_rela); 549 printf("tot_rela: %lu\n", tot_rela); 550 } 551 552 return 0; 553 } 554 555 struct elf *elf_open_read(const char *name, int flags) 556 { 557 struct elf *elf; 558 Elf_Cmd cmd; 559 560 elf_version(EV_CURRENT); 561 562 elf = malloc(sizeof(*elf)); 563 if (!elf) { 564 perror("malloc"); 565 return NULL; 566 } 567 memset(elf, 0, offsetof(struct elf, sections)); 568 569 INIT_LIST_HEAD(&elf->sections); 570 571 elf_hash_init(elf->symbol_hash); 572 elf_hash_init(elf->symbol_name_hash); 573 elf_hash_init(elf->section_hash); 574 elf_hash_init(elf->section_name_hash); 575 elf_hash_init(elf->rela_hash); 576 577 elf->fd = open(name, flags); 578 if (elf->fd == -1) { 579 fprintf(stderr, "objtool: Can't open '%s': %s\n", 580 name, strerror(errno)); 581 goto err; 582 } 583 584 if ((flags & O_ACCMODE) == O_RDONLY) 585 cmd = ELF_C_READ_MMAP; 586 else if ((flags & O_ACCMODE) == O_RDWR) 587 cmd = ELF_C_RDWR; 588 else /* O_WRONLY */ 589 cmd = ELF_C_WRITE; 590 591 elf->elf = elf_begin(elf->fd, cmd, NULL); 592 if (!elf->elf) { 593 WARN_ELF("elf_begin"); 594 goto err; 595 } 596 597 if (!gelf_getehdr(elf->elf, &elf->ehdr)) { 598 WARN_ELF("gelf_getehdr"); 599 goto err; 600 } 601 602 if (read_sections(elf)) 603 goto err; 604 605 if (read_symbols(elf)) 606 goto err; 607 608 if (read_relas(elf)) 609 goto err; 610 611 return elf; 612 613 err: 614 elf_close(elf); 615 return NULL; 616 } 617 618 struct section *elf_create_section(struct elf *elf, const char *name, 619 size_t entsize, int nr) 620 { 621 struct section *sec, *shstrtab; 622 size_t size = entsize * nr; 623 Elf_Scn *s; 624 Elf_Data *data; 625 626 sec = malloc(sizeof(*sec)); 627 if (!sec) { 628 perror("malloc"); 629 return NULL; 630 } 631 memset(sec, 0, sizeof(*sec)); 632 633 INIT_LIST_HEAD(&sec->symbol_list); 634 INIT_LIST_HEAD(&sec->rela_list); 635 636 s = elf_newscn(elf->elf); 637 if (!s) { 638 WARN_ELF("elf_newscn"); 639 return NULL; 640 } 641 642 sec->name = strdup(name); 643 if (!sec->name) { 644 perror("strdup"); 645 return NULL; 646 } 647 648 sec->idx = elf_ndxscn(s); 649 sec->len = size; 650 sec->changed = true; 651 652 sec->data = elf_newdata(s); 653 if (!sec->data) { 654 WARN_ELF("elf_newdata"); 655 return NULL; 656 } 657 658 sec->data->d_size = size; 659 sec->data->d_align = 1; 660 661 if (size) { 662 sec->data->d_buf = malloc(size); 663 if (!sec->data->d_buf) { 664 perror("malloc"); 665 return NULL; 666 } 667 memset(sec->data->d_buf, 0, size); 668 } 669 670 if (!gelf_getshdr(s, &sec->sh)) { 671 WARN_ELF("gelf_getshdr"); 672 return NULL; 673 } 674 675 sec->sh.sh_size = size; 676 sec->sh.sh_entsize = entsize; 677 sec->sh.sh_type = SHT_PROGBITS; 678 sec->sh.sh_addralign = 1; 679 sec->sh.sh_flags = SHF_ALLOC; 680 681 682 /* Add section name to .shstrtab (or .strtab for Clang) */ 683 shstrtab = find_section_by_name(elf, ".shstrtab"); 684 if (!shstrtab) 685 shstrtab = find_section_by_name(elf, ".strtab"); 686 if (!shstrtab) { 687 WARN("can't find .shstrtab or .strtab section"); 688 return NULL; 689 } 690 691 s = elf_getscn(elf->elf, shstrtab->idx); 692 if (!s) { 693 WARN_ELF("elf_getscn"); 694 return NULL; 695 } 696 697 data = elf_newdata(s); 698 if (!data) { 699 WARN_ELF("elf_newdata"); 700 return NULL; 701 } 702 703 data->d_buf = sec->name; 704 data->d_size = strlen(name) + 1; 705 data->d_align = 1; 706 707 sec->sh.sh_name = shstrtab->len; 708 709 shstrtab->len += strlen(name) + 1; 710 shstrtab->changed = true; 711 712 list_add_tail(&sec->list, &elf->sections); 713 elf_hash_add(elf->section_hash, &sec->hash, sec->idx); 714 elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name)); 715 716 return sec; 717 } 718 719 struct section *elf_create_rela_section(struct elf *elf, struct section *base) 720 { 721 char *relaname; 722 struct section *sec; 723 724 relaname = malloc(strlen(base->name) + strlen(".rela") + 1); 725 if (!relaname) { 726 perror("malloc"); 727 return NULL; 728 } 729 strcpy(relaname, ".rela"); 730 strcat(relaname, base->name); 731 732 sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0); 733 free(relaname); 734 if (!sec) 735 return NULL; 736 737 base->rela = sec; 738 sec->base = base; 739 740 sec->sh.sh_type = SHT_RELA; 741 sec->sh.sh_addralign = 8; 742 sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx; 743 sec->sh.sh_info = base->idx; 744 sec->sh.sh_flags = SHF_INFO_LINK; 745 746 return sec; 747 } 748 749 int elf_rebuild_rela_section(struct section *sec) 750 { 751 struct rela *rela; 752 int nr, idx = 0, size; 753 GElf_Rela *relas; 754 755 nr = 0; 756 list_for_each_entry(rela, &sec->rela_list, list) 757 nr++; 758 759 size = nr * sizeof(*relas); 760 relas = malloc(size); 761 if (!relas) { 762 perror("malloc"); 763 return -1; 764 } 765 766 sec->data->d_buf = relas; 767 sec->data->d_size = size; 768 769 sec->sh.sh_size = size; 770 771 idx = 0; 772 list_for_each_entry(rela, &sec->rela_list, list) { 773 relas[idx].r_offset = rela->offset; 774 relas[idx].r_addend = rela->addend; 775 relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type); 776 idx++; 777 } 778 779 return 0; 780 } 781 782 int elf_write(const struct elf *elf) 783 { 784 struct section *sec; 785 Elf_Scn *s; 786 787 /* Update section headers for changed sections: */ 788 list_for_each_entry(sec, &elf->sections, list) { 789 if (sec->changed) { 790 s = elf_getscn(elf->elf, sec->idx); 791 if (!s) { 792 WARN_ELF("elf_getscn"); 793 return -1; 794 } 795 if (!gelf_update_shdr(s, &sec->sh)) { 796 WARN_ELF("gelf_update_shdr"); 797 return -1; 798 } 799 } 800 } 801 802 /* Make sure the new section header entries get updated properly. */ 803 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY); 804 805 /* Write all changes to the file. */ 806 if (elf_update(elf->elf, ELF_C_WRITE) < 0) { 807 WARN_ELF("elf_update"); 808 return -1; 809 } 810 811 return 0; 812 } 813 814 void elf_close(struct elf *elf) 815 { 816 struct section *sec, *tmpsec; 817 struct symbol *sym, *tmpsym; 818 struct rela *rela, *tmprela; 819 820 if (elf->elf) 821 elf_end(elf->elf); 822 823 if (elf->fd > 0) 824 close(elf->fd); 825 826 list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) { 827 list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) { 828 list_del(&sym->list); 829 hash_del(&sym->hash); 830 free(sym); 831 } 832 list_for_each_entry_safe(rela, tmprela, &sec->rela_list, list) { 833 list_del(&rela->list); 834 hash_del(&rela->hash); 835 free(rela); 836 } 837 list_del(&sec->list); 838 free(sec); 839 } 840 841 free(elf); 842 } 843