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 (off <= s->off) { 781 if (!s->loadable) 782 s->off = roundup(off, s->align); 783 } else { 784 if (s->loadable) 785 warnx("moving loadable section %s, " 786 "is this intentional?", s->name); 787 s->off = roundup(off, s->align); 788 } 789 790 /* Calculate next section offset. */ 791 off = s->off; 792 if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 793 off += s->sz; 794 795 if (s->pseudo) { 796 ps = NULL; 797 continue; 798 } 799 800 /* Count padding bytes added through --pad-to. */ 801 if (s->pad_sz > 0) 802 off += s->pad_sz; 803 804 /* Update section header accordingly. */ 805 if (gelf_getshdr(s->os, &osh) == NULL) 806 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 807 elf_errmsg(-1)); 808 osh.sh_addr = s->vma; 809 osh.sh_offset = s->off; 810 osh.sh_size = s->sz; 811 if (!gelf_update_shdr(s->os, &osh)) 812 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 813 elf_errmsg(-1)); 814 815 /* Add padding for previous section, if need. */ 816 if (ps != NULL) { 817 if (ps->pad_sz > 0) { 818 /* Apply padding added by --pad-to. */ 819 pad_section(ecp, ps); 820 } else if ((ecp->flags & GAP_FILL) && 821 (ps->off + ps->sz < s->off)) { 822 /* 823 * Fill the gap between sections by padding 824 * the section with lower address. 825 */ 826 ps->pad_sz = s->off - (ps->off + ps->sz); 827 pad_section(ecp, ps); 828 } 829 } 830 831 ps = s; 832 } 833 834 /* Pad the last section, if need. */ 835 if (ps != NULL && ps->pad_sz > 0) 836 pad_section(ecp, ps); 837 } 838 839 static void 840 modify_section(struct elfcopy *ecp, struct section *s) 841 { 842 struct sec_action *sac; 843 size_t srcsz, dstsz, p, len; 844 char *b, *c, *d, *src, *end; 845 int dupe; 846 847 src = read_section(s, &srcsz); 848 if (src == NULL || srcsz == 0) { 849 /* For empty section, we proceed if we need to append. */ 850 if (!is_append_section(ecp, s->name)) 851 return; 852 } 853 854 /* Allocate buffer needed for new section data. */ 855 dstsz = srcsz; 856 if (is_append_section(ecp, s->name)) { 857 sac = lookup_sec_act(ecp, s->name, 0); 858 dstsz += strlen(sac->string) + 1; 859 } 860 if ((b = malloc(dstsz)) == NULL) 861 err(EXIT_FAILURE, "malloc failed"); 862 s->buf = b; 863 864 /* Compress section. */ 865 p = 0; 866 if (is_compress_section(ecp, s->name)) { 867 end = src + srcsz; 868 for(c = src; c < end;) { 869 len = 0; 870 while(c + len < end && c[len] != '\0') 871 len++; 872 if (c + len == end) { 873 /* XXX should we warn here? */ 874 strncpy(&b[p], c, len); 875 p += len; 876 break; 877 } 878 dupe = 0; 879 for (d = b; d < b + p; ) { 880 if (strcmp(d, c) == 0) { 881 dupe = 1; 882 break; 883 } 884 d += strlen(d) + 1; 885 } 886 if (!dupe) { 887 strncpy(&b[p], c, len); 888 b[p + len] = '\0'; 889 p += len + 1; 890 } 891 c += len + 1; 892 } 893 } else { 894 memcpy(b, src, srcsz); 895 p += srcsz; 896 } 897 898 /* Append section. */ 899 if (is_append_section(ecp, s->name)) { 900 sac = lookup_sec_act(ecp, s->name, 0); 901 len = strlen(sac->string); 902 strncpy(&b[p], sac->string, len); 903 b[p + len] = '\0'; 904 p += len + 1; 905 } 906 907 s->sz = p; 908 s->nocopy = 1; 909 } 910 911 static void 912 print_data(const char *d, size_t sz) 913 { 914 const char *c; 915 916 for (c = d; c < d + sz; c++) { 917 if (*c == '\0') 918 putchar('\n'); 919 else 920 putchar(*c); 921 } 922 } 923 924 static void 925 print_section(struct section *s) 926 { 927 Elf_Data *id; 928 int elferr; 929 930 if (s->buf != NULL && s->sz > 0) { 931 print_data(s->buf, s->sz); 932 } else { 933 id = NULL; 934 while ((id = elf_getdata(s->is, id)) != NULL) 935 print_data(id->d_buf, id->d_size); 936 elferr = elf_errno(); 937 if (elferr != 0) 938 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 939 elf_errmsg(elferr)); 940 } 941 putchar('\n'); 942 } 943 944 static void * 945 read_section(struct section *s, size_t *size) 946 { 947 Elf_Data *id; 948 char *b; 949 size_t sz; 950 int elferr; 951 952 sz = 0; 953 b = NULL; 954 id = NULL; 955 while ((id = elf_getdata(s->is, id)) != NULL) { 956 if (b == NULL) 957 b = malloc(id->d_size); 958 else 959 b = malloc(sz + id->d_size); 960 if (b == NULL) 961 err(EXIT_FAILURE, "malloc or realloc failed"); 962 963 memcpy(&b[sz], id->d_buf, id->d_size); 964 sz += id->d_size; 965 } 966 elferr = elf_errno(); 967 if (elferr != 0) 968 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 969 elf_errmsg(elferr)); 970 971 *size = sz; 972 973 return (b); 974 } 975 976 void 977 copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 978 int sec_flags) 979 { 980 GElf_Shdr ish, osh; 981 982 if (gelf_getshdr(s->is, &ish) == NULL) 983 errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", 984 elf_errmsg(-1)); 985 if (gelf_getshdr(s->os, &osh) == NULL) 986 errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", 987 elf_errmsg(-1)); 988 989 if (copy) 990 (void) memcpy(&osh, &ish, sizeof(ish)); 991 else { 992 osh.sh_type = s->type; 993 osh.sh_addr = s->vma; 994 osh.sh_offset = s->off; 995 osh.sh_size = s->sz; 996 osh.sh_link = ish.sh_link; 997 osh.sh_info = ish.sh_info; 998 osh.sh_addralign = s->align; 999 osh.sh_entsize = ish.sh_entsize; 1000 1001 if (sec_flags) { 1002 osh.sh_flags = 0; 1003 if (sec_flags & SF_ALLOC) { 1004 osh.sh_flags |= SHF_ALLOC; 1005 if (!s->loadable) 1006 warnx("set SHF_ALLOC flag for " 1007 "unloadable section %s", 1008 s->name); 1009 } 1010 if ((sec_flags & SF_READONLY) == 0) 1011 osh.sh_flags |= SHF_WRITE; 1012 if (sec_flags & SF_CODE) 1013 osh.sh_flags |= SHF_EXECINSTR; 1014 } else 1015 osh.sh_flags = ish.sh_flags; 1016 } 1017 1018 if (name == NULL) 1019 add_to_shstrtab(ecp, s->name); 1020 else 1021 add_to_shstrtab(ecp, name); 1022 1023 if (!gelf_update_shdr(s->os, &osh)) 1024 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1025 elf_errmsg(-1)); 1026 } 1027 1028 void 1029 copy_data(struct section *s) 1030 { 1031 Elf_Data *id, *od; 1032 int elferr; 1033 1034 if (s->nocopy && s->buf == NULL) 1035 return; 1036 1037 if ((id = elf_getdata(s->is, NULL)) == NULL) { 1038 elferr = elf_errno(); 1039 if (elferr != 0) 1040 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1041 elf_errmsg(elferr)); 1042 return; 1043 } 1044 1045 if ((od = elf_newdata(s->os)) == NULL) 1046 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1047 elf_errmsg(-1)); 1048 1049 if (s->nocopy) { 1050 /* Use s->buf as content if s->nocopy is set. */ 1051 od->d_align = id->d_align; 1052 od->d_off = 0; 1053 od->d_buf = s->buf; 1054 od->d_type = id->d_type; 1055 od->d_size = s->sz; 1056 od->d_version = id->d_version; 1057 } else { 1058 od->d_align = id->d_align; 1059 od->d_off = id->d_off; 1060 od->d_buf = id->d_buf; 1061 od->d_type = id->d_type; 1062 od->d_size = id->d_size; 1063 od->d_version = id->d_version; 1064 } 1065 1066 /* 1067 * Alignment Fixup. libelf does not allow the alignment for 1068 * Elf_Data descriptor to be set to 0. In this case we workaround 1069 * it by setting the alignment to 1. 1070 * 1071 * According to the ELF ABI, alignment 0 and 1 has the same 1072 * meaning: the section has no alignment constraints. 1073 */ 1074 if (od->d_align == 0) 1075 od->d_align = 1; 1076 } 1077 1078 struct section * 1079 create_external_section(struct elfcopy *ecp, const char *name, char *newname, 1080 void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1081 uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1082 { 1083 struct section *s; 1084 Elf_Scn *os; 1085 Elf_Data *od; 1086 GElf_Shdr osh; 1087 1088 if ((os = elf_newscn(ecp->eout)) == NULL) 1089 errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1090 elf_errmsg(-1)); 1091 if ((s = calloc(1, sizeof(*s))) == NULL) 1092 err(EXIT_FAILURE, "calloc failed"); 1093 s->name = name; 1094 s->newname = newname; /* needs to be free()'ed */ 1095 s->off = off; 1096 s->sz = size; 1097 s->vma = vma; 1098 s->align = align; 1099 s->loadable = loadable; 1100 s->is = NULL; 1101 s->os = os; 1102 s->type = stype; 1103 s->nocopy = 1; 1104 insert_to_sec_list(ecp, s, 1); 1105 1106 if (gelf_getshdr(os, &osh) == NULL) 1107 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1108 elf_errmsg(-1)); 1109 osh.sh_flags = flags; 1110 osh.sh_type = s->type; 1111 osh.sh_addr = s->vma; 1112 osh.sh_addralign = s->align; 1113 if (!gelf_update_shdr(os, &osh)) 1114 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1115 elf_errmsg(-1)); 1116 add_to_shstrtab(ecp, name); 1117 1118 if (buf != NULL && size != 0) { 1119 if ((od = elf_newdata(os)) == NULL) 1120 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1121 elf_errmsg(-1)); 1122 od->d_align = align; 1123 od->d_off = 0; 1124 od->d_buf = buf; 1125 od->d_size = size; 1126 od->d_type = dtype; 1127 od->d_version = EV_CURRENT; 1128 } 1129 1130 /* 1131 * Clear SYMTAB_INTACT, as we probably need to update/add new 1132 * STT_SECTION symbols into the symbol table. 1133 */ 1134 ecp->flags &= ~SYMTAB_INTACT; 1135 1136 return (s); 1137 } 1138 1139 /* 1140 * Insert sections specified by --add-section to the end of section list. 1141 */ 1142 static void 1143 insert_sections(struct elfcopy *ecp) 1144 { 1145 struct sec_add *sa; 1146 struct section *s; 1147 size_t off; 1148 1149 /* Put these sections in the end of current list. */ 1150 off = 0; 1151 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1152 if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1153 off = s->off + s->sz; 1154 else 1155 off = s->off; 1156 } 1157 1158 STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1159 1160 /* TODO: Add section header vma/lma, flag changes here */ 1161 1162 (void) create_external_section(ecp, sa->name, NULL, sa->content, 1163 sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); 1164 } 1165 } 1166 1167 void 1168 add_to_shstrtab(struct elfcopy *ecp, const char *name) 1169 { 1170 struct section *s; 1171 1172 s = ecp->shstrtab; 1173 insert_to_strtab(s, name); 1174 } 1175 1176 void 1177 update_shdr(struct elfcopy *ecp, int update_link) 1178 { 1179 struct section *s; 1180 GElf_Shdr osh; 1181 int elferr; 1182 1183 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1184 if (s->pseudo) 1185 continue; 1186 1187 if (gelf_getshdr(s->os, &osh) == NULL) 1188 errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", 1189 elf_errmsg(-1)); 1190 1191 /* Find section name in string table and set sh_name. */ 1192 osh.sh_name = lookup_string(ecp->shstrtab, s->name); 1193 1194 /* 1195 * sh_link needs to be updated, since the index of the 1196 * linked section might have changed. 1197 */ 1198 if (update_link && osh.sh_link != 0) 1199 osh.sh_link = ecp->secndx[osh.sh_link]; 1200 1201 /* 1202 * sh_info of relocation section links to the section to which 1203 * its relocation info applies. So it may need update as well. 1204 */ 1205 if ((s->type == SHT_REL || s->type == SHT_RELA) && 1206 osh.sh_info != 0) 1207 osh.sh_info = ecp->secndx[osh.sh_info]; 1208 1209 if (!gelf_update_shdr(s->os, &osh)) 1210 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1211 elf_errmsg(-1)); 1212 } 1213 elferr = elf_errno(); 1214 if (elferr != 0) 1215 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1216 elf_errmsg(elferr)); 1217 } 1218 1219 void 1220 init_shstrtab(struct elfcopy *ecp) 1221 { 1222 struct section *s; 1223 1224 if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1225 err(EXIT_FAILURE, "calloc failed"); 1226 s = ecp->shstrtab; 1227 s->name = ".shstrtab"; 1228 s->is = NULL; 1229 s->sz = 0; 1230 s->align = 1; 1231 s->loadable = 0; 1232 s->type = SHT_STRTAB; 1233 s->vma = 0; 1234 1235 insert_to_strtab(s, ""); 1236 insert_to_strtab(s, ".symtab"); 1237 insert_to_strtab(s, ".strtab"); 1238 insert_to_strtab(s, ".shstrtab"); 1239 } 1240 1241 void 1242 set_shstrtab(struct elfcopy *ecp) 1243 { 1244 struct section *s; 1245 Elf_Data *data; 1246 GElf_Shdr sh; 1247 1248 s = ecp->shstrtab; 1249 1250 if (gelf_getshdr(s->os, &sh) == NULL) 1251 errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", 1252 elf_errmsg(-1)); 1253 sh.sh_addr = 0; 1254 sh.sh_addralign = 1; 1255 sh.sh_offset = s->off; 1256 sh.sh_type = SHT_STRTAB; 1257 sh.sh_flags = 0; 1258 sh.sh_entsize = 0; 1259 sh.sh_info = 0; 1260 sh.sh_link = 0; 1261 1262 if ((data = elf_newdata(s->os)) == NULL) 1263 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1264 elf_errmsg(-1)); 1265 1266 /* 1267 * If we don't have a symbol table, skip those a few bytes 1268 * which are reserved for this in the beginning of shstrtab. 1269 */ 1270 if (!(ecp->flags & SYMTAB_EXIST)) { 1271 s->sz -= sizeof(".symtab\0.strtab"); 1272 memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), 1273 s->sz); 1274 } 1275 1276 sh.sh_size = s->sz; 1277 if (!gelf_update_shdr(s->os, &sh)) 1278 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1279 elf_errmsg(-1)); 1280 1281 data->d_align = 1; 1282 data->d_buf = s->buf; 1283 data->d_size = s->sz; 1284 data->d_off = 0; 1285 data->d_type = ELF_T_BYTE; 1286 data->d_version = EV_CURRENT; 1287 1288 if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1289 errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1290 elf_errmsg(-1)); 1291 } 1292 1293 void 1294 add_section(struct elfcopy *ecp, const char *arg) 1295 { 1296 struct sec_add *sa; 1297 struct stat sb; 1298 const char *s, *fn; 1299 FILE *fp; 1300 int len; 1301 1302 if ((s = strchr(arg, '=')) == NULL) 1303 errx(EXIT_FAILURE, 1304 "illegal format for --add-section option"); 1305 if ((sa = malloc(sizeof(*sa))) == NULL) 1306 err(EXIT_FAILURE, "malloc failed"); 1307 1308 len = s - arg; 1309 if ((sa->name = malloc(len + 1)) == NULL) 1310 err(EXIT_FAILURE, "malloc failed"); 1311 strncpy(sa->name, arg, len); 1312 sa->name[len] = '\0'; 1313 1314 fn = s + 1; 1315 if (stat(fn, &sb) == -1) 1316 err(EXIT_FAILURE, "stat failed"); 1317 sa->size = sb.st_size; 1318 if ((sa->content = malloc(sa->size)) == NULL) 1319 err(EXIT_FAILURE, "malloc failed"); 1320 if ((fp = fopen(fn, "r")) == NULL) 1321 err(EXIT_FAILURE, "can not open %s", fn); 1322 if (fread(sa->content, 1, sa->size, fp) == 0 || 1323 ferror(fp)) 1324 err(EXIT_FAILURE, "fread failed"); 1325 fclose(fp); 1326 1327 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1328 ecp->flags |= SEC_ADD; 1329 } 1330 1331 void 1332 free_sec_add(struct elfcopy *ecp) 1333 { 1334 struct sec_add *sa, *sa_temp; 1335 1336 STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1337 STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1338 free(sa->name); 1339 free(sa->content); 1340 free(sa); 1341 } 1342 } 1343 1344 static void 1345 add_gnu_debuglink(struct elfcopy *ecp) 1346 { 1347 struct sec_add *sa; 1348 struct stat sb; 1349 FILE *fp; 1350 char *fnbase, *buf; 1351 int crc_off; 1352 int crc; 1353 1354 if (ecp->debuglink == NULL) 1355 return; 1356 1357 /* Read debug file content. */ 1358 if ((sa = malloc(sizeof(*sa))) == NULL) 1359 err(EXIT_FAILURE, "malloc failed"); 1360 if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1361 err(EXIT_FAILURE, "strdup failed"); 1362 if (stat(ecp->debuglink, &sb) == -1) 1363 err(EXIT_FAILURE, "stat failed"); 1364 if ((buf = malloc(sb.st_size)) == NULL) 1365 err(EXIT_FAILURE, "malloc failed"); 1366 if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1367 err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1368 if (fread(buf, 1, sb.st_size, fp) == 0 || 1369 ferror(fp)) 1370 err(EXIT_FAILURE, "fread failed"); 1371 fclose(fp); 1372 1373 /* Calculate crc checksum. */ 1374 crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1375 free(buf); 1376 1377 /* Calculate section size and the offset to store crc checksum. */ 1378 if ((fnbase = basename(ecp->debuglink)) == NULL) 1379 err(EXIT_FAILURE, "basename failed"); 1380 crc_off = roundup(strlen(fnbase) + 1, 4); 1381 sa->size = crc_off + 4; 1382 1383 /* Section content. */ 1384 if ((sa->content = calloc(1, sa->size)) == NULL) 1385 err(EXIT_FAILURE, "malloc failed"); 1386 strncpy(sa->content, fnbase, strlen(fnbase)); 1387 if (ecp->oed == ELFDATA2LSB) { 1388 sa->content[crc_off] = crc & 0xFF; 1389 sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1390 sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1391 sa->content[crc_off + 3] = crc >> 24; 1392 } else { 1393 sa->content[crc_off] = crc >> 24; 1394 sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1395 sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1396 sa->content[crc_off + 3] = crc & 0xFF; 1397 } 1398 1399 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1400 ecp->flags |= SEC_ADD; 1401 } 1402 1403 static void 1404 insert_to_strtab(struct section *t, const char *s) 1405 { 1406 const char *r; 1407 char *b, *c; 1408 size_t len, slen; 1409 int append; 1410 1411 if (t->sz == 0) { 1412 t->cap = 512; 1413 if ((t->buf = malloc(t->cap)) == NULL) 1414 err(EXIT_FAILURE, "malloc failed"); 1415 } 1416 1417 slen = strlen(s); 1418 append = 0; 1419 b = t->buf; 1420 for (c = b; c < b + t->sz;) { 1421 len = strlen(c); 1422 if (!append && len >= slen) { 1423 r = c + (len - slen); 1424 if (strcmp(r, s) == 0) 1425 return; 1426 } else if (len < slen && len != 0) { 1427 r = s + (slen - len); 1428 if (strcmp(c, r) == 0) { 1429 t->sz -= len + 1; 1430 memmove(c, c + len + 1, t->sz - (c - b)); 1431 append = 1; 1432 continue; 1433 } 1434 } 1435 c += len + 1; 1436 } 1437 1438 while (t->sz + slen + 1 >= t->cap) { 1439 t->cap *= 2; 1440 if ((t->buf = realloc(t->buf, t->cap)) == NULL) 1441 err(EXIT_FAILURE, "realloc failed"); 1442 } 1443 b = t->buf; 1444 strncpy(&b[t->sz], s, slen); 1445 b[t->sz + slen] = '\0'; 1446 t->sz += slen + 1; 1447 } 1448 1449 static int 1450 lookup_string(struct section *t, const char *s) 1451 { 1452 const char *b, *c, *r; 1453 size_t len, slen; 1454 1455 slen = strlen(s); 1456 b = t->buf; 1457 for (c = b; c < b + t->sz;) { 1458 len = strlen(c); 1459 if (len >= slen) { 1460 r = c + (len - slen); 1461 if (strcmp(r, s) == 0) 1462 return (r - b); 1463 } 1464 c += len + 1; 1465 } 1466 1467 return (-1); 1468 } 1469 1470 static uint32_t crctable[256] = 1471 { 1472 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1473 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1474 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1475 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1476 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1477 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1478 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1479 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1480 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1481 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1482 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1483 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1484 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1485 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1486 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1487 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1488 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1489 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1490 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1491 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1492 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1493 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1494 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1495 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1496 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1497 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1498 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1499 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1500 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1501 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1502 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1503 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1504 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1505 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1506 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1507 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1508 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1509 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1510 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1511 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1512 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1513 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1514 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1515 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1516 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1517 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1518 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1519 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1520 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1521 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1522 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1523 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1524 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1525 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1526 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1527 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1528 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1529 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1530 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1531 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1532 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1533 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1534 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1535 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1536 }; 1537 1538 static uint32_t 1539 calc_crc32(const char *p, size_t len, uint32_t crc) 1540 { 1541 uint32_t i; 1542 1543 for (i = 0; i < len; i++) { 1544 crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1545 } 1546 1547 return (crc ^ 0xFFFFFFFF); 1548 } 1549