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 19 #include "elf.h" 20 #include "warn.h" 21 22 #define MAX_NAME_LEN 128 23 24 struct section *find_section_by_name(struct elf *elf, const char *name) 25 { 26 struct section *sec; 27 28 list_for_each_entry(sec, &elf->sections, list) 29 if (!strcmp(sec->name, name)) 30 return sec; 31 32 return NULL; 33 } 34 35 static struct section *find_section_by_index(struct elf *elf, 36 unsigned int idx) 37 { 38 struct section *sec; 39 40 list_for_each_entry(sec, &elf->sections, list) 41 if (sec->idx == idx) 42 return sec; 43 44 return NULL; 45 } 46 47 static struct symbol *find_symbol_by_index(struct elf *elf, unsigned int idx) 48 { 49 struct section *sec; 50 struct symbol *sym; 51 52 list_for_each_entry(sec, &elf->sections, list) 53 hash_for_each_possible(sec->symbol_hash, sym, hash, idx) 54 if (sym->idx == idx) 55 return sym; 56 57 return NULL; 58 } 59 60 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset) 61 { 62 struct symbol *sym; 63 64 list_for_each_entry(sym, &sec->symbol_list, list) 65 if (sym->type != STT_SECTION && 66 sym->offset == offset) 67 return sym; 68 69 return NULL; 70 } 71 72 struct symbol *find_symbol_by_name(struct elf *elf, const char *name) 73 { 74 struct section *sec; 75 struct symbol *sym; 76 77 list_for_each_entry(sec, &elf->sections, list) 78 list_for_each_entry(sym, &sec->symbol_list, list) 79 if (!strcmp(sym->name, name)) 80 return sym; 81 82 return NULL; 83 } 84 85 struct symbol *find_symbol_containing(struct section *sec, unsigned long offset) 86 { 87 struct symbol *sym; 88 89 list_for_each_entry(sym, &sec->symbol_list, list) 90 if (sym->type != STT_SECTION && 91 offset >= sym->offset && offset < sym->offset + sym->len) 92 return sym; 93 94 return NULL; 95 } 96 97 struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset, 98 unsigned int len) 99 { 100 struct rela *rela; 101 unsigned long o; 102 103 if (!sec->rela) 104 return NULL; 105 106 for (o = offset; o < offset + len; o++) 107 hash_for_each_possible(sec->rela->rela_hash, rela, hash, o) 108 if (rela->offset == o) 109 return rela; 110 111 return NULL; 112 } 113 114 struct rela *find_rela_by_dest(struct section *sec, unsigned long offset) 115 { 116 return find_rela_by_dest_range(sec, offset, 1); 117 } 118 119 struct symbol *find_containing_func(struct section *sec, unsigned long offset) 120 { 121 struct symbol *func; 122 123 list_for_each_entry(func, &sec->symbol_list, list) 124 if (func->type == STT_FUNC && offset >= func->offset && 125 offset < func->offset + func->len) 126 return func; 127 128 return NULL; 129 } 130 131 static int read_sections(struct elf *elf) 132 { 133 Elf_Scn *s = NULL; 134 struct section *sec; 135 size_t shstrndx, sections_nr; 136 int i; 137 138 if (elf_getshdrnum(elf->elf, §ions_nr)) { 139 WARN_ELF("elf_getshdrnum"); 140 return -1; 141 } 142 143 if (elf_getshdrstrndx(elf->elf, &shstrndx)) { 144 WARN_ELF("elf_getshdrstrndx"); 145 return -1; 146 } 147 148 for (i = 0; i < sections_nr; i++) { 149 sec = malloc(sizeof(*sec)); 150 if (!sec) { 151 perror("malloc"); 152 return -1; 153 } 154 memset(sec, 0, sizeof(*sec)); 155 156 INIT_LIST_HEAD(&sec->symbol_list); 157 INIT_LIST_HEAD(&sec->rela_list); 158 hash_init(sec->rela_hash); 159 hash_init(sec->symbol_hash); 160 161 list_add_tail(&sec->list, &elf->sections); 162 163 s = elf_getscn(elf->elf, i); 164 if (!s) { 165 WARN_ELF("elf_getscn"); 166 return -1; 167 } 168 169 sec->idx = elf_ndxscn(s); 170 171 if (!gelf_getshdr(s, &sec->sh)) { 172 WARN_ELF("gelf_getshdr"); 173 return -1; 174 } 175 176 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name); 177 if (!sec->name) { 178 WARN_ELF("elf_strptr"); 179 return -1; 180 } 181 182 if (sec->sh.sh_size != 0) { 183 sec->data = elf_getdata(s, NULL); 184 if (!sec->data) { 185 WARN_ELF("elf_getdata"); 186 return -1; 187 } 188 if (sec->data->d_off != 0 || 189 sec->data->d_size != sec->sh.sh_size) { 190 WARN("unexpected data attributes for %s", 191 sec->name); 192 return -1; 193 } 194 } 195 sec->len = sec->sh.sh_size; 196 } 197 198 /* sanity check, one more call to elf_nextscn() should return NULL */ 199 if (elf_nextscn(elf->elf, s)) { 200 WARN("section entry mismatch"); 201 return -1; 202 } 203 204 return 0; 205 } 206 207 static int read_symbols(struct elf *elf) 208 { 209 struct section *symtab, *sec; 210 struct symbol *sym, *pfunc, *alias; 211 struct list_head *entry, *tmp; 212 int symbols_nr, i; 213 char *coldstr; 214 215 symtab = find_section_by_name(elf, ".symtab"); 216 if (!symtab) { 217 WARN("missing symbol table"); 218 return -1; 219 } 220 221 symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize; 222 223 for (i = 0; i < symbols_nr; i++) { 224 sym = malloc(sizeof(*sym)); 225 if (!sym) { 226 perror("malloc"); 227 return -1; 228 } 229 memset(sym, 0, sizeof(*sym)); 230 alias = sym; 231 232 sym->idx = i; 233 234 if (!gelf_getsym(symtab->data, i, &sym->sym)) { 235 WARN_ELF("gelf_getsym"); 236 goto err; 237 } 238 239 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link, 240 sym->sym.st_name); 241 if (!sym->name) { 242 WARN_ELF("elf_strptr"); 243 goto err; 244 } 245 246 sym->type = GELF_ST_TYPE(sym->sym.st_info); 247 sym->bind = GELF_ST_BIND(sym->sym.st_info); 248 249 if (sym->sym.st_shndx > SHN_UNDEF && 250 sym->sym.st_shndx < SHN_LORESERVE) { 251 sym->sec = find_section_by_index(elf, 252 sym->sym.st_shndx); 253 if (!sym->sec) { 254 WARN("couldn't find section for symbol %s", 255 sym->name); 256 goto err; 257 } 258 if (sym->type == STT_SECTION) { 259 sym->name = sym->sec->name; 260 sym->sec->sym = sym; 261 } 262 } else 263 sym->sec = find_section_by_index(elf, 0); 264 265 sym->offset = sym->sym.st_value; 266 sym->len = sym->sym.st_size; 267 268 /* sorted insert into a per-section list */ 269 entry = &sym->sec->symbol_list; 270 list_for_each_prev(tmp, &sym->sec->symbol_list) { 271 struct symbol *s; 272 273 s = list_entry(tmp, struct symbol, list); 274 275 if (sym->offset > s->offset) { 276 entry = tmp; 277 break; 278 } 279 280 if (sym->offset == s->offset) { 281 if (sym->len && sym->len == s->len && alias == sym) 282 alias = s; 283 284 if (sym->len >= s->len) { 285 entry = tmp; 286 break; 287 } 288 } 289 } 290 sym->alias = alias; 291 list_add(&sym->list, entry); 292 hash_add(sym->sec->symbol_hash, &sym->hash, sym->idx); 293 } 294 295 /* Create parent/child links for any cold subfunctions */ 296 list_for_each_entry(sec, &elf->sections, list) { 297 list_for_each_entry(sym, &sec->symbol_list, list) { 298 char pname[MAX_NAME_LEN + 1]; 299 size_t pnamelen; 300 if (sym->type != STT_FUNC) 301 continue; 302 sym->pfunc = sym->cfunc = sym; 303 coldstr = strstr(sym->name, ".cold"); 304 if (!coldstr) 305 continue; 306 307 pnamelen = coldstr - sym->name; 308 if (pnamelen > MAX_NAME_LEN) { 309 WARN("%s(): parent function name exceeds maximum length of %d characters", 310 sym->name, MAX_NAME_LEN); 311 return -1; 312 } 313 314 strncpy(pname, sym->name, pnamelen); 315 pname[pnamelen] = '\0'; 316 pfunc = find_symbol_by_name(elf, pname); 317 318 if (!pfunc) { 319 WARN("%s(): can't find parent function", 320 sym->name); 321 return -1; 322 } 323 324 sym->pfunc = pfunc; 325 pfunc->cfunc = sym; 326 327 /* 328 * Unfortunately, -fnoreorder-functions puts the child 329 * inside the parent. Remove the overlap so we can 330 * have sane assumptions. 331 * 332 * Note that pfunc->len now no longer matches 333 * pfunc->sym.st_size. 334 */ 335 if (sym->sec == pfunc->sec && 336 sym->offset >= pfunc->offset && 337 sym->offset + sym->len == pfunc->offset + pfunc->len) { 338 pfunc->len -= sym->len; 339 } 340 } 341 } 342 343 return 0; 344 345 err: 346 free(sym); 347 return -1; 348 } 349 350 static int read_relas(struct elf *elf) 351 { 352 struct section *sec; 353 struct rela *rela; 354 int i; 355 unsigned int symndx; 356 357 list_for_each_entry(sec, &elf->sections, list) { 358 if (sec->sh.sh_type != SHT_RELA) 359 continue; 360 361 sec->base = find_section_by_name(elf, sec->name + 5); 362 if (!sec->base) { 363 WARN("can't find base section for rela section %s", 364 sec->name); 365 return -1; 366 } 367 368 sec->base->rela = sec; 369 370 for (i = 0; i < sec->sh.sh_size / sec->sh.sh_entsize; i++) { 371 rela = malloc(sizeof(*rela)); 372 if (!rela) { 373 perror("malloc"); 374 return -1; 375 } 376 memset(rela, 0, sizeof(*rela)); 377 378 if (!gelf_getrela(sec->data, i, &rela->rela)) { 379 WARN_ELF("gelf_getrela"); 380 return -1; 381 } 382 383 rela->type = GELF_R_TYPE(rela->rela.r_info); 384 rela->addend = rela->rela.r_addend; 385 rela->offset = rela->rela.r_offset; 386 symndx = GELF_R_SYM(rela->rela.r_info); 387 rela->sym = find_symbol_by_index(elf, symndx); 388 rela->sec = sec; 389 if (!rela->sym) { 390 WARN("can't find rela entry symbol %d for %s", 391 symndx, sec->name); 392 return -1; 393 } 394 395 list_add_tail(&rela->list, &sec->rela_list); 396 hash_add(sec->rela_hash, &rela->hash, rela->offset); 397 398 } 399 } 400 401 return 0; 402 } 403 404 struct elf *elf_read(const char *name, int flags) 405 { 406 struct elf *elf; 407 Elf_Cmd cmd; 408 409 elf_version(EV_CURRENT); 410 411 elf = malloc(sizeof(*elf)); 412 if (!elf) { 413 perror("malloc"); 414 return NULL; 415 } 416 memset(elf, 0, sizeof(*elf)); 417 418 INIT_LIST_HEAD(&elf->sections); 419 420 elf->fd = open(name, flags); 421 if (elf->fd == -1) { 422 fprintf(stderr, "objtool: Can't open '%s': %s\n", 423 name, strerror(errno)); 424 goto err; 425 } 426 427 if ((flags & O_ACCMODE) == O_RDONLY) 428 cmd = ELF_C_READ_MMAP; 429 else if ((flags & O_ACCMODE) == O_RDWR) 430 cmd = ELF_C_RDWR; 431 else /* O_WRONLY */ 432 cmd = ELF_C_WRITE; 433 434 elf->elf = elf_begin(elf->fd, cmd, NULL); 435 if (!elf->elf) { 436 WARN_ELF("elf_begin"); 437 goto err; 438 } 439 440 if (!gelf_getehdr(elf->elf, &elf->ehdr)) { 441 WARN_ELF("gelf_getehdr"); 442 goto err; 443 } 444 445 if (read_sections(elf)) 446 goto err; 447 448 if (read_symbols(elf)) 449 goto err; 450 451 if (read_relas(elf)) 452 goto err; 453 454 return elf; 455 456 err: 457 elf_close(elf); 458 return NULL; 459 } 460 461 struct section *elf_create_section(struct elf *elf, const char *name, 462 size_t entsize, int nr) 463 { 464 struct section *sec, *shstrtab; 465 size_t size = entsize * nr; 466 Elf_Scn *s; 467 Elf_Data *data; 468 469 sec = malloc(sizeof(*sec)); 470 if (!sec) { 471 perror("malloc"); 472 return NULL; 473 } 474 memset(sec, 0, sizeof(*sec)); 475 476 INIT_LIST_HEAD(&sec->symbol_list); 477 INIT_LIST_HEAD(&sec->rela_list); 478 hash_init(sec->rela_hash); 479 hash_init(sec->symbol_hash); 480 481 list_add_tail(&sec->list, &elf->sections); 482 483 s = elf_newscn(elf->elf); 484 if (!s) { 485 WARN_ELF("elf_newscn"); 486 return NULL; 487 } 488 489 sec->name = strdup(name); 490 if (!sec->name) { 491 perror("strdup"); 492 return NULL; 493 } 494 495 sec->idx = elf_ndxscn(s); 496 sec->len = size; 497 sec->changed = true; 498 499 sec->data = elf_newdata(s); 500 if (!sec->data) { 501 WARN_ELF("elf_newdata"); 502 return NULL; 503 } 504 505 sec->data->d_size = size; 506 sec->data->d_align = 1; 507 508 if (size) { 509 sec->data->d_buf = malloc(size); 510 if (!sec->data->d_buf) { 511 perror("malloc"); 512 return NULL; 513 } 514 memset(sec->data->d_buf, 0, size); 515 } 516 517 if (!gelf_getshdr(s, &sec->sh)) { 518 WARN_ELF("gelf_getshdr"); 519 return NULL; 520 } 521 522 sec->sh.sh_size = size; 523 sec->sh.sh_entsize = entsize; 524 sec->sh.sh_type = SHT_PROGBITS; 525 sec->sh.sh_addralign = 1; 526 sec->sh.sh_flags = SHF_ALLOC; 527 528 529 /* Add section name to .shstrtab (or .strtab for Clang) */ 530 shstrtab = find_section_by_name(elf, ".shstrtab"); 531 if (!shstrtab) 532 shstrtab = find_section_by_name(elf, ".strtab"); 533 if (!shstrtab) { 534 WARN("can't find .shstrtab or .strtab section"); 535 return NULL; 536 } 537 538 s = elf_getscn(elf->elf, shstrtab->idx); 539 if (!s) { 540 WARN_ELF("elf_getscn"); 541 return NULL; 542 } 543 544 data = elf_newdata(s); 545 if (!data) { 546 WARN_ELF("elf_newdata"); 547 return NULL; 548 } 549 550 data->d_buf = sec->name; 551 data->d_size = strlen(name) + 1; 552 data->d_align = 1; 553 554 sec->sh.sh_name = shstrtab->len; 555 556 shstrtab->len += strlen(name) + 1; 557 shstrtab->changed = true; 558 559 return sec; 560 } 561 562 struct section *elf_create_rela_section(struct elf *elf, struct section *base) 563 { 564 char *relaname; 565 struct section *sec; 566 567 relaname = malloc(strlen(base->name) + strlen(".rela") + 1); 568 if (!relaname) { 569 perror("malloc"); 570 return NULL; 571 } 572 strcpy(relaname, ".rela"); 573 strcat(relaname, base->name); 574 575 sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0); 576 free(relaname); 577 if (!sec) 578 return NULL; 579 580 base->rela = sec; 581 sec->base = base; 582 583 sec->sh.sh_type = SHT_RELA; 584 sec->sh.sh_addralign = 8; 585 sec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx; 586 sec->sh.sh_info = base->idx; 587 sec->sh.sh_flags = SHF_INFO_LINK; 588 589 return sec; 590 } 591 592 int elf_rebuild_rela_section(struct section *sec) 593 { 594 struct rela *rela; 595 int nr, idx = 0, size; 596 GElf_Rela *relas; 597 598 nr = 0; 599 list_for_each_entry(rela, &sec->rela_list, list) 600 nr++; 601 602 size = nr * sizeof(*relas); 603 relas = malloc(size); 604 if (!relas) { 605 perror("malloc"); 606 return -1; 607 } 608 609 sec->data->d_buf = relas; 610 sec->data->d_size = size; 611 612 sec->sh.sh_size = size; 613 614 idx = 0; 615 list_for_each_entry(rela, &sec->rela_list, list) { 616 relas[idx].r_offset = rela->offset; 617 relas[idx].r_addend = rela->addend; 618 relas[idx].r_info = GELF_R_INFO(rela->sym->idx, rela->type); 619 idx++; 620 } 621 622 return 0; 623 } 624 625 int elf_write(struct elf *elf) 626 { 627 struct section *sec; 628 Elf_Scn *s; 629 630 /* Update section headers for changed sections: */ 631 list_for_each_entry(sec, &elf->sections, list) { 632 if (sec->changed) { 633 s = elf_getscn(elf->elf, sec->idx); 634 if (!s) { 635 WARN_ELF("elf_getscn"); 636 return -1; 637 } 638 if (!gelf_update_shdr(s, &sec->sh)) { 639 WARN_ELF("gelf_update_shdr"); 640 return -1; 641 } 642 } 643 } 644 645 /* Make sure the new section header entries get updated properly. */ 646 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY); 647 648 /* Write all changes to the file. */ 649 if (elf_update(elf->elf, ELF_C_WRITE) < 0) { 650 WARN_ELF("elf_update"); 651 return -1; 652 } 653 654 return 0; 655 } 656 657 void elf_close(struct elf *elf) 658 { 659 struct section *sec, *tmpsec; 660 struct symbol *sym, *tmpsym; 661 struct rela *rela, *tmprela; 662 663 if (elf->elf) 664 elf_end(elf->elf); 665 666 if (elf->fd > 0) 667 close(elf->fd); 668 669 list_for_each_entry_safe(sec, tmpsec, &elf->sections, list) { 670 list_for_each_entry_safe(sym, tmpsym, &sec->symbol_list, list) { 671 list_del(&sym->list); 672 hash_del(&sym->hash); 673 free(sym); 674 } 675 list_for_each_entry_safe(rela, tmprela, &sec->rela_list, list) { 676 list_del(&rela->list); 677 hash_del(&rela->hash); 678 free(rela); 679 } 680 list_del(&sec->list); 681 free(sec); 682 } 683 684 free(elf); 685 } 686