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 reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, 232 unsigned long offset, unsigned int len) 233 { 234 struct reloc *reloc, *r = NULL; 235 unsigned long o; 236 237 if (!sec->reloc) 238 return NULL; 239 240 sec = sec->reloc; 241 242 for_offset_range(o, offset, offset + len) { 243 elf_hash_for_each_possible(elf->reloc_hash, reloc, hash, 244 sec_offset_hash(sec, o)) { 245 if (reloc->sec != sec) 246 continue; 247 248 if (reloc->offset >= offset && reloc->offset < offset + len) { 249 if (!r || reloc->offset < r->offset) 250 r = reloc; 251 } 252 } 253 if (r) 254 return r; 255 } 256 257 return NULL; 258 } 259 260 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset) 261 { 262 return find_reloc_by_dest_range(elf, sec, offset, 1); 263 } 264 265 void insn_to_reloc_sym_addend(struct section *sec, unsigned long offset, 266 struct reloc *reloc) 267 { 268 if (sec->sym) { 269 reloc->sym = sec->sym; 270 reloc->addend = offset; 271 return; 272 } 273 274 /* 275 * The Clang assembler strips section symbols, so we have to reference 276 * the function symbol instead: 277 */ 278 reloc->sym = find_symbol_containing(sec, offset); 279 if (!reloc->sym) { 280 /* 281 * Hack alert. This happens when we need to reference the NOP 282 * pad insn immediately after the function. 283 */ 284 reloc->sym = find_symbol_containing(sec, offset - 1); 285 } 286 287 if (reloc->sym) 288 reloc->addend = offset - reloc->sym->offset; 289 } 290 291 static int read_sections(struct elf *elf) 292 { 293 Elf_Scn *s = NULL; 294 struct section *sec; 295 size_t shstrndx, sections_nr; 296 int i; 297 298 if (elf_getshdrnum(elf->elf, §ions_nr)) { 299 WARN_ELF("elf_getshdrnum"); 300 return -1; 301 } 302 303 if (elf_getshdrstrndx(elf->elf, &shstrndx)) { 304 WARN_ELF("elf_getshdrstrndx"); 305 return -1; 306 } 307 308 for (i = 0; i < sections_nr; i++) { 309 sec = malloc(sizeof(*sec)); 310 if (!sec) { 311 perror("malloc"); 312 return -1; 313 } 314 memset(sec, 0, sizeof(*sec)); 315 316 INIT_LIST_HEAD(&sec->symbol_list); 317 INIT_LIST_HEAD(&sec->reloc_list); 318 319 s = elf_getscn(elf->elf, i); 320 if (!s) { 321 WARN_ELF("elf_getscn"); 322 return -1; 323 } 324 325 sec->idx = elf_ndxscn(s); 326 327 if (!gelf_getshdr(s, &sec->sh)) { 328 WARN_ELF("gelf_getshdr"); 329 return -1; 330 } 331 332 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name); 333 if (!sec->name) { 334 WARN_ELF("elf_strptr"); 335 return -1; 336 } 337 338 if (sec->sh.sh_size != 0) { 339 sec->data = elf_getdata(s, NULL); 340 if (!sec->data) { 341 WARN_ELF("elf_getdata"); 342 return -1; 343 } 344 if (sec->data->d_off != 0 || 345 sec->data->d_size != sec->sh.sh_size) { 346 WARN("unexpected data attributes for %s", 347 sec->name); 348 return -1; 349 } 350 } 351 sec->len = sec->sh.sh_size; 352 353 list_add_tail(&sec->list, &elf->sections); 354 elf_hash_add(elf->section_hash, &sec->hash, sec->idx); 355 elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name)); 356 } 357 358 if (stats) 359 printf("nr_sections: %lu\n", (unsigned long)sections_nr); 360 361 /* sanity check, one more call to elf_nextscn() should return NULL */ 362 if (elf_nextscn(elf->elf, s)) { 363 WARN("section entry mismatch"); 364 return -1; 365 } 366 367 return 0; 368 } 369 370 static int read_symbols(struct elf *elf) 371 { 372 struct section *symtab, *symtab_shndx, *sec; 373 struct symbol *sym, *pfunc; 374 struct list_head *entry; 375 struct rb_node *pnode; 376 int symbols_nr, i; 377 char *coldstr; 378 Elf_Data *shndx_data = NULL; 379 Elf32_Word shndx; 380 381 symtab = find_section_by_name(elf, ".symtab"); 382 if (!symtab) { 383 WARN("missing symbol table"); 384 return -1; 385 } 386 387 symtab_shndx = find_section_by_name(elf, ".symtab_shndx"); 388 if (symtab_shndx) 389 shndx_data = symtab_shndx->data; 390 391 symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize; 392 393 for (i = 0; i < symbols_nr; i++) { 394 sym = malloc(sizeof(*sym)); 395 if (!sym) { 396 perror("malloc"); 397 return -1; 398 } 399 memset(sym, 0, sizeof(*sym)); 400 sym->alias = sym; 401 402 sym->idx = i; 403 404 if (!gelf_getsymshndx(symtab->data, shndx_data, i, &sym->sym, 405 &shndx)) { 406 WARN_ELF("gelf_getsymshndx"); 407 goto err; 408 } 409 410 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link, 411 sym->sym.st_name); 412 if (!sym->name) { 413 WARN_ELF("elf_strptr"); 414 goto err; 415 } 416 417 sym->type = GELF_ST_TYPE(sym->sym.st_info); 418 sym->bind = GELF_ST_BIND(sym->sym.st_info); 419 420 if ((sym->sym.st_shndx > SHN_UNDEF && 421 sym->sym.st_shndx < SHN_LORESERVE) || 422 (shndx_data && sym->sym.st_shndx == SHN_XINDEX)) { 423 if (sym->sym.st_shndx != SHN_XINDEX) 424 shndx = sym->sym.st_shndx; 425 426 sym->sec = find_section_by_index(elf, shndx); 427 if (!sym->sec) { 428 WARN("couldn't find section for symbol %s", 429 sym->name); 430 goto err; 431 } 432 if (sym->type == STT_SECTION) { 433 sym->name = sym->sec->name; 434 sym->sec->sym = sym; 435 } 436 } else 437 sym->sec = find_section_by_index(elf, 0); 438 439 sym->offset = sym->sym.st_value; 440 sym->len = sym->sym.st_size; 441 442 rb_add(&sym->sec->symbol_tree, &sym->node, symbol_to_offset); 443 pnode = rb_prev(&sym->node); 444 if (pnode) 445 entry = &rb_entry(pnode, struct symbol, node)->list; 446 else 447 entry = &sym->sec->symbol_list; 448 list_add(&sym->list, entry); 449 elf_hash_add(elf->symbol_hash, &sym->hash, sym->idx); 450 elf_hash_add(elf->symbol_name_hash, &sym->name_hash, str_hash(sym->name)); 451 } 452 453 if (stats) 454 printf("nr_symbols: %lu\n", (unsigned long)symbols_nr); 455 456 /* Create parent/child links for any cold subfunctions */ 457 list_for_each_entry(sec, &elf->sections, list) { 458 list_for_each_entry(sym, &sec->symbol_list, list) { 459 char pname[MAX_NAME_LEN + 1]; 460 size_t pnamelen; 461 if (sym->type != STT_FUNC) 462 continue; 463 464 if (sym->pfunc == NULL) 465 sym->pfunc = sym; 466 467 if (sym->cfunc == NULL) 468 sym->cfunc = sym; 469 470 coldstr = strstr(sym->name, ".cold"); 471 if (!coldstr) 472 continue; 473 474 pnamelen = coldstr - sym->name; 475 if (pnamelen > MAX_NAME_LEN) { 476 WARN("%s(): parent function name exceeds maximum length of %d characters", 477 sym->name, MAX_NAME_LEN); 478 return -1; 479 } 480 481 strncpy(pname, sym->name, pnamelen); 482 pname[pnamelen] = '\0'; 483 pfunc = find_symbol_by_name(elf, pname); 484 485 if (!pfunc) { 486 WARN("%s(): can't find parent function", 487 sym->name); 488 return -1; 489 } 490 491 sym->pfunc = pfunc; 492 pfunc->cfunc = sym; 493 494 /* 495 * Unfortunately, -fnoreorder-functions puts the child 496 * inside the parent. Remove the overlap so we can 497 * have sane assumptions. 498 * 499 * Note that pfunc->len now no longer matches 500 * pfunc->sym.st_size. 501 */ 502 if (sym->sec == pfunc->sec && 503 sym->offset >= pfunc->offset && 504 sym->offset + sym->len == pfunc->offset + pfunc->len) { 505 pfunc->len -= sym->len; 506 } 507 } 508 } 509 510 return 0; 511 512 err: 513 free(sym); 514 return -1; 515 } 516 517 void elf_add_reloc(struct elf *elf, struct reloc *reloc) 518 { 519 struct section *sec = reloc->sec; 520 521 list_add_tail(&reloc->list, &sec->reloc_list); 522 elf_hash_add(elf->reloc_hash, &reloc->hash, reloc_hash(reloc)); 523 } 524 525 static int read_rel_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx) 526 { 527 if (!gelf_getrel(sec->data, i, &reloc->rel)) { 528 WARN_ELF("gelf_getrel"); 529 return -1; 530 } 531 reloc->type = GELF_R_TYPE(reloc->rel.r_info); 532 reloc->addend = 0; 533 reloc->offset = reloc->rel.r_offset; 534 *symndx = GELF_R_SYM(reloc->rel.r_info); 535 return 0; 536 } 537 538 static int read_rela_reloc(struct section *sec, int i, struct reloc *reloc, unsigned int *symndx) 539 { 540 if (!gelf_getrela(sec->data, i, &reloc->rela)) { 541 WARN_ELF("gelf_getrela"); 542 return -1; 543 } 544 reloc->type = GELF_R_TYPE(reloc->rela.r_info); 545 reloc->addend = reloc->rela.r_addend; 546 reloc->offset = reloc->rela.r_offset; 547 *symndx = GELF_R_SYM(reloc->rela.r_info); 548 return 0; 549 } 550 551 static int read_relocs(struct elf *elf) 552 { 553 struct section *sec; 554 struct reloc *reloc; 555 int i; 556 unsigned int symndx; 557 unsigned long nr_reloc, max_reloc = 0, tot_reloc = 0; 558 559 list_for_each_entry(sec, &elf->sections, list) { 560 if ((sec->sh.sh_type != SHT_RELA) && 561 (sec->sh.sh_type != SHT_REL)) 562 continue; 563 564 sec->base = find_section_by_index(elf, sec->sh.sh_info); 565 if (!sec->base) { 566 WARN("can't find base section for reloc section %s", 567 sec->name); 568 return -1; 569 } 570 571 sec->base->reloc = sec; 572 573 nr_reloc = 0; 574 for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) { 575 reloc = malloc(sizeof(*reloc)); 576 if (!reloc) { 577 perror("malloc"); 578 return -1; 579 } 580 memset(reloc, 0, sizeof(*reloc)); 581 switch (sec->sh.sh_type) { 582 case SHT_REL: 583 if (read_rel_reloc(sec, i, reloc, &symndx)) 584 return -1; 585 break; 586 case SHT_RELA: 587 if (read_rela_reloc(sec, i, reloc, &symndx)) 588 return -1; 589 break; 590 default: return -1; 591 } 592 593 reloc->sec = sec; 594 reloc->idx = i; 595 reloc->sym = find_symbol_by_index(elf, symndx); 596 if (!reloc->sym) { 597 WARN("can't find reloc entry symbol %d for %s", 598 symndx, sec->name); 599 return -1; 600 } 601 602 elf_add_reloc(elf, reloc); 603 nr_reloc++; 604 } 605 max_reloc = max(max_reloc, nr_reloc); 606 tot_reloc += nr_reloc; 607 } 608 609 if (stats) { 610 printf("max_reloc: %lu\n", max_reloc); 611 printf("tot_reloc: %lu\n", tot_reloc); 612 } 613 614 return 0; 615 } 616 617 struct elf *elf_open_read(const char *name, int flags) 618 { 619 struct elf *elf; 620 Elf_Cmd cmd; 621 622 elf_version(EV_CURRENT); 623 624 elf = malloc(sizeof(*elf)); 625 if (!elf) { 626 perror("malloc"); 627 return NULL; 628 } 629 memset(elf, 0, offsetof(struct elf, sections)); 630 631 INIT_LIST_HEAD(&elf->sections); 632 633 elf_hash_init(elf->symbol_hash); 634 elf_hash_init(elf->symbol_name_hash); 635 elf_hash_init(elf->section_hash); 636 elf_hash_init(elf->section_name_hash); 637 elf_hash_init(elf->reloc_hash); 638 639 elf->fd = open(name, flags); 640 if (elf->fd == -1) { 641 fprintf(stderr, "objtool: Can't open '%s': %s\n", 642 name, strerror(errno)); 643 goto err; 644 } 645 646 if ((flags & O_ACCMODE) == O_RDONLY) 647 cmd = ELF_C_READ_MMAP; 648 else if ((flags & O_ACCMODE) == O_RDWR) 649 cmd = ELF_C_RDWR; 650 else /* O_WRONLY */ 651 cmd = ELF_C_WRITE; 652 653 elf->elf = elf_begin(elf->fd, cmd, NULL); 654 if (!elf->elf) { 655 WARN_ELF("elf_begin"); 656 goto err; 657 } 658 659 if (!gelf_getehdr(elf->elf, &elf->ehdr)) { 660 WARN_ELF("gelf_getehdr"); 661 goto err; 662 } 663 664 if (read_sections(elf)) 665 goto err; 666 667 if (read_symbols(elf)) 668 goto err; 669 670 if (read_relocs(elf)) 671 goto err; 672 673 return elf; 674 675 err: 676 elf_close(elf); 677 return NULL; 678 } 679 680 struct section *elf_create_section(struct elf *elf, const char *name, 681 unsigned int sh_flags, size_t entsize, int nr) 682 { 683 struct section *sec, *shstrtab; 684 size_t size = entsize * nr; 685 Elf_Scn *s; 686 Elf_Data *data; 687 688 sec = malloc(sizeof(*sec)); 689 if (!sec) { 690 perror("malloc"); 691 return NULL; 692 } 693 memset(sec, 0, sizeof(*sec)); 694 695 INIT_LIST_HEAD(&sec->symbol_list); 696 INIT_LIST_HEAD(&sec->reloc_list); 697 698 s = elf_newscn(elf->elf); 699 if (!s) { 700 WARN_ELF("elf_newscn"); 701 return NULL; 702 } 703 704 sec->name = strdup(name); 705 if (!sec->name) { 706 perror("strdup"); 707 return NULL; 708 } 709 710 sec->idx = elf_ndxscn(s); 711 sec->len = size; 712 sec->changed = true; 713 714 sec->data = elf_newdata(s); 715 if (!sec->data) { 716 WARN_ELF("elf_newdata"); 717 return NULL; 718 } 719 720 sec->data->d_size = size; 721 sec->data->d_align = 1; 722 723 if (size) { 724 sec->data->d_buf = malloc(size); 725 if (!sec->data->d_buf) { 726 perror("malloc"); 727 return NULL; 728 } 729 memset(sec->data->d_buf, 0, size); 730 } 731 732 if (!gelf_getshdr(s, &sec->sh)) { 733 WARN_ELF("gelf_getshdr"); 734 return NULL; 735 } 736 737 sec->sh.sh_size = size; 738 sec->sh.sh_entsize = entsize; 739 sec->sh.sh_type = SHT_PROGBITS; 740 sec->sh.sh_addralign = 1; 741 sec->sh.sh_flags = SHF_ALLOC | sh_flags; 742 743 744 /* Add section name to .shstrtab (or .strtab for Clang) */ 745 shstrtab = find_section_by_name(elf, ".shstrtab"); 746 if (!shstrtab) 747 shstrtab = find_section_by_name(elf, ".strtab"); 748 if (!shstrtab) { 749 WARN("can't find .shstrtab or .strtab section"); 750 return NULL; 751 } 752 753 s = elf_getscn(elf->elf, shstrtab->idx); 754 if (!s) { 755 WARN_ELF("elf_getscn"); 756 return NULL; 757 } 758 759 data = elf_newdata(s); 760 if (!data) { 761 WARN_ELF("elf_newdata"); 762 return NULL; 763 } 764 765 data->d_buf = sec->name; 766 data->d_size = strlen(name) + 1; 767 data->d_align = 1; 768 769 sec->sh.sh_name = shstrtab->len; 770 771 shstrtab->len += strlen(name) + 1; 772 shstrtab->changed = true; 773 774 list_add_tail(&sec->list, &elf->sections); 775 elf_hash_add(elf->section_hash, &sec->hash, sec->idx); 776 elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name)); 777 778 elf->changed = true; 779 780 return sec; 781 } 782 783 static struct section *elf_create_rel_reloc_section(struct elf *elf, struct section *base) 784 { 785 char *relocname; 786 struct section *sec; 787 788 relocname = malloc(strlen(base->name) + strlen(".rel") + 1); 789 if (!relocname) { 790 perror("malloc"); 791 return NULL; 792 } 793 strcpy(relocname, ".rel"); 794 strcat(relocname, base->name); 795 796 sec = elf_create_section(elf, relocname, 0, sizeof(GElf_Rel), 0); 797 free(relocname); 798 if (!sec) 799 return NULL; 800 801 base->reloc = sec; 802 sec->base = base; 803 804 sec->sh.sh_type = SHT_REL; 805 sec->sh.sh_addralign = 8; 806 sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx; 807 sec->sh.sh_info = base->idx; 808 sec->sh.sh_flags = SHF_INFO_LINK; 809 810 return sec; 811 } 812 813 static struct section *elf_create_rela_reloc_section(struct elf *elf, struct section *base) 814 { 815 char *relocname; 816 struct section *sec; 817 818 relocname = malloc(strlen(base->name) + strlen(".rela") + 1); 819 if (!relocname) { 820 perror("malloc"); 821 return NULL; 822 } 823 strcpy(relocname, ".rela"); 824 strcat(relocname, base->name); 825 826 sec = elf_create_section(elf, relocname, 0, sizeof(GElf_Rela), 0); 827 free(relocname); 828 if (!sec) 829 return NULL; 830 831 base->reloc = sec; 832 sec->base = base; 833 834 sec->sh.sh_type = SHT_RELA; 835 sec->sh.sh_addralign = 8; 836 sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx; 837 sec->sh.sh_info = base->idx; 838 sec->sh.sh_flags = SHF_INFO_LINK; 839 840 return sec; 841 } 842 843 struct section *elf_create_reloc_section(struct elf *elf, 844 struct section *base, 845 int reltype) 846 { 847 switch (reltype) { 848 case SHT_REL: return elf_create_rel_reloc_section(elf, base); 849 case SHT_RELA: return elf_create_rela_reloc_section(elf, base); 850 default: return NULL; 851 } 852 } 853 854 static int elf_rebuild_rel_reloc_section(struct section *sec, int nr) 855 { 856 struct reloc *reloc; 857 int idx = 0, size; 858 GElf_Rel *relocs; 859 860 /* Allocate a buffer for relocations */ 861 size = nr * sizeof(*relocs); 862 relocs = malloc(size); 863 if (!relocs) { 864 perror("malloc"); 865 return -1; 866 } 867 868 sec->data->d_buf = relocs; 869 sec->data->d_size = size; 870 871 sec->sh.sh_size = size; 872 873 idx = 0; 874 list_for_each_entry(reloc, &sec->reloc_list, list) { 875 relocs[idx].r_offset = reloc->offset; 876 relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 877 idx++; 878 } 879 880 return 0; 881 } 882 883 static int elf_rebuild_rela_reloc_section(struct section *sec, int nr) 884 { 885 struct reloc *reloc; 886 int idx = 0, size; 887 GElf_Rela *relocs; 888 889 /* Allocate a buffer for relocations with addends */ 890 size = nr * sizeof(*relocs); 891 relocs = malloc(size); 892 if (!relocs) { 893 perror("malloc"); 894 return -1; 895 } 896 897 sec->data->d_buf = relocs; 898 sec->data->d_size = size; 899 900 sec->sh.sh_size = size; 901 902 idx = 0; 903 list_for_each_entry(reloc, &sec->reloc_list, list) { 904 relocs[idx].r_offset = reloc->offset; 905 relocs[idx].r_addend = reloc->addend; 906 relocs[idx].r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 907 idx++; 908 } 909 910 return 0; 911 } 912 913 int elf_rebuild_reloc_section(struct elf *elf, struct section *sec) 914 { 915 struct reloc *reloc; 916 int nr; 917 918 sec->changed = true; 919 elf->changed = true; 920 921 nr = 0; 922 list_for_each_entry(reloc, &sec->reloc_list, list) 923 nr++; 924 925 switch (sec->sh.sh_type) { 926 case SHT_REL: return elf_rebuild_rel_reloc_section(sec, nr); 927 case SHT_RELA: return elf_rebuild_rela_reloc_section(sec, nr); 928 default: return -1; 929 } 930 } 931 932 int elf_write_insn(struct elf *elf, struct section *sec, 933 unsigned long offset, unsigned int len, 934 const char *insn) 935 { 936 Elf_Data *data = sec->data; 937 938 if (data->d_type != ELF_T_BYTE || data->d_off) { 939 WARN("write to unexpected data for section: %s", sec->name); 940 return -1; 941 } 942 943 memcpy(data->d_buf + offset, insn, len); 944 elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY); 945 946 elf->changed = true; 947 948 return 0; 949 } 950 951 int elf_write_reloc(struct elf *elf, struct reloc *reloc) 952 { 953 struct section *sec = reloc->sec; 954 955 if (sec->sh.sh_type == SHT_REL) { 956 reloc->rel.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 957 reloc->rel.r_offset = reloc->offset; 958 959 if (!gelf_update_rel(sec->data, reloc->idx, &reloc->rel)) { 960 WARN_ELF("gelf_update_rel"); 961 return -1; 962 } 963 } else { 964 reloc->rela.r_info = GELF_R_INFO(reloc->sym->idx, reloc->type); 965 reloc->rela.r_addend = reloc->addend; 966 reloc->rela.r_offset = reloc->offset; 967 968 if (!gelf_update_rela(sec->data, reloc->idx, &reloc->rela)) { 969 WARN_ELF("gelf_update_rela"); 970 return -1; 971 } 972 } 973 974 elf->changed = true; 975 976 return 0; 977 } 978 979 int elf_write(struct elf *elf) 980 { 981 struct section *sec; 982 Elf_Scn *s; 983 984 /* Update section headers for changed sections: */ 985 list_for_each_entry(sec, &elf->sections, list) { 986 if (sec->changed) { 987 s = elf_getscn(elf->elf, sec->idx); 988 if (!s) { 989 WARN_ELF("elf_getscn"); 990 return -1; 991 } 992 if (!gelf_update_shdr(s, &sec->sh)) { 993 WARN_ELF("gelf_update_shdr"); 994 return -1; 995 } 996 997 sec->changed = false; 998 } 999 } 1000 1001 /* Make sure the new section header entries get updated properly. */ 1002 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY); 1003 1004 /* Write all changes to the file. */ 1005 if (elf_update(elf->elf, ELF_C_WRITE) < 0) { 1006 WARN_ELF("elf_update"); 1007 return -1; 1008 } 1009 1010 elf->changed = false; 1011 1012 return 0; 1013 } 1014 1015 void elf_close(struct elf *elf) 1016 { 1017 struct section *sec, *tmpsec; 1018 struct symbol *sym, *tmpsym; 1019 struct reloc *reloc, *tmpreloc; 1020 1021 if (elf->elf) 1022 elf_end(elf->elf); 1023 1024 if (elf->fd > 0) 1025 close(elf->fd); 1026 1027 list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) { 1028 list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) { 1029 list_del(&sym->list); 1030 hash_del(&sym->hash); 1031 free(sym); 1032 } 1033 list_for_each_entry_safe(reloc, tmpreloc, &sec->reloc_list, list) { 1034 list_del(&reloc->list); 1035 hash_del(&reloc->hash); 1036 free(reloc); 1037 } 1038 list_del(&sec->list); 1039 free(sec); 1040 } 1041 1042 free(elf); 1043 } 1044