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