1 /*- 2 * Copyright (c) 2007-2011,2014 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <sys/stat.h> 29 #include <err.h> 30 #include <libgen.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 #include "elfcopy.h" 36 37 ELFTC_VCSID("$Id: sections.c 3272 2015-12-11 20:00:54Z kaiwang27 $"); 38 39 static void add_gnu_debuglink(struct elfcopy *ecp); 40 static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); 41 static void check_section_rename(struct elfcopy *ecp, struct section *s); 42 static void filter_reloc(struct elfcopy *ecp, struct section *s); 43 static int get_section_flags(struct elfcopy *ecp, const char *name); 44 static void insert_sections(struct elfcopy *ecp); 45 static void insert_to_strtab(struct section *t, const char *s); 46 static int is_append_section(struct elfcopy *ecp, const char *name); 47 static int is_compress_section(struct elfcopy *ecp, const char *name); 48 static int is_debug_section(const char *name); 49 static int is_dwo_section(const char *name); 50 static int is_modify_section(struct elfcopy *ecp, const char *name); 51 static int is_print_section(struct elfcopy *ecp, const char *name); 52 static int lookup_string(struct section *t, const char *s); 53 static void modify_section(struct elfcopy *ecp, struct section *s); 54 static void pad_section(struct elfcopy *ecp, struct section *s); 55 static void print_data(const char *d, size_t sz); 56 static void print_section(struct section *s); 57 static void *read_section(struct section *s, size_t *size); 58 static void update_reloc(struct elfcopy *ecp, struct section *s); 59 static void update_section_group(struct elfcopy *ecp, struct section *s); 60 61 int 62 is_remove_section(struct elfcopy *ecp, const char *name) 63 { 64 65 /* Always keep section name table */ 66 if (strcmp(name, ".shstrtab") == 0) 67 return 0; 68 if (strcmp(name, ".symtab") == 0 || 69 strcmp(name, ".strtab") == 0) { 70 if (ecp->strip == STRIP_ALL && lookup_symop_list( 71 ecp, NULL, SYMOP_KEEP) == NULL) 72 return (1); 73 else 74 return (0); 75 } 76 77 if (ecp->strip == STRIP_DWO && is_dwo_section(name)) 78 return (1); 79 if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name)) 80 return (1); 81 82 if (is_debug_section(name)) { 83 if (ecp->strip == STRIP_ALL || 84 ecp->strip == STRIP_DEBUG || 85 ecp->strip == STRIP_UNNEEDED || 86 (ecp->flags & DISCARD_LOCAL)) 87 return (1); 88 if (ecp->strip == STRIP_NONDEBUG) 89 return (0); 90 } 91 92 if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { 93 struct sec_action *sac; 94 95 sac = lookup_sec_act(ecp, name, 0); 96 if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) 97 return (1); 98 if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) 99 return (1); 100 } 101 102 return (0); 103 } 104 105 /* 106 * Relocation section needs to be removed if the section it applies to 107 * will be removed. 108 */ 109 int 110 is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) 111 { 112 const char *name; 113 GElf_Shdr ish; 114 Elf_Scn *is; 115 size_t indx; 116 int elferr; 117 118 if (elf_getshstrndx(ecp->ein, &indx) == 0) 119 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 120 elf_errmsg(-1)); 121 122 is = NULL; 123 while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 124 if (sh_info == elf_ndxscn(is)) { 125 if (gelf_getshdr(is, &ish) == NULL) 126 errx(EXIT_FAILURE, "gelf_getshdr failed: %s", 127 elf_errmsg(-1)); 128 if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == 129 NULL) 130 errx(EXIT_FAILURE, "elf_strptr failed: %s", 131 elf_errmsg(-1)); 132 if (is_remove_section(ecp, name)) 133 return (1); 134 else 135 return (0); 136 } 137 } 138 elferr = elf_errno(); 139 if (elferr != 0) 140 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 141 elf_errmsg(elferr)); 142 143 /* Remove reloc section if we can't find the target section. */ 144 return (1); 145 } 146 147 static int 148 is_append_section(struct elfcopy *ecp, const char *name) 149 { 150 struct sec_action *sac; 151 152 sac = lookup_sec_act(ecp, name, 0); 153 if (sac != NULL && sac->append != 0 && sac->string != NULL) 154 return (1); 155 156 return (0); 157 } 158 159 static int 160 is_compress_section(struct elfcopy *ecp, const char *name) 161 { 162 struct sec_action *sac; 163 164 sac = lookup_sec_act(ecp, name, 0); 165 if (sac != NULL && sac->compress != 0) 166 return (1); 167 168 return (0); 169 } 170 171 static void 172 check_section_rename(struct elfcopy *ecp, struct section *s) 173 { 174 struct sec_action *sac; 175 char *prefix; 176 size_t namelen; 177 178 if (s->pseudo) 179 return; 180 181 sac = lookup_sec_act(ecp, s->name, 0); 182 if (sac != NULL && sac->rename) 183 s->name = sac->newname; 184 185 if (!strcmp(s->name, ".symtab") || 186 !strcmp(s->name, ".strtab") || 187 !strcmp(s->name, ".shstrtab")) 188 return; 189 190 prefix = NULL; 191 if (s->loadable && ecp->prefix_alloc != NULL) 192 prefix = ecp->prefix_alloc; 193 else if (ecp->prefix_sec != NULL) 194 prefix = ecp->prefix_sec; 195 196 if (prefix != NULL) { 197 namelen = strlen(s->name) + strlen(prefix) + 1; 198 if ((s->newname = malloc(namelen)) == NULL) 199 err(EXIT_FAILURE, "malloc failed"); 200 snprintf(s->newname, namelen, "%s%s", prefix, s->name); 201 s->name = s->newname; 202 } 203 } 204 205 static int 206 get_section_flags(struct elfcopy *ecp, const char *name) 207 { 208 struct sec_action *sac; 209 210 sac = lookup_sec_act(ecp, name, 0); 211 if (sac != NULL && sac->flags) 212 return sac->flags; 213 214 return (0); 215 } 216 217 /* 218 * Determine whether the section are debugging section. 219 * According to libbfd, debugging sections are recognized 220 * only by name. 221 */ 222 static int 223 is_debug_section(const char *name) 224 { 225 const char *dbg_sec[] = { 226 ".debug", 227 ".gnu.linkonce.wi.", 228 ".line", 229 ".stab", 230 NULL 231 }; 232 const char **p; 233 234 for(p = dbg_sec; *p; p++) { 235 if (strncmp(name, *p, strlen(*p)) == 0) 236 return (1); 237 } 238 239 return (0); 240 } 241 242 static int 243 is_dwo_section(const char *name) 244 { 245 size_t len; 246 247 if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0) 248 return (1); 249 return (0); 250 } 251 252 static int 253 is_print_section(struct elfcopy *ecp, const char *name) 254 { 255 struct sec_action *sac; 256 257 sac = lookup_sec_act(ecp, name, 0); 258 if (sac != NULL && sac->print != 0) 259 return (1); 260 261 return (0); 262 } 263 264 static int 265 is_modify_section(struct elfcopy *ecp, const char *name) 266 { 267 268 if (is_append_section(ecp, name) || 269 is_compress_section(ecp, name)) 270 return (1); 271 272 return (0); 273 } 274 275 struct sec_action* 276 lookup_sec_act(struct elfcopy *ecp, const char *name, int add) 277 { 278 struct sec_action *sac; 279 280 if (name == NULL) 281 return NULL; 282 283 STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { 284 if (strcmp(name, sac->name) == 0) 285 return sac; 286 } 287 288 if (add == 0) 289 return NULL; 290 291 if ((sac = malloc(sizeof(*sac))) == NULL) 292 errx(EXIT_FAILURE, "not enough memory"); 293 memset(sac, 0, sizeof(*sac)); 294 sac->name = name; 295 STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); 296 297 return (sac); 298 } 299 300 void 301 free_sec_act(struct elfcopy *ecp) 302 { 303 struct sec_action *sac, *sac_temp; 304 305 STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { 306 STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); 307 free(sac); 308 } 309 } 310 311 void 312 insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) 313 { 314 struct section *s; 315 316 if (!tail) { 317 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 318 if (sec->off < s->off) { 319 TAILQ_INSERT_BEFORE(s, sec, sec_list); 320 goto inc_nos; 321 } 322 } 323 } 324 325 TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); 326 327 inc_nos: 328 if (sec->pseudo == 0) 329 ecp->nos++; 330 } 331 332 /* 333 * First step of section creation: create scn and internal section 334 * structure, discard sections to be removed. 335 */ 336 void 337 create_scn(struct elfcopy *ecp) 338 { 339 struct section *s; 340 const char *name; 341 Elf_Scn *is; 342 GElf_Shdr ish; 343 size_t indx; 344 uint64_t oldndx, newndx; 345 int elferr, sec_flags; 346 347 /* 348 * Insert a pseudo section that contains the ELF header 349 * and program header. Used as reference for section offset 350 * or load address adjustment. 351 */ 352 if ((s = calloc(1, sizeof(*s))) == NULL) 353 err(EXIT_FAILURE, "calloc failed"); 354 s->off = 0; 355 s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + 356 gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); 357 s->align = 1; 358 s->pseudo = 1; 359 s->loadable = add_to_inseg_list(ecp, s); 360 insert_to_sec_list(ecp, s, 0); 361 362 /* Create internal .shstrtab section. */ 363 init_shstrtab(ecp); 364 365 if (elf_getshstrndx(ecp->ein, &indx) == 0) 366 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", 367 elf_errmsg(-1)); 368 369 is = NULL; 370 while ((is = elf_nextscn(ecp->ein, is)) != NULL) { 371 if (gelf_getshdr(is, &ish) == NULL) 372 errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s", 373 elf_errmsg(-1)); 374 if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) 375 errx(EXIT_FAILURE, "elf_strptr failed: %s", 376 elf_errmsg(-1)); 377 378 /* Skip sections to be removed. */ 379 if (is_remove_section(ecp, name)) 380 continue; 381 382 /* 383 * Relocation section need to be remove if the section 384 * it applies will be removed. 385 */ 386 if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 387 if (ish.sh_info != 0 && 388 is_remove_reloc_sec(ecp, ish.sh_info)) 389 continue; 390 391 /* 392 * Section groups should be removed if symbol table will 393 * be removed. (section group's signature stored in symbol 394 * table) 395 */ 396 if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL) 397 continue; 398 399 /* Get section flags set by user. */ 400 sec_flags = get_section_flags(ecp, name); 401 402 /* Create internal section object. */ 403 if (strcmp(name, ".shstrtab") != 0) { 404 if ((s = calloc(1, sizeof(*s))) == NULL) 405 err(EXIT_FAILURE, "calloc failed"); 406 s->name = name; 407 s->is = is; 408 s->off = ish.sh_offset; 409 s->sz = ish.sh_size; 410 s->align = ish.sh_addralign; 411 s->type = ish.sh_type; 412 s->vma = ish.sh_addr; 413 414 /* 415 * Search program headers to determine whether section 416 * is loadable, but if user explicitly set section flags 417 * while neither "load" nor "alloc" is set, we make the 418 * section unloadable. 419 */ 420 if (sec_flags && 421 (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) 422 s->loadable = 0; 423 else 424 s->loadable = add_to_inseg_list(ecp, s); 425 } else { 426 /* Assuming .shstrtab is "unloadable". */ 427 s = ecp->shstrtab; 428 s->off = ish.sh_offset; 429 } 430 431 oldndx = newndx = SHN_UNDEF; 432 if (strcmp(name, ".symtab") != 0 && 433 strcmp(name, ".strtab") != 0) { 434 if (!strcmp(name, ".shstrtab")) { 435 /* 436 * Add sections specified by --add-section and 437 * gnu debuglink. we want these sections have 438 * smaller index than .shstrtab section. 439 */ 440 if (ecp->debuglink != NULL) 441 add_gnu_debuglink(ecp); 442 if (ecp->flags & SEC_ADD) 443 insert_sections(ecp); 444 } 445 if ((s->os = elf_newscn(ecp->eout)) == NULL) 446 errx(EXIT_FAILURE, "elf_newscn failed: %s", 447 elf_errmsg(-1)); 448 if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) 449 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 450 elf_errmsg(-1)); 451 } 452 if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) 453 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 454 elf_errmsg(-1)); 455 if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) 456 ecp->secndx[oldndx] = newndx; 457 458 /* 459 * If strip action is STRIP_NONDEBUG(only keep debug), 460 * change sections type of loadable sections and section 461 * groups to SHT_NOBITS, and the content of those sections 462 * will be discarded. However, SHT_NOTE sections should 463 * be kept. 464 */ 465 if (ecp->strip == STRIP_NONDEBUG) { 466 if (((ish.sh_flags & SHF_ALLOC) || 467 (ish.sh_flags & SHF_GROUP)) && 468 ish.sh_type != SHT_NOTE) 469 s->type = SHT_NOBITS; 470 } 471 472 check_section_rename(ecp, s); 473 474 /* create section header based on input object. */ 475 if (strcmp(name, ".symtab") != 0 && 476 strcmp(name, ".strtab") != 0 && 477 strcmp(name, ".shstrtab") != 0) 478 copy_shdr(ecp, s, NULL, 0, sec_flags); 479 480 if (strcmp(name, ".symtab") == 0) { 481 ecp->flags |= SYMTAB_EXIST; 482 ecp->symtab = s; 483 } 484 if (strcmp(name, ".strtab") == 0) 485 ecp->strtab = s; 486 487 insert_to_sec_list(ecp, s, 0); 488 } 489 elferr = elf_errno(); 490 if (elferr != 0) 491 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 492 elf_errmsg(elferr)); 493 } 494 495 struct section * 496 insert_shtab(struct elfcopy *ecp, int tail) 497 { 498 struct section *s, *shtab; 499 GElf_Ehdr ieh; 500 int nsecs; 501 502 /* 503 * Treat section header table as a "pseudo" section, insert it 504 * into section list, so later it will get sorted and resynced 505 * just as normal sections. 506 */ 507 if ((shtab = calloc(1, sizeof(*shtab))) == NULL) 508 errx(EXIT_FAILURE, "calloc failed"); 509 if (!tail) { 510 /* 511 * "shoff" of input object is used as a hint for section 512 * resync later. 513 */ 514 if (gelf_getehdr(ecp->ein, &ieh) == NULL) 515 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 516 elf_errmsg(-1)); 517 shtab->off = ieh.e_shoff; 518 } else 519 shtab->off = 0; 520 /* Calculate number of sections in the output object. */ 521 nsecs = 0; 522 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 523 if (!s->pseudo) 524 nsecs++; 525 } 526 /* Remember there is always a null section, so we +1 here. */ 527 shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); 528 if (shtab->sz == 0) 529 errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); 530 shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); 531 shtab->loadable = 0; 532 shtab->pseudo = 1; 533 insert_to_sec_list(ecp, shtab, tail); 534 535 return (shtab); 536 } 537 538 void 539 copy_content(struct elfcopy *ecp) 540 { 541 struct section *s; 542 543 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 544 /* Skip pseudo section. */ 545 if (s->pseudo) 546 continue; 547 548 /* Skip special sections. */ 549 if (strcmp(s->name, ".symtab") == 0 || 550 strcmp(s->name, ".strtab") == 0 || 551 strcmp(s->name, ".shstrtab") == 0) 552 continue; 553 554 /* 555 * If strip action is STRIP_ALL, relocation info need 556 * to be stripped. Skip filtering otherwisw. 557 */ 558 if (ecp->strip == STRIP_ALL && 559 (s->type == SHT_REL || s->type == SHT_RELA)) 560 filter_reloc(ecp, s); 561 562 /* 563 * The section indices in the SHT_GROUP section needs 564 * to be updated since we might have stripped some 565 * sections and changed section numbering. 566 */ 567 if (s->type == SHT_GROUP) 568 update_section_group(ecp, s); 569 570 if (is_modify_section(ecp, s->name)) 571 modify_section(ecp, s); 572 573 copy_data(s); 574 575 /* 576 * If symbol table is modified, relocation info might 577 * need update, as symbol index may have changed. 578 */ 579 if ((ecp->flags & SYMTAB_INTACT) == 0 && 580 (ecp->flags & SYMTAB_EXIST) && 581 (s->type == SHT_REL || s->type == SHT_RELA)) 582 update_reloc(ecp, s); 583 584 if (is_print_section(ecp, s->name)) 585 print_section(s); 586 } 587 } 588 589 590 /* 591 * Update section group section. The section indices in the SHT_GROUP 592 * section need update after section numbering changed. 593 */ 594 static void 595 update_section_group(struct elfcopy *ecp, struct section *s) 596 { 597 GElf_Shdr ish; 598 Elf_Data *id; 599 uint32_t *ws, *wd; 600 uint64_t n; 601 size_t ishnum; 602 int i, j; 603 604 if (!elf_getshnum(ecp->ein, &ishnum)) 605 errx(EXIT_FAILURE, "elf_getshnum failed: %s", 606 elf_errmsg(-1)); 607 608 if (gelf_getshdr(s->is, &ish) == NULL) 609 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 610 elf_errmsg(-1)); 611 612 if ((id = elf_getdata(s->is, NULL)) == NULL) 613 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 614 elf_errmsg(-1)); 615 616 if (ish.sh_size == 0) 617 return; 618 619 if (ish.sh_entsize == 0) 620 ish.sh_entsize = 4; 621 622 ws = id->d_buf; 623 624 /* We only support COMDAT section. */ 625 #ifndef GRP_COMDAT 626 #define GRP_COMDAT 0x1 627 #endif 628 if ((*ws & GRP_COMDAT) == 0) 629 return; 630 631 if ((s->buf = malloc(ish.sh_size)) == NULL) 632 err(EXIT_FAILURE, "malloc failed"); 633 634 s->sz = ish.sh_size; 635 636 wd = s->buf; 637 638 /* Copy the flag word as-is. */ 639 *wd = *ws; 640 641 /* Update the section indices. */ 642 n = ish.sh_size / ish.sh_entsize; 643 for(i = 1, j = 1; (uint64_t)i < n; i++) { 644 if (ws[i] != SHN_UNDEF && ws[i] < ishnum && 645 ecp->secndx[ws[i]] != 0) 646 wd[j++] = ecp->secndx[ws[i]]; 647 else 648 s->sz -= 4; 649 } 650 651 s->nocopy = 1; 652 } 653 654 /* 655 * Filter relocation entries, only keep those entries whose 656 * symbol is in the keep list. 657 */ 658 static void 659 filter_reloc(struct elfcopy *ecp, struct section *s) 660 { 661 const char *name; 662 GElf_Shdr ish; 663 GElf_Rel rel; 664 GElf_Rela rela; 665 Elf32_Rel *rel32; 666 Elf64_Rel *rel64; 667 Elf32_Rela *rela32; 668 Elf64_Rela *rela64; 669 Elf_Data *id; 670 uint64_t cap, n, nrels; 671 int elferr, i; 672 673 if (gelf_getshdr(s->is, &ish) == NULL) 674 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 675 elf_errmsg(-1)); 676 677 /* We don't want to touch relocation info for dynamic symbols. */ 678 if ((ecp->flags & SYMTAB_EXIST) == 0) { 679 if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) { 680 /* 681 * This reloc section applies to the symbol table 682 * that was stripped, so discard whole section. 683 */ 684 s->nocopy = 1; 685 s->sz = 0; 686 } 687 return; 688 } else { 689 /* Symbol table exist, check if index equals. */ 690 if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) 691 return; 692 } 693 694 #define COPYREL(REL, SZ) do { \ 695 if (nrels == 0) { \ 696 if ((REL##SZ = malloc(cap * \ 697 sizeof(Elf##SZ##_Rel))) == NULL) \ 698 err(EXIT_FAILURE, "malloc failed"); \ 699 } \ 700 if (nrels >= cap) { \ 701 cap *= 2; \ 702 if ((REL##SZ = realloc(REL##SZ, cap * \ 703 sizeof(Elf##SZ##_Rel))) == NULL) \ 704 err(EXIT_FAILURE, "realloc failed"); \ 705 } \ 706 REL##SZ[nrels].r_offset = REL.r_offset; \ 707 REL##SZ[nrels].r_info = REL.r_info; \ 708 if (s->type == SHT_RELA) \ 709 rela##SZ[nrels].r_addend = rela.r_addend; \ 710 nrels++; \ 711 } while (0) 712 713 nrels = 0; 714 cap = 4; /* keep list is usually small. */ 715 rel32 = NULL; 716 rel64 = NULL; 717 rela32 = NULL; 718 rela64 = NULL; 719 if ((id = elf_getdata(s->is, NULL)) == NULL) 720 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 721 elf_errmsg(-1)); 722 n = ish.sh_size / ish.sh_entsize; 723 for(i = 0; (uint64_t)i < n; i++) { 724 if (s->type == SHT_REL) { 725 if (gelf_getrel(id, i, &rel) != &rel) 726 errx(EXIT_FAILURE, "gelf_getrel failed: %s", 727 elf_errmsg(-1)); 728 } else { 729 if (gelf_getrela(id, i, &rela) != &rela) 730 errx(EXIT_FAILURE, "gelf_getrel failed: %s", 731 elf_errmsg(-1)); 732 } 733 name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), 734 GELF_R_SYM(rel.r_info)); 735 if (name == NULL) 736 errx(EXIT_FAILURE, "elf_strptr failed: %s", 737 elf_errmsg(-1)); 738 if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) { 739 if (ecp->oec == ELFCLASS32) { 740 if (s->type == SHT_REL) 741 COPYREL(rel, 32); 742 else 743 COPYREL(rela, 32); 744 } else { 745 if (s->type == SHT_REL) 746 COPYREL(rel, 64); 747 else 748 COPYREL(rela, 64); 749 } 750 } 751 } 752 elferr = elf_errno(); 753 if (elferr != 0) 754 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 755 elf_errmsg(elferr)); 756 757 if (ecp->oec == ELFCLASS32) { 758 if (s->type == SHT_REL) 759 s->buf = rel32; 760 else 761 s->buf = rela32; 762 } else { 763 if (s->type == SHT_REL) 764 s->buf = rel64; 765 else 766 s->buf = rela64; 767 } 768 s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : 769 ELF_T_RELA), nrels, EV_CURRENT); 770 s->nocopy = 1; 771 } 772 773 static void 774 update_reloc(struct elfcopy *ecp, struct section *s) 775 { 776 GElf_Shdr osh; 777 GElf_Rel rel; 778 GElf_Rela rela; 779 Elf_Data *od; 780 uint64_t n; 781 int i; 782 783 #define UPDATEREL(REL) do { \ 784 if (gelf_get##REL(od, i, &REL) != &REL) \ 785 errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ 786 elf_errmsg(-1)); \ 787 REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ 788 GELF_R_TYPE(REL.r_info)); \ 789 if (!gelf_update_##REL(od, i, &REL)) \ 790 errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ 791 elf_errmsg(-1)); \ 792 } while(0) 793 794 if (s->sz == 0) 795 return; 796 if (gelf_getshdr(s->os, &osh) == NULL) 797 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 798 elf_errmsg(-1)); 799 /* Only process .symtab reloc info. */ 800 if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) 801 return; 802 if ((od = elf_getdata(s->os, NULL)) == NULL) 803 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 804 elf_errmsg(-1)); 805 n = osh.sh_size / osh.sh_entsize; 806 for(i = 0; (uint64_t)i < n; i++) { 807 if (s->type == SHT_REL) 808 UPDATEREL(rel); 809 else 810 UPDATEREL(rela); 811 } 812 } 813 814 static void 815 pad_section(struct elfcopy *ecp, struct section *s) 816 { 817 GElf_Shdr osh; 818 Elf_Data *od; 819 820 if (s == NULL || s->pad_sz == 0) 821 return; 822 823 if ((s->pad = malloc(s->pad_sz)) == NULL) 824 err(EXIT_FAILURE, "malloc failed"); 825 memset(s->pad, ecp->fill, s->pad_sz); 826 827 /* Create a new Elf_Data to contain the padding bytes. */ 828 if ((od = elf_newdata(s->os)) == NULL) 829 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 830 elf_errmsg(-1)); 831 od->d_align = 1; 832 od->d_off = s->sz; 833 od->d_buf = s->pad; 834 od->d_type = ELF_T_BYTE; 835 od->d_size = s->pad_sz; 836 od->d_version = EV_CURRENT; 837 838 /* Update section header. */ 839 if (gelf_getshdr(s->os, &osh) == NULL) 840 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 841 elf_errmsg(-1)); 842 osh.sh_size = s->sz + s->pad_sz; 843 if (!gelf_update_shdr(s->os, &osh)) 844 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 845 elf_errmsg(-1)); 846 } 847 848 void 849 resync_sections(struct elfcopy *ecp) 850 { 851 struct section *s, *ps; 852 GElf_Shdr osh; 853 uint64_t off; 854 int first; 855 856 ps = NULL; 857 first = 1; 858 off = 0; 859 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 860 if (first) { 861 off = s->off; 862 first = 0; 863 } 864 865 /* 866 * Ignore TLS sections with load address 0 and without 867 * content. We don't need to adjust their file offset or 868 * VMA, only the size matters. 869 */ 870 if (s->seg_tls != NULL && s->type == SHT_NOBITS && 871 s->off == 0) 872 continue; 873 874 /* Align section offset. */ 875 if (s->align == 0) 876 s->align = 1; 877 if (off <= s->off) { 878 if (!s->loadable) 879 s->off = roundup(off, s->align); 880 } else { 881 if (s->loadable) 882 warnx("moving loadable section %s, " 883 "is this intentional?", s->name); 884 s->off = roundup(off, s->align); 885 } 886 887 /* Calculate next section offset. */ 888 off = s->off; 889 if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 890 off += s->sz; 891 892 if (s->pseudo) { 893 ps = NULL; 894 continue; 895 } 896 897 /* Count padding bytes added through --pad-to. */ 898 if (s->pad_sz > 0) 899 off += s->pad_sz; 900 901 /* Update section header accordingly. */ 902 if (gelf_getshdr(s->os, &osh) == NULL) 903 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 904 elf_errmsg(-1)); 905 osh.sh_addr = s->vma; 906 osh.sh_offset = s->off; 907 osh.sh_size = s->sz; 908 if (!gelf_update_shdr(s->os, &osh)) 909 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 910 elf_errmsg(-1)); 911 912 /* Add padding for previous section, if need. */ 913 if (ps != NULL) { 914 if (ps->pad_sz > 0) { 915 /* Apply padding added by --pad-to. */ 916 pad_section(ecp, ps); 917 } else if ((ecp->flags & GAP_FILL) && 918 (ps->off + ps->sz < s->off)) { 919 /* 920 * Fill the gap between sections by padding 921 * the section with lower address. 922 */ 923 ps->pad_sz = s->off - (ps->off + ps->sz); 924 pad_section(ecp, ps); 925 } 926 } 927 928 ps = s; 929 } 930 931 /* Pad the last section, if need. */ 932 if (ps != NULL && ps->pad_sz > 0) 933 pad_section(ecp, ps); 934 } 935 936 static void 937 modify_section(struct elfcopy *ecp, struct section *s) 938 { 939 struct sec_action *sac; 940 size_t srcsz, dstsz, p, len; 941 char *b, *c, *d, *src, *end; 942 int dupe; 943 944 src = read_section(s, &srcsz); 945 if (src == NULL || srcsz == 0) { 946 /* For empty section, we proceed if we need to append. */ 947 if (!is_append_section(ecp, s->name)) 948 return; 949 } 950 951 /* Allocate buffer needed for new section data. */ 952 dstsz = srcsz; 953 if (is_append_section(ecp, s->name)) { 954 sac = lookup_sec_act(ecp, s->name, 0); 955 dstsz += strlen(sac->string) + 1; 956 } 957 if ((b = malloc(dstsz)) == NULL) 958 err(EXIT_FAILURE, "malloc failed"); 959 s->buf = b; 960 961 /* Compress section. */ 962 p = 0; 963 if (is_compress_section(ecp, s->name)) { 964 end = src + srcsz; 965 for(c = src; c < end;) { 966 len = 0; 967 while(c + len < end && c[len] != '\0') 968 len++; 969 if (c + len == end) { 970 /* XXX should we warn here? */ 971 strncpy(&b[p], c, len); 972 p += len; 973 break; 974 } 975 dupe = 0; 976 for (d = b; d < b + p; ) { 977 if (strcmp(d, c) == 0) { 978 dupe = 1; 979 break; 980 } 981 d += strlen(d) + 1; 982 } 983 if (!dupe) { 984 strncpy(&b[p], c, len); 985 b[p + len] = '\0'; 986 p += len + 1; 987 } 988 c += len + 1; 989 } 990 } else { 991 memcpy(b, src, srcsz); 992 p += srcsz; 993 } 994 995 /* Append section. */ 996 if (is_append_section(ecp, s->name)) { 997 sac = lookup_sec_act(ecp, s->name, 0); 998 len = strlen(sac->string); 999 strncpy(&b[p], sac->string, len); 1000 b[p + len] = '\0'; 1001 p += len + 1; 1002 } 1003 1004 s->sz = p; 1005 s->nocopy = 1; 1006 } 1007 1008 static void 1009 print_data(const char *d, size_t sz) 1010 { 1011 const char *c; 1012 1013 for (c = d; c < d + sz; c++) { 1014 if (*c == '\0') 1015 putchar('\n'); 1016 else 1017 putchar(*c); 1018 } 1019 } 1020 1021 static void 1022 print_section(struct section *s) 1023 { 1024 Elf_Data *id; 1025 int elferr; 1026 1027 if (s->buf != NULL && s->sz > 0) { 1028 print_data(s->buf, s->sz); 1029 } else { 1030 id = NULL; 1031 while ((id = elf_getdata(s->is, id)) != NULL) 1032 print_data(id->d_buf, id->d_size); 1033 elferr = elf_errno(); 1034 if (elferr != 0) 1035 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1036 elf_errmsg(elferr)); 1037 } 1038 putchar('\n'); 1039 } 1040 1041 static void * 1042 read_section(struct section *s, size_t *size) 1043 { 1044 Elf_Data *id; 1045 char *b; 1046 size_t sz; 1047 int elferr; 1048 1049 sz = 0; 1050 b = NULL; 1051 id = NULL; 1052 while ((id = elf_getdata(s->is, id)) != NULL) { 1053 if (b == NULL) 1054 b = malloc(id->d_size); 1055 else 1056 b = malloc(sz + id->d_size); 1057 if (b == NULL) 1058 err(EXIT_FAILURE, "malloc or realloc failed"); 1059 1060 memcpy(&b[sz], id->d_buf, id->d_size); 1061 sz += id->d_size; 1062 } 1063 elferr = elf_errno(); 1064 if (elferr != 0) 1065 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1066 elf_errmsg(elferr)); 1067 1068 *size = sz; 1069 1070 return (b); 1071 } 1072 1073 void 1074 copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 1075 int sec_flags) 1076 { 1077 GElf_Shdr ish, osh; 1078 1079 if (gelf_getshdr(s->is, &ish) == NULL) 1080 errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", 1081 elf_errmsg(-1)); 1082 if (gelf_getshdr(s->os, &osh) == NULL) 1083 errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", 1084 elf_errmsg(-1)); 1085 1086 if (copy) 1087 (void) memcpy(&osh, &ish, sizeof(ish)); 1088 else { 1089 osh.sh_type = s->type; 1090 osh.sh_addr = s->vma; 1091 osh.sh_offset = s->off; 1092 osh.sh_size = s->sz; 1093 osh.sh_link = ish.sh_link; 1094 osh.sh_info = ish.sh_info; 1095 osh.sh_addralign = s->align; 1096 osh.sh_entsize = ish.sh_entsize; 1097 1098 if (sec_flags) { 1099 osh.sh_flags = 0; 1100 if (sec_flags & SF_ALLOC) { 1101 osh.sh_flags |= SHF_ALLOC; 1102 if (!s->loadable) 1103 warnx("set SHF_ALLOC flag for " 1104 "unloadable section %s", 1105 s->name); 1106 } 1107 if ((sec_flags & SF_READONLY) == 0) 1108 osh.sh_flags |= SHF_WRITE; 1109 if (sec_flags & SF_CODE) 1110 osh.sh_flags |= SHF_EXECINSTR; 1111 } else { 1112 osh.sh_flags = ish.sh_flags; 1113 if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) 1114 osh.sh_flags |= SHF_INFO_LINK; 1115 } 1116 } 1117 1118 if (name == NULL) 1119 add_to_shstrtab(ecp, s->name); 1120 else 1121 add_to_shstrtab(ecp, name); 1122 1123 if (!gelf_update_shdr(s->os, &osh)) 1124 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1125 elf_errmsg(-1)); 1126 } 1127 1128 void 1129 copy_data(struct section *s) 1130 { 1131 Elf_Data *id, *od; 1132 int elferr; 1133 1134 if (s->nocopy && s->buf == NULL) 1135 return; 1136 1137 if ((id = elf_getdata(s->is, NULL)) == NULL) { 1138 elferr = elf_errno(); 1139 if (elferr != 0) 1140 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1141 elf_errmsg(elferr)); 1142 return; 1143 } 1144 1145 if ((od = elf_newdata(s->os)) == NULL) 1146 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1147 elf_errmsg(-1)); 1148 1149 if (s->nocopy) { 1150 /* Use s->buf as content if s->nocopy is set. */ 1151 od->d_align = id->d_align; 1152 od->d_off = 0; 1153 od->d_buf = s->buf; 1154 od->d_type = id->d_type; 1155 od->d_size = s->sz; 1156 od->d_version = id->d_version; 1157 } else { 1158 od->d_align = id->d_align; 1159 od->d_off = id->d_off; 1160 od->d_buf = id->d_buf; 1161 od->d_type = id->d_type; 1162 od->d_size = id->d_size; 1163 od->d_version = id->d_version; 1164 } 1165 1166 /* 1167 * Alignment Fixup. libelf does not allow the alignment for 1168 * Elf_Data descriptor to be set to 0. In this case we workaround 1169 * it by setting the alignment to 1. 1170 * 1171 * According to the ELF ABI, alignment 0 and 1 has the same 1172 * meaning: the section has no alignment constraints. 1173 */ 1174 if (od->d_align == 0) 1175 od->d_align = 1; 1176 } 1177 1178 struct section * 1179 create_external_section(struct elfcopy *ecp, const char *name, char *newname, 1180 void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1181 uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1182 { 1183 struct section *s; 1184 Elf_Scn *os; 1185 Elf_Data *od; 1186 GElf_Shdr osh; 1187 1188 if ((os = elf_newscn(ecp->eout)) == NULL) 1189 errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1190 elf_errmsg(-1)); 1191 if ((s = calloc(1, sizeof(*s))) == NULL) 1192 err(EXIT_FAILURE, "calloc failed"); 1193 s->name = name; 1194 s->newname = newname; /* needs to be free()'ed */ 1195 s->off = off; 1196 s->sz = size; 1197 s->vma = vma; 1198 s->align = align; 1199 s->loadable = loadable; 1200 s->is = NULL; 1201 s->os = os; 1202 s->type = stype; 1203 s->nocopy = 1; 1204 insert_to_sec_list(ecp, s, 1); 1205 1206 if (gelf_getshdr(os, &osh) == NULL) 1207 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1208 elf_errmsg(-1)); 1209 osh.sh_flags = flags; 1210 osh.sh_type = s->type; 1211 osh.sh_addr = s->vma; 1212 osh.sh_addralign = s->align; 1213 if (!gelf_update_shdr(os, &osh)) 1214 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1215 elf_errmsg(-1)); 1216 add_to_shstrtab(ecp, name); 1217 1218 if (buf != NULL && size != 0) { 1219 if ((od = elf_newdata(os)) == NULL) 1220 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1221 elf_errmsg(-1)); 1222 od->d_align = align; 1223 od->d_off = 0; 1224 od->d_buf = buf; 1225 od->d_size = size; 1226 od->d_type = dtype; 1227 od->d_version = EV_CURRENT; 1228 } 1229 1230 /* 1231 * Clear SYMTAB_INTACT, as we probably need to update/add new 1232 * STT_SECTION symbols into the symbol table. 1233 */ 1234 ecp->flags &= ~SYMTAB_INTACT; 1235 1236 return (s); 1237 } 1238 1239 /* 1240 * Insert sections specified by --add-section to the end of section list. 1241 */ 1242 static void 1243 insert_sections(struct elfcopy *ecp) 1244 { 1245 struct sec_add *sa; 1246 struct section *s; 1247 size_t off; 1248 1249 /* Put these sections in the end of current list. */ 1250 off = 0; 1251 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1252 if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1253 off = s->off + s->sz; 1254 else 1255 off = s->off; 1256 } 1257 1258 STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1259 1260 /* TODO: Add section header vma/lma, flag changes here */ 1261 1262 (void) create_external_section(ecp, sa->name, NULL, sa->content, 1263 sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); 1264 } 1265 } 1266 1267 void 1268 add_to_shstrtab(struct elfcopy *ecp, const char *name) 1269 { 1270 struct section *s; 1271 1272 s = ecp->shstrtab; 1273 insert_to_strtab(s, name); 1274 } 1275 1276 void 1277 update_shdr(struct elfcopy *ecp, int update_link) 1278 { 1279 struct section *s; 1280 GElf_Shdr osh; 1281 int elferr; 1282 1283 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1284 if (s->pseudo) 1285 continue; 1286 1287 if (gelf_getshdr(s->os, &osh) == NULL) 1288 errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", 1289 elf_errmsg(-1)); 1290 1291 /* Find section name in string table and set sh_name. */ 1292 osh.sh_name = lookup_string(ecp->shstrtab, s->name); 1293 1294 /* 1295 * sh_link needs to be updated, since the index of the 1296 * linked section might have changed. 1297 */ 1298 if (update_link && osh.sh_link != 0) 1299 osh.sh_link = ecp->secndx[osh.sh_link]; 1300 1301 /* 1302 * sh_info of relocation section links to the section to which 1303 * its relocation info applies. So it may need update as well. 1304 */ 1305 if ((s->type == SHT_REL || s->type == SHT_RELA) && 1306 osh.sh_info != 0) 1307 osh.sh_info = ecp->secndx[osh.sh_info]; 1308 1309 /* 1310 * sh_info of SHT_GROUP section needs to point to the correct 1311 * string in the symbol table. 1312 */ 1313 if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) && 1314 (ecp->flags & SYMTAB_INTACT) == 0) 1315 osh.sh_info = ecp->symndx[osh.sh_info]; 1316 1317 if (!gelf_update_shdr(s->os, &osh)) 1318 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1319 elf_errmsg(-1)); 1320 } 1321 elferr = elf_errno(); 1322 if (elferr != 0) 1323 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1324 elf_errmsg(elferr)); 1325 } 1326 1327 void 1328 init_shstrtab(struct elfcopy *ecp) 1329 { 1330 struct section *s; 1331 1332 if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1333 err(EXIT_FAILURE, "calloc failed"); 1334 s = ecp->shstrtab; 1335 s->name = ".shstrtab"; 1336 s->is = NULL; 1337 s->sz = 0; 1338 s->align = 1; 1339 s->loadable = 0; 1340 s->type = SHT_STRTAB; 1341 s->vma = 0; 1342 1343 insert_to_strtab(s, ""); 1344 insert_to_strtab(s, ".symtab"); 1345 insert_to_strtab(s, ".strtab"); 1346 insert_to_strtab(s, ".shstrtab"); 1347 } 1348 1349 void 1350 set_shstrtab(struct elfcopy *ecp) 1351 { 1352 struct section *s; 1353 Elf_Data *data; 1354 GElf_Shdr sh; 1355 1356 s = ecp->shstrtab; 1357 1358 if (s->os == NULL) { 1359 /* Input object does not contain .shstrtab section */ 1360 if ((s->os = elf_newscn(ecp->eout)) == NULL) 1361 errx(EXIT_FAILURE, "elf_newscn failed: %s", 1362 elf_errmsg(-1)); 1363 insert_to_sec_list(ecp, s, 1); 1364 } 1365 1366 if (gelf_getshdr(s->os, &sh) == NULL) 1367 errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", 1368 elf_errmsg(-1)); 1369 sh.sh_addr = 0; 1370 sh.sh_addralign = 1; 1371 sh.sh_offset = s->off; 1372 sh.sh_type = SHT_STRTAB; 1373 sh.sh_flags = 0; 1374 sh.sh_entsize = 0; 1375 sh.sh_info = 0; 1376 sh.sh_link = 0; 1377 1378 if ((data = elf_newdata(s->os)) == NULL) 1379 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1380 elf_errmsg(-1)); 1381 1382 /* 1383 * If we don't have a symbol table, skip those a few bytes 1384 * which are reserved for this in the beginning of shstrtab. 1385 */ 1386 if (!(ecp->flags & SYMTAB_EXIST)) { 1387 s->sz -= sizeof(".symtab\0.strtab"); 1388 memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), 1389 s->sz); 1390 } 1391 1392 sh.sh_size = s->sz; 1393 if (!gelf_update_shdr(s->os, &sh)) 1394 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1395 elf_errmsg(-1)); 1396 1397 data->d_align = 1; 1398 data->d_buf = s->buf; 1399 data->d_size = s->sz; 1400 data->d_off = 0; 1401 data->d_type = ELF_T_BYTE; 1402 data->d_version = EV_CURRENT; 1403 1404 if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1405 errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1406 elf_errmsg(-1)); 1407 } 1408 1409 void 1410 add_section(struct elfcopy *ecp, const char *arg) 1411 { 1412 struct sec_add *sa; 1413 struct stat sb; 1414 const char *s, *fn; 1415 FILE *fp; 1416 int len; 1417 1418 if ((s = strchr(arg, '=')) == NULL) 1419 errx(EXIT_FAILURE, 1420 "illegal format for --add-section option"); 1421 if ((sa = malloc(sizeof(*sa))) == NULL) 1422 err(EXIT_FAILURE, "malloc failed"); 1423 1424 len = s - arg; 1425 if ((sa->name = malloc(len + 1)) == NULL) 1426 err(EXIT_FAILURE, "malloc failed"); 1427 strncpy(sa->name, arg, len); 1428 sa->name[len] = '\0'; 1429 1430 fn = s + 1; 1431 if (stat(fn, &sb) == -1) 1432 err(EXIT_FAILURE, "stat failed"); 1433 sa->size = sb.st_size; 1434 if ((sa->content = malloc(sa->size)) == NULL) 1435 err(EXIT_FAILURE, "malloc failed"); 1436 if ((fp = fopen(fn, "r")) == NULL) 1437 err(EXIT_FAILURE, "can not open %s", fn); 1438 if (fread(sa->content, 1, sa->size, fp) == 0 || 1439 ferror(fp)) 1440 err(EXIT_FAILURE, "fread failed"); 1441 fclose(fp); 1442 1443 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1444 ecp->flags |= SEC_ADD; 1445 } 1446 1447 void 1448 free_sec_add(struct elfcopy *ecp) 1449 { 1450 struct sec_add *sa, *sa_temp; 1451 1452 STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1453 STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1454 free(sa->name); 1455 free(sa->content); 1456 free(sa); 1457 } 1458 } 1459 1460 static void 1461 add_gnu_debuglink(struct elfcopy *ecp) 1462 { 1463 struct sec_add *sa; 1464 struct stat sb; 1465 FILE *fp; 1466 char *fnbase, *buf; 1467 int crc_off; 1468 int crc; 1469 1470 if (ecp->debuglink == NULL) 1471 return; 1472 1473 /* Read debug file content. */ 1474 if ((sa = malloc(sizeof(*sa))) == NULL) 1475 err(EXIT_FAILURE, "malloc failed"); 1476 if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1477 err(EXIT_FAILURE, "strdup failed"); 1478 if (stat(ecp->debuglink, &sb) == -1) 1479 err(EXIT_FAILURE, "stat failed"); 1480 if ((buf = malloc(sb.st_size)) == NULL) 1481 err(EXIT_FAILURE, "malloc failed"); 1482 if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1483 err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1484 if (fread(buf, 1, sb.st_size, fp) == 0 || 1485 ferror(fp)) 1486 err(EXIT_FAILURE, "fread failed"); 1487 fclose(fp); 1488 1489 /* Calculate crc checksum. */ 1490 crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1491 free(buf); 1492 1493 /* Calculate section size and the offset to store crc checksum. */ 1494 if ((fnbase = basename(ecp->debuglink)) == NULL) 1495 err(EXIT_FAILURE, "basename failed"); 1496 crc_off = roundup(strlen(fnbase) + 1, 4); 1497 sa->size = crc_off + 4; 1498 1499 /* Section content. */ 1500 if ((sa->content = calloc(1, sa->size)) == NULL) 1501 err(EXIT_FAILURE, "malloc failed"); 1502 strncpy(sa->content, fnbase, strlen(fnbase)); 1503 if (ecp->oed == ELFDATA2LSB) { 1504 sa->content[crc_off] = crc & 0xFF; 1505 sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1506 sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1507 sa->content[crc_off + 3] = crc >> 24; 1508 } else { 1509 sa->content[crc_off] = crc >> 24; 1510 sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1511 sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1512 sa->content[crc_off + 3] = crc & 0xFF; 1513 } 1514 1515 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1516 ecp->flags |= SEC_ADD; 1517 } 1518 1519 static void 1520 insert_to_strtab(struct section *t, const char *s) 1521 { 1522 const char *r; 1523 char *b, *c; 1524 size_t len, slen; 1525 int append; 1526 1527 if (t->sz == 0) { 1528 t->cap = 512; 1529 if ((t->buf = malloc(t->cap)) == NULL) 1530 err(EXIT_FAILURE, "malloc failed"); 1531 } 1532 1533 slen = strlen(s); 1534 append = 0; 1535 b = t->buf; 1536 for (c = b; c < b + t->sz;) { 1537 len = strlen(c); 1538 if (!append && len >= slen) { 1539 r = c + (len - slen); 1540 if (strcmp(r, s) == 0) 1541 return; 1542 } else if (len < slen && len != 0) { 1543 r = s + (slen - len); 1544 if (strcmp(c, r) == 0) { 1545 t->sz -= len + 1; 1546 memmove(c, c + len + 1, t->sz - (c - b)); 1547 append = 1; 1548 continue; 1549 } 1550 } 1551 c += len + 1; 1552 } 1553 1554 while (t->sz + slen + 1 >= t->cap) { 1555 t->cap *= 2; 1556 if ((t->buf = realloc(t->buf, t->cap)) == NULL) 1557 err(EXIT_FAILURE, "realloc failed"); 1558 } 1559 b = t->buf; 1560 strncpy(&b[t->sz], s, slen); 1561 b[t->sz + slen] = '\0'; 1562 t->sz += slen + 1; 1563 } 1564 1565 static int 1566 lookup_string(struct section *t, const char *s) 1567 { 1568 const char *b, *c, *r; 1569 size_t len, slen; 1570 1571 slen = strlen(s); 1572 b = t->buf; 1573 for (c = b; c < b + t->sz;) { 1574 len = strlen(c); 1575 if (len >= slen) { 1576 r = c + (len - slen); 1577 if (strcmp(r, s) == 0) 1578 return (r - b); 1579 } 1580 c += len + 1; 1581 } 1582 1583 return (-1); 1584 } 1585 1586 static uint32_t crctable[256] = 1587 { 1588 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1589 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1590 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1591 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1592 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1593 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1594 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1595 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1596 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1597 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1598 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1599 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1600 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1601 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1602 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1603 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1604 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1605 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1606 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1607 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1608 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1609 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1610 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1611 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1612 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1613 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1614 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1615 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1616 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1617 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1618 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1619 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1620 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1621 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1622 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1623 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1624 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1625 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1626 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1627 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1628 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1629 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1630 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1631 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1632 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1633 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1634 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1635 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1636 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1637 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1638 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1639 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1640 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1641 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1642 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1643 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1644 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1645 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1646 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1647 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1648 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1649 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1650 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1651 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1652 }; 1653 1654 static uint32_t 1655 calc_crc32(const char *p, size_t len, uint32_t crc) 1656 { 1657 uint32_t i; 1658 1659 for (i = 0; i < len; i++) { 1660 crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1661 } 1662 1663 return (crc ^ 0xFFFFFFFF); 1664 } 1665