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