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