1 /*- 2 * Copyright (c) 2007-2011 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 2358 2011-12-19 18:22:32Z 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 /* Get section flags set by user. */ 376 sec_flags = get_section_flags(ecp, name); 377 378 /* Create internal section object. */ 379 if (strcmp(name, ".shstrtab") != 0) { 380 if ((s = calloc(1, sizeof(*s))) == NULL) 381 err(EXIT_FAILURE, "calloc failed"); 382 s->name = name; 383 s->is = is; 384 s->off = ish.sh_offset; 385 s->sz = ish.sh_size; 386 s->align = ish.sh_addralign; 387 s->type = ish.sh_type; 388 s->vma = ish.sh_addr; 389 390 /* 391 * Search program headers to determine whether section 392 * is loadable, but if user explicitly set section flags 393 * while neither "load" nor "alloc" is set, we make the 394 * section unloadable. 395 */ 396 if (sec_flags && 397 (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) 398 s->loadable = 0; 399 else 400 s->loadable = add_to_inseg_list(ecp, s); 401 } else { 402 /* Assuming .shstrtab is "unloadable". */ 403 s = ecp->shstrtab; 404 s->off = ish.sh_offset; 405 } 406 407 oldndx = newndx = SHN_UNDEF; 408 if (strcmp(name, ".symtab") != 0 && 409 strcmp(name, ".strtab") != 0) { 410 if (!strcmp(name, ".shstrtab")) { 411 /* 412 * Add sections specified by --add-section and 413 * gnu debuglink. we want these sections have 414 * smaller index than .shstrtab section. 415 */ 416 if (ecp->debuglink != NULL) 417 add_gnu_debuglink(ecp); 418 if (ecp->flags & SEC_ADD) 419 insert_sections(ecp); 420 } 421 if ((s->os = elf_newscn(ecp->eout)) == NULL) 422 errx(EXIT_FAILURE, "elf_newscn failed: %s", 423 elf_errmsg(-1)); 424 if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) 425 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 426 elf_errmsg(-1)); 427 } 428 if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) 429 errx(EXIT_FAILURE, "elf_ndxscn failed: %s", 430 elf_errmsg(-1)); 431 if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) 432 ecp->secndx[oldndx] = newndx; 433 434 /* 435 * If strip action is STRIP_NONDEBUG(only keep debug), 436 * change sections flags of loadable sections to SHF_NOBITS, 437 * and the content of those sections will be ignored. 438 */ 439 if (ecp->strip == STRIP_NONDEBUG && (ish.sh_flags & SHF_ALLOC)) 440 s->type = SHT_NOBITS; 441 442 check_section_rename(ecp, s); 443 444 /* create section header based on input object. */ 445 if (strcmp(name, ".symtab") != 0 && 446 strcmp(name, ".strtab") != 0 && 447 strcmp(name, ".shstrtab") != 0) 448 copy_shdr(ecp, s, NULL, 0, sec_flags); 449 450 if (strcmp(name, ".symtab") == 0) { 451 ecp->flags |= SYMTAB_EXIST; 452 ecp->symtab = s; 453 } 454 if (strcmp(name, ".strtab") == 0) 455 ecp->strtab = s; 456 457 insert_to_sec_list(ecp, s, 0); 458 } 459 elferr = elf_errno(); 460 if (elferr != 0) 461 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 462 elf_errmsg(elferr)); 463 } 464 465 struct section * 466 insert_shtab(struct elfcopy *ecp, int tail) 467 { 468 struct section *s, *shtab; 469 GElf_Ehdr ieh; 470 int nsecs; 471 472 /* 473 * Treat section header table as a "pseudo" section, insert it 474 * into section list, so later it will get sorted and resynced 475 * just as normal sections. 476 */ 477 if ((shtab = calloc(1, sizeof(*shtab))) == NULL) 478 errx(EXIT_FAILURE, "calloc failed"); 479 if (!tail) { 480 /* shoff of input object is used as a hint. */ 481 if (gelf_getehdr(ecp->ein, &ieh) == NULL) 482 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 483 elf_errmsg(-1)); 484 shtab->off = ieh.e_shoff; 485 } else 486 shtab->off = 0; 487 /* Calculate number of sections in the output object. */ 488 nsecs = 0; 489 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 490 if (!s->pseudo) 491 nsecs++; 492 } 493 /* Remember there is always a null section, so we +1 here. */ 494 shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); 495 if (shtab->sz == 0) 496 errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); 497 shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); 498 shtab->loadable = 0; 499 shtab->pseudo = 1; 500 insert_to_sec_list(ecp, shtab, tail); 501 502 return (shtab); 503 } 504 505 void 506 copy_content(struct elfcopy *ecp) 507 { 508 struct section *s; 509 510 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 511 /* Skip pseudo section. */ 512 if (s->pseudo) 513 continue; 514 515 /* Skip special sections. */ 516 if (strcmp(s->name, ".symtab") == 0 || 517 strcmp(s->name, ".strtab") == 0 || 518 strcmp(s->name, ".shstrtab") == 0) 519 continue; 520 521 /* 522 * If strip action is STRIP_ALL, relocation info need 523 * to be stripped. Skip filtering otherwisw. 524 */ 525 if (ecp->strip == STRIP_ALL && 526 (s->type == SHT_REL || s->type == SHT_RELA)) 527 filter_reloc(ecp, s); 528 529 if (is_modify_section(ecp, s->name)) 530 modify_section(ecp, s); 531 532 copy_data(s); 533 534 /* 535 * If symbol table is modified, relocation info might 536 * need update, as symbol index may have changed. 537 */ 538 if ((ecp->flags & SYMTAB_INTACT) == 0 && 539 (ecp->flags & SYMTAB_EXIST) && 540 (s->type == SHT_REL || s->type == SHT_RELA)) 541 update_reloc(ecp, s); 542 543 if (is_print_section(ecp, s->name)) 544 print_section(s); 545 } 546 } 547 548 /* 549 * Filter relocation entries, only keep those entries whose 550 * symbol is in the keep list. 551 */ 552 static void 553 filter_reloc(struct elfcopy *ecp, struct section *s) 554 { 555 const char *name; 556 GElf_Shdr ish; 557 GElf_Rel rel; 558 GElf_Rela rela; 559 Elf32_Rel *rel32; 560 Elf64_Rel *rel64; 561 Elf32_Rela *rela32; 562 Elf64_Rela *rela64; 563 Elf_Data *id; 564 uint64_t cap, n, nrels; 565 int elferr, i; 566 567 if (gelf_getshdr(s->is, &ish) == NULL) 568 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 569 elf_errmsg(-1)); 570 571 /* We don't want to touch relocation info for dynamic symbols. */ 572 if ((ecp->flags & SYMTAB_EXIST) == 0) { 573 if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) { 574 /* 575 * This reloc section applies to the symbol table 576 * that was stripped, so discard whole section. 577 */ 578 s->nocopy = 1; 579 s->sz = 0; 580 } 581 return; 582 } else { 583 /* Symbol table exist, check if index equals. */ 584 if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) 585 return; 586 } 587 588 #define COPYREL(REL, SZ) do { \ 589 if (nrels == 0) { \ 590 if ((REL##SZ = malloc(cap * \ 591 sizeof(Elf##SZ##_Rel))) == NULL) \ 592 err(EXIT_FAILURE, "malloc failed"); \ 593 } \ 594 if (nrels >= cap) { \ 595 cap *= 2; \ 596 if ((REL##SZ = realloc(REL##SZ, cap * \ 597 sizeof(Elf##SZ##_Rel))) == NULL) \ 598 err(EXIT_FAILURE, "realloc failed"); \ 599 } \ 600 REL##SZ[nrels].r_offset = REL.r_offset; \ 601 REL##SZ[nrels].r_info = REL.r_info; \ 602 if (s->type == SHT_RELA) \ 603 rela##SZ[nrels].r_addend = rela.r_addend; \ 604 nrels++; \ 605 } while (0) 606 607 nrels = 0; 608 cap = 4; /* keep list is usually small. */ 609 rel32 = NULL; 610 rel64 = NULL; 611 rela32 = NULL; 612 rela64 = NULL; 613 if ((id = elf_getdata(s->is, NULL)) == NULL) 614 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 615 elf_errmsg(-1)); 616 n = ish.sh_size / ish.sh_entsize; 617 for(i = 0; (uint64_t)i < n; i++) { 618 if (s->type == SHT_REL) { 619 if (gelf_getrel(id, i, &rel) != &rel) 620 errx(EXIT_FAILURE, "gelf_getrel failed: %s", 621 elf_errmsg(-1)); 622 } else { 623 if (gelf_getrela(id, i, &rela) != &rela) 624 errx(EXIT_FAILURE, "gelf_getrel failed: %s", 625 elf_errmsg(-1)); 626 } 627 name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), 628 GELF_R_SYM(rel.r_info)); 629 if (name == NULL) 630 errx(EXIT_FAILURE, "elf_strptr failed: %s", 631 elf_errmsg(-1)); 632 if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) { 633 if (ecp->oec == ELFCLASS32) { 634 if (s->type == SHT_REL) 635 COPYREL(rel, 32); 636 else 637 COPYREL(rela, 32); 638 } else { 639 if (s->type == SHT_REL) 640 COPYREL(rel, 64); 641 else 642 COPYREL(rela, 64); 643 } 644 } 645 } 646 elferr = elf_errno(); 647 if (elferr != 0) 648 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 649 elf_errmsg(elferr)); 650 651 if (ecp->oec == ELFCLASS32) { 652 if (s->type == SHT_REL) 653 s->buf = rel32; 654 else 655 s->buf = rela32; 656 } else { 657 if (s->type == SHT_REL) 658 s->buf = rel64; 659 else 660 s->buf = rela64; 661 } 662 s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : 663 ELF_T_RELA), nrels, EV_CURRENT); 664 s->nocopy = 1; 665 } 666 667 static void 668 update_reloc(struct elfcopy *ecp, struct section *s) 669 { 670 GElf_Shdr osh; 671 GElf_Rel rel; 672 GElf_Rela rela; 673 Elf_Data *od; 674 uint64_t n; 675 int i; 676 677 #define UPDATEREL(REL) do { \ 678 if (gelf_get##REL(od, i, &REL) != &REL) \ 679 errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ 680 elf_errmsg(-1)); \ 681 REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ 682 GELF_R_TYPE(REL.r_info)); \ 683 if (!gelf_update_##REL(od, i, &REL)) \ 684 errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ 685 elf_errmsg(-1)); \ 686 } while(0) 687 688 if (s->sz == 0) 689 return; 690 if (gelf_getshdr(s->os, &osh) == NULL) 691 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", 692 elf_errmsg(-1)); 693 /* Only process .symtab reloc info. */ 694 if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) 695 return; 696 if ((od = elf_getdata(s->os, NULL)) == NULL) 697 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 698 elf_errmsg(-1)); 699 n = osh.sh_size / osh.sh_entsize; 700 for(i = 0; (uint64_t)i < n; i++) { 701 if (s->type == SHT_REL) 702 UPDATEREL(rel); 703 else 704 UPDATEREL(rela); 705 } 706 } 707 708 static void 709 pad_section(struct elfcopy *ecp, struct section *s) 710 { 711 GElf_Shdr osh; 712 Elf_Data *od; 713 714 if (s == NULL || s->pad_sz == 0) 715 return; 716 717 if ((s->pad = malloc(s->pad_sz)) == NULL) 718 err(EXIT_FAILURE, "malloc failed"); 719 memset(s->pad, ecp->fill, s->pad_sz); 720 721 /* Create a new Elf_Data to contain the padding bytes. */ 722 if ((od = elf_newdata(s->os)) == NULL) 723 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 724 elf_errmsg(-1)); 725 od->d_align = 1; 726 od->d_off = s->sz; 727 od->d_buf = s->pad; 728 od->d_type = ELF_T_BYTE; 729 od->d_size = s->pad_sz; 730 od->d_version = EV_CURRENT; 731 732 /* Update section header. */ 733 if (gelf_getshdr(s->os, &osh) == NULL) 734 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 735 elf_errmsg(-1)); 736 osh.sh_size = s->sz + s->pad_sz; 737 if (!gelf_update_shdr(s->os, &osh)) 738 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 739 elf_errmsg(-1)); 740 } 741 742 void 743 resync_sections(struct elfcopy *ecp) 744 { 745 struct section *s, *ps; 746 GElf_Shdr osh; 747 uint64_t off; 748 int first; 749 750 ps = NULL; 751 first = 1; 752 off = 0; 753 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 754 if (first) { 755 off = s->off; 756 first = 0; 757 } 758 759 /* Align section offset. */ 760 if (off <= s->off) { 761 if (!s->loadable) 762 s->off = roundup(off, s->align); 763 } else { 764 if (s->loadable) 765 warnx("moving loadable section," 766 "is this intentional?"); 767 s->off = roundup(off, s->align); 768 } 769 770 /* Calculate next section offset. */ 771 off = s->off; 772 if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) 773 off += s->sz; 774 775 if (s->pseudo) { 776 ps = NULL; 777 continue; 778 } 779 780 /* Count padding bytes added through --pad-to. */ 781 if (s->pad_sz > 0) 782 off += s->pad_sz; 783 784 /* Update section header accordingly. */ 785 if (gelf_getshdr(s->os, &osh) == NULL) 786 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 787 elf_errmsg(-1)); 788 osh.sh_addr = s->vma; 789 osh.sh_offset = s->off; 790 osh.sh_size = s->sz; 791 if (!gelf_update_shdr(s->os, &osh)) 792 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 793 elf_errmsg(-1)); 794 795 /* Add padding for previous section, if need. */ 796 if (ps != NULL) { 797 if (ps->pad_sz > 0) { 798 /* Apply padding added by --pad-to. */ 799 pad_section(ecp, ps); 800 } else if ((ecp->flags & GAP_FILL) && 801 (ps->off + ps->sz < s->off)) { 802 /* 803 * Fill the gap between sections by padding 804 * the section with lower address. 805 */ 806 ps->pad_sz = s->off - (ps->off + ps->sz); 807 pad_section(ecp, ps); 808 } 809 } 810 811 ps = s; 812 } 813 814 /* Pad the last section, if need. */ 815 if (ps != NULL && ps->pad_sz > 0) 816 pad_section(ecp, ps); 817 } 818 819 static void 820 modify_section(struct elfcopy *ecp, struct section *s) 821 { 822 struct sec_action *sac; 823 size_t srcsz, dstsz, p, len; 824 char *b, *c, *d, *src, *end; 825 int dupe; 826 827 src = read_section(s, &srcsz); 828 if (src == NULL || srcsz == 0) { 829 /* For empty section, we proceed if we need to append. */ 830 if (!is_append_section(ecp, s->name)) 831 return; 832 } 833 834 /* Allocate buffer needed for new section data. */ 835 dstsz = srcsz; 836 if (is_append_section(ecp, s->name)) { 837 sac = lookup_sec_act(ecp, s->name, 0); 838 dstsz += strlen(sac->string) + 1; 839 } 840 if ((b = malloc(dstsz)) == NULL) 841 err(EXIT_FAILURE, "malloc failed"); 842 s->buf = b; 843 844 /* Compress section. */ 845 p = 0; 846 if (is_compress_section(ecp, s->name)) { 847 end = src + srcsz; 848 for(c = src; c < end;) { 849 len = 0; 850 while(c + len < end && c[len] != '\0') 851 len++; 852 if (c + len == end) { 853 /* XXX should we warn here? */ 854 strncpy(&b[p], c, len); 855 p += len; 856 break; 857 } 858 dupe = 0; 859 for (d = b; d < b + p; ) { 860 if (strcmp(d, c) == 0) { 861 dupe = 1; 862 break; 863 } 864 d += strlen(d) + 1; 865 } 866 if (!dupe) { 867 strncpy(&b[p], c, len); 868 b[p + len] = '\0'; 869 p += len + 1; 870 } 871 c += len + 1; 872 } 873 } else { 874 memcpy(b, src, srcsz); 875 p += srcsz; 876 } 877 878 /* Append section. */ 879 if (is_append_section(ecp, s->name)) { 880 sac = lookup_sec_act(ecp, s->name, 0); 881 len = strlen(sac->string); 882 strncpy(&b[p], sac->string, len); 883 b[p + len] = '\0'; 884 p += len + 1; 885 } 886 887 s->sz = p; 888 s->nocopy = 1; 889 } 890 891 static void 892 print_data(const char *d, size_t sz) 893 { 894 const char *c; 895 896 for (c = d; c < d + sz; c++) { 897 if (*c == '\0') 898 putchar('\n'); 899 else 900 putchar(*c); 901 } 902 } 903 904 static void 905 print_section(struct section *s) 906 { 907 Elf_Data *id; 908 int elferr; 909 910 if (s->buf != NULL && s->sz > 0) { 911 print_data(s->buf, s->sz); 912 } else { 913 id = NULL; 914 while ((id = elf_getdata(s->is, id)) != NULL) 915 print_data(id->d_buf, id->d_size); 916 elferr = elf_errno(); 917 if (elferr != 0) 918 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 919 elf_errmsg(elferr)); 920 } 921 putchar('\n'); 922 } 923 924 static void * 925 read_section(struct section *s, size_t *size) 926 { 927 Elf_Data *id; 928 char *b; 929 size_t sz; 930 int elferr; 931 932 sz = 0; 933 b = NULL; 934 id = NULL; 935 while ((id = elf_getdata(s->is, id)) != NULL) { 936 if (b == NULL) 937 b = malloc(id->d_size); 938 else 939 b = malloc(sz + id->d_size); 940 if (b == NULL) 941 err(EXIT_FAILURE, "malloc or realloc failed"); 942 943 memcpy(&b[sz], id->d_buf, id->d_size); 944 sz += id->d_size; 945 } 946 elferr = elf_errno(); 947 if (elferr != 0) 948 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 949 elf_errmsg(elferr)); 950 951 *size = sz; 952 953 return (b); 954 } 955 956 void 957 copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, 958 int sec_flags) 959 { 960 GElf_Shdr ish, osh; 961 962 if (gelf_getshdr(s->is, &ish) == NULL) 963 errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", 964 elf_errmsg(-1)); 965 if (gelf_getshdr(s->os, &osh) == NULL) 966 errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", 967 elf_errmsg(-1)); 968 969 if (copy) 970 (void) memcpy(&osh, &ish, sizeof(ish)); 971 else { 972 osh.sh_type = s->type; 973 osh.sh_addr = s->vma; 974 osh.sh_offset = s->off; 975 osh.sh_size = s->sz; 976 osh.sh_link = ish.sh_link; 977 osh.sh_info = ish.sh_info; 978 osh.sh_addralign = s->align; 979 osh.sh_entsize = ish.sh_entsize; 980 981 if (sec_flags) { 982 osh.sh_flags = 0; 983 if (sec_flags & SF_ALLOC) { 984 osh.sh_flags |= SHF_ALLOC; 985 if (!s->loadable) 986 warnx("set SHF_ALLOC flag for " 987 "unloadable section %s", 988 s->name); 989 } 990 if ((sec_flags & SF_READONLY) == 0) 991 osh.sh_flags |= SHF_WRITE; 992 if (sec_flags & SF_CODE) 993 osh.sh_flags |= SHF_EXECINSTR; 994 } else 995 osh.sh_flags = ish.sh_flags; 996 } 997 998 if (name == NULL) 999 add_to_shstrtab(ecp, s->name); 1000 else 1001 add_to_shstrtab(ecp, name); 1002 1003 if (!gelf_update_shdr(s->os, &osh)) 1004 errx(EXIT_FAILURE, "elf_update_shdr failed: %s", 1005 elf_errmsg(-1)); 1006 } 1007 1008 void 1009 copy_data(struct section *s) 1010 { 1011 Elf_Data *id, *od; 1012 int elferr; 1013 1014 if (s->nocopy && s->buf == NULL) 1015 return; 1016 1017 if ((id = elf_getdata(s->is, NULL)) == NULL) { 1018 elferr = elf_errno(); 1019 if (elferr != 0) 1020 errx(EXIT_FAILURE, "elf_getdata() failed: %s", 1021 elf_errmsg(elferr)); 1022 return; 1023 } 1024 1025 if ((od = elf_newdata(s->os)) == NULL) 1026 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1027 elf_errmsg(-1)); 1028 1029 if (s->nocopy) { 1030 /* Use s->buf as content if s->nocopy is set. */ 1031 od->d_align = id->d_align; 1032 od->d_off = 0; 1033 od->d_buf = s->buf; 1034 od->d_type = id->d_type; 1035 od->d_size = s->sz; 1036 od->d_version = id->d_version; 1037 } else { 1038 od->d_align = id->d_align; 1039 od->d_off = id->d_off; 1040 od->d_buf = id->d_buf; 1041 od->d_type = id->d_type; 1042 od->d_size = id->d_size; 1043 od->d_version = id->d_version; 1044 } 1045 } 1046 1047 struct section * 1048 create_external_section(struct elfcopy *ecp, const char *name, char *newname, 1049 void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, 1050 uint64_t flags, uint64_t align, uint64_t vma, int loadable) 1051 { 1052 struct section *s; 1053 Elf_Scn *os; 1054 Elf_Data *od; 1055 GElf_Shdr osh; 1056 1057 if ((os = elf_newscn(ecp->eout)) == NULL) 1058 errx(EXIT_FAILURE, "elf_newscn() failed: %s", 1059 elf_errmsg(-1)); 1060 if ((s = calloc(1, sizeof(*s))) == NULL) 1061 err(EXIT_FAILURE, "calloc failed"); 1062 s->name = name; 1063 s->newname = newname; /* needs to be free()'ed */ 1064 s->off = off; 1065 s->sz = size; 1066 s->vma = vma; 1067 s->align = align; 1068 s->loadable = loadable; 1069 s->is = NULL; 1070 s->os = os; 1071 s->type = stype; 1072 s->nocopy = 1; 1073 insert_to_sec_list(ecp, s, 1); 1074 1075 if (gelf_getshdr(os, &osh) == NULL) 1076 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", 1077 elf_errmsg(-1)); 1078 osh.sh_flags = flags; 1079 osh.sh_type = s->type; 1080 osh.sh_addr = s->vma; 1081 osh.sh_addralign = s->align; 1082 if (!gelf_update_shdr(os, &osh)) 1083 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1084 elf_errmsg(-1)); 1085 add_to_shstrtab(ecp, name); 1086 1087 if (buf != NULL && size != 0) { 1088 if ((od = elf_newdata(os)) == NULL) 1089 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1090 elf_errmsg(-1)); 1091 od->d_align = align; 1092 od->d_off = 0; 1093 od->d_buf = buf; 1094 od->d_size = size; 1095 od->d_type = dtype; 1096 od->d_version = EV_CURRENT; 1097 } 1098 1099 /* 1100 * Clear SYMTAB_INTACT, as we probably need to update/add new 1101 * STT_SECTION symbols into the symbol table. 1102 */ 1103 ecp->flags &= ~SYMTAB_INTACT; 1104 1105 return (s); 1106 } 1107 1108 /* 1109 * Insert sections specified by --add-section to the end of section list. 1110 */ 1111 static void 1112 insert_sections(struct elfcopy *ecp) 1113 { 1114 struct sec_add *sa; 1115 struct section *s; 1116 size_t off; 1117 1118 /* Put these sections in the end of current list. */ 1119 off = 0; 1120 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1121 if (s->type != SHT_NOBITS && s->type != SHT_NULL) 1122 off = s->off + s->sz; 1123 else 1124 off = s->off; 1125 } 1126 1127 STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { 1128 1129 /* TODO: Add section header vma/lma, flag changes here */ 1130 1131 (void) create_external_section(ecp, sa->name, NULL, sa->content, 1132 sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); 1133 } 1134 } 1135 1136 void 1137 add_to_shstrtab(struct elfcopy *ecp, const char *name) 1138 { 1139 struct section *s; 1140 1141 s = ecp->shstrtab; 1142 if (s->buf == NULL) { 1143 insert_to_strtab(s, ""); 1144 insert_to_strtab(s, ".symtab"); 1145 insert_to_strtab(s, ".strtab"); 1146 insert_to_strtab(s, ".shstrtab"); 1147 } 1148 insert_to_strtab(s, name); 1149 } 1150 1151 void 1152 update_shdr(struct elfcopy *ecp, int update_link) 1153 { 1154 struct section *s; 1155 GElf_Shdr osh; 1156 int elferr; 1157 1158 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 1159 if (s->pseudo) 1160 continue; 1161 1162 if (gelf_getshdr(s->os, &osh) == NULL) 1163 errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", 1164 elf_errmsg(-1)); 1165 1166 /* Find section name in string table and set sh_name. */ 1167 osh.sh_name = lookup_string(ecp->shstrtab, s->name); 1168 1169 /* 1170 * sh_link needs to be updated, since the index of the 1171 * linked section might have changed. 1172 */ 1173 if (update_link && osh.sh_link != 0) 1174 osh.sh_link = ecp->secndx[osh.sh_link]; 1175 1176 /* 1177 * sh_info of relocation section links to the section to which 1178 * its relocation info applies. So it may need update as well. 1179 */ 1180 if ((s->type == SHT_REL || s->type == SHT_RELA) && 1181 osh.sh_info != 0) 1182 osh.sh_info = ecp->secndx[osh.sh_info]; 1183 1184 if (!gelf_update_shdr(s->os, &osh)) 1185 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1186 elf_errmsg(-1)); 1187 } 1188 elferr = elf_errno(); 1189 if (elferr != 0) 1190 errx(EXIT_FAILURE, "elf_nextscn failed: %s", 1191 elf_errmsg(elferr)); 1192 } 1193 1194 void 1195 init_shstrtab(struct elfcopy *ecp) 1196 { 1197 struct section *s; 1198 1199 if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) 1200 err(EXIT_FAILURE, "calloc failed"); 1201 s = ecp->shstrtab; 1202 s->name = ".shstrtab"; 1203 s->is = NULL; 1204 s->sz = 0; 1205 s->align = 1; 1206 s->loadable = 0; 1207 s->type = SHT_STRTAB; 1208 s->vma = 0; 1209 } 1210 1211 void 1212 set_shstrtab(struct elfcopy *ecp) 1213 { 1214 struct section *s; 1215 Elf_Data *data; 1216 GElf_Shdr sh; 1217 1218 s = ecp->shstrtab; 1219 1220 if (gelf_getshdr(s->os, &sh) == NULL) 1221 errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", 1222 elf_errmsg(-1)); 1223 sh.sh_addr = 0; 1224 sh.sh_addralign = 1; 1225 sh.sh_offset = s->off; 1226 sh.sh_type = SHT_STRTAB; 1227 sh.sh_flags = 0; 1228 sh.sh_entsize = 0; 1229 sh.sh_info = 0; 1230 sh.sh_link = 0; 1231 1232 if ((data = elf_newdata(s->os)) == NULL) 1233 errx(EXIT_FAILURE, "elf_newdata() failed: %s", 1234 elf_errmsg(-1)); 1235 1236 /* 1237 * If we don't have a symbol table, skip those a few bytes 1238 * which are reserved for this in the beginning of shstrtab. 1239 */ 1240 if (!(ecp->flags & SYMTAB_EXIST)) { 1241 s->sz -= sizeof(".symtab\0.strtab"); 1242 memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), 1243 s->sz); 1244 } 1245 1246 sh.sh_size = s->sz; 1247 if (!gelf_update_shdr(s->os, &sh)) 1248 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", 1249 elf_errmsg(-1)); 1250 1251 data->d_align = 1; 1252 data->d_buf = s->buf; 1253 data->d_size = s->sz; 1254 data->d_off = 0; 1255 data->d_type = ELF_T_BYTE; 1256 data->d_version = EV_CURRENT; 1257 1258 if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) 1259 errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", 1260 elf_errmsg(-1)); 1261 } 1262 1263 void 1264 add_section(struct elfcopy *ecp, const char *arg) 1265 { 1266 struct sec_add *sa; 1267 struct stat sb; 1268 const char *s, *fn; 1269 FILE *fp; 1270 int len; 1271 1272 if ((s = strchr(arg, '=')) == NULL) 1273 errx(EXIT_FAILURE, 1274 "illegal format for --add-section option"); 1275 if ((sa = malloc(sizeof(*sa))) == NULL) 1276 err(EXIT_FAILURE, "malloc failed"); 1277 1278 len = s - arg; 1279 if ((sa->name = malloc(len + 1)) == NULL) 1280 err(EXIT_FAILURE, "malloc failed"); 1281 strncpy(sa->name, arg, len); 1282 sa->name[len] = '\0'; 1283 1284 fn = s + 1; 1285 if (stat(fn, &sb) == -1) 1286 err(EXIT_FAILURE, "stat failed"); 1287 sa->size = sb.st_size; 1288 if ((sa->content = malloc(sa->size)) == NULL) 1289 err(EXIT_FAILURE, "malloc failed"); 1290 if ((fp = fopen(fn, "r")) == NULL) 1291 err(EXIT_FAILURE, "can not open %s", fn); 1292 if (fread(sa->content, 1, sa->size, fp) == 0 || 1293 ferror(fp)) 1294 err(EXIT_FAILURE, "fread failed"); 1295 fclose(fp); 1296 1297 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1298 ecp->flags |= SEC_ADD; 1299 } 1300 1301 void 1302 free_sec_add(struct elfcopy *ecp) 1303 { 1304 struct sec_add *sa, *sa_temp; 1305 1306 STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { 1307 STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); 1308 free(sa->name); 1309 free(sa->content); 1310 free(sa); 1311 } 1312 } 1313 1314 static void 1315 add_gnu_debuglink(struct elfcopy *ecp) 1316 { 1317 struct sec_add *sa; 1318 struct stat sb; 1319 FILE *fp; 1320 char *fnbase, *buf; 1321 int crc_off; 1322 int crc; 1323 1324 if (ecp->debuglink == NULL) 1325 return; 1326 1327 /* Read debug file content. */ 1328 if ((sa = malloc(sizeof(*sa))) == NULL) 1329 err(EXIT_FAILURE, "malloc failed"); 1330 if ((sa->name = strdup(".gnu_debuglink")) == NULL) 1331 err(EXIT_FAILURE, "strdup failed"); 1332 if (stat(ecp->debuglink, &sb) == -1) 1333 err(EXIT_FAILURE, "stat failed"); 1334 if ((buf = malloc(sb.st_size)) == NULL) 1335 err(EXIT_FAILURE, "malloc failed"); 1336 if ((fp = fopen(ecp->debuglink, "r")) == NULL) 1337 err(EXIT_FAILURE, "can not open %s", ecp->debuglink); 1338 if (fread(buf, 1, sb.st_size, fp) == 0 || 1339 ferror(fp)) 1340 err(EXIT_FAILURE, "fread failed"); 1341 fclose(fp); 1342 1343 /* Calculate crc checksum. */ 1344 crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); 1345 free(buf); 1346 1347 /* Calculate section size and the offset to store crc checksum. */ 1348 if ((fnbase = basename(ecp->debuglink)) == NULL) 1349 err(EXIT_FAILURE, "basename failed"); 1350 crc_off = roundup(strlen(fnbase) + 1, 4); 1351 sa->size = crc_off + 4; 1352 1353 /* Section content. */ 1354 if ((sa->content = calloc(1, sa->size)) == NULL) 1355 err(EXIT_FAILURE, "malloc failed"); 1356 strncpy(sa->content, fnbase, strlen(fnbase)); 1357 if (ecp->oed == ELFDATA2LSB) { 1358 sa->content[crc_off] = crc & 0xFF; 1359 sa->content[crc_off + 1] = (crc >> 8) & 0xFF; 1360 sa->content[crc_off + 2] = (crc >> 16) & 0xFF; 1361 sa->content[crc_off + 3] = crc >> 24; 1362 } else { 1363 sa->content[crc_off] = crc >> 24; 1364 sa->content[crc_off + 1] = (crc >> 16) & 0xFF; 1365 sa->content[crc_off + 2] = (crc >> 8) & 0xFF; 1366 sa->content[crc_off + 3] = crc & 0xFF; 1367 } 1368 1369 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); 1370 ecp->flags |= SEC_ADD; 1371 } 1372 1373 static void 1374 insert_to_strtab(struct section *t, const char *s) 1375 { 1376 const char *r; 1377 char *b, *c; 1378 size_t len, slen; 1379 int append; 1380 1381 if (t->sz == 0) { 1382 t->cap = 512; 1383 if ((t->buf = malloc(t->cap)) == NULL) 1384 err(EXIT_FAILURE, "malloc failed"); 1385 } 1386 1387 slen = strlen(s); 1388 append = 0; 1389 b = t->buf; 1390 for (c = b; c < b + t->sz;) { 1391 len = strlen(c); 1392 if (!append && len >= slen) { 1393 r = c + (len - slen); 1394 if (strcmp(r, s) == 0) 1395 return; 1396 } else if (len < slen && len != 0) { 1397 r = s + (slen - len); 1398 if (strcmp(c, r) == 0) { 1399 t->sz -= len + 1; 1400 memmove(c, c + len + 1, t->sz - (c - b)); 1401 append = 1; 1402 continue; 1403 } 1404 } 1405 c += len + 1; 1406 } 1407 1408 while (t->sz + slen + 1 >= t->cap) { 1409 t->cap *= 2; 1410 if ((t->buf = realloc(t->buf, t->cap)) == NULL) 1411 err(EXIT_FAILURE, "realloc failed"); 1412 } 1413 b = t->buf; 1414 strncpy(&b[t->sz], s, slen); 1415 b[t->sz + slen] = '\0'; 1416 t->sz += slen + 1; 1417 } 1418 1419 static int 1420 lookup_string(struct section *t, const char *s) 1421 { 1422 const char *b, *c, *r; 1423 size_t len, slen; 1424 1425 slen = strlen(s); 1426 b = t->buf; 1427 for (c = b; c < b + t->sz;) { 1428 len = strlen(c); 1429 if (len >= slen) { 1430 r = c + (len - slen); 1431 if (strcmp(r, s) == 0) 1432 return (r - b); 1433 } 1434 c += len + 1; 1435 } 1436 1437 return (-1); 1438 } 1439 1440 static uint32_t crctable[256] = 1441 { 1442 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 1443 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 1444 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 1445 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 1446 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 1447 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 1448 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 1449 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 1450 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 1451 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 1452 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 1453 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 1454 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 1455 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 1456 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 1457 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 1458 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 1459 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 1460 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 1461 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 1462 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 1463 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 1464 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 1465 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 1466 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 1467 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 1468 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 1469 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 1470 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 1471 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 1472 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 1473 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 1474 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 1475 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 1476 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 1477 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 1478 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 1479 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 1480 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 1481 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 1482 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 1483 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 1484 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 1485 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 1486 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 1487 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 1488 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 1489 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 1490 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 1491 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 1492 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 1493 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 1494 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 1495 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 1496 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 1497 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 1498 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 1499 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 1500 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 1501 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 1502 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 1503 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 1504 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 1505 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL 1506 }; 1507 1508 static uint32_t 1509 calc_crc32(const char *p, size_t len, uint32_t crc) 1510 { 1511 uint32_t i; 1512 1513 for (i = 0; i < len; i++) { 1514 crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); 1515 } 1516 1517 return (crc ^ 0xFFFFFFFF); 1518 } 1519