2 * Copyright (c) 2007-2011,2014 Kai Wang
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/param.h>
37 ELFTC_VCSID("$Id: sections.c 3272 2015-12-11 20:00:54Z kaiwang27 $");
39 static void add_gnu_debuglink(struct elfcopy *ecp);
40 static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
41 static void check_section_rename(struct elfcopy *ecp, struct section *s);
42 static void filter_reloc(struct elfcopy *ecp, struct section *s);
43 static int get_section_flags(struct elfcopy *ecp, const char *name);
44 static void insert_sections(struct elfcopy *ecp);
45 static void insert_to_strtab(struct section *t, const char *s);
46 static int is_append_section(struct elfcopy *ecp, const char *name);
47 static int is_compress_section(struct elfcopy *ecp, const char *name);
48 static int is_debug_section(const char *name);
49 static int is_dwo_section(const char *name);
50 static int is_modify_section(struct elfcopy *ecp, const char *name);
51 static int is_print_section(struct elfcopy *ecp, const char *name);
52 static int lookup_string(struct section *t, const char *s);
53 static void modify_section(struct elfcopy *ecp, struct section *s);
54 static void pad_section(struct elfcopy *ecp, struct section *s);
55 static void print_data(const char *d, size_t sz);
56 static void print_section(struct section *s);
57 static void *read_section(struct section *s, size_t *size);
58 static void update_reloc(struct elfcopy *ecp, struct section *s);
59 static void update_section_group(struct elfcopy *ecp, struct section *s);
62 is_remove_section(struct elfcopy *ecp, const char *name)
65 /* Always keep section name table */
66 if (strcmp(name, ".shstrtab") == 0)
68 if (strcmp(name, ".symtab") == 0 ||
69 strcmp(name, ".strtab") == 0) {
70 if (ecp->strip == STRIP_ALL && lookup_symop_list(
71 ecp, NULL, SYMOP_KEEP) == NULL)
77 if (ecp->strip == STRIP_DWO && is_dwo_section(name))
79 if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name))
82 if (is_debug_section(name)) {
83 if (ecp->strip == STRIP_ALL ||
84 ecp->strip == STRIP_DEBUG ||
85 ecp->strip == STRIP_UNNEEDED ||
86 (ecp->flags & DISCARD_LOCAL))
88 if (ecp->strip == STRIP_NONDEBUG)
92 if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) {
93 struct sec_action *sac;
95 sac = lookup_sec_act(ecp, name, 0);
96 if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove)
98 if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy))
106 * Relocation section needs to be removed if the section it applies to
110 is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info)
118 if (elf_getshstrndx(ecp->ein, &indx) == 0)
119 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
123 while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
124 if (sh_info == elf_ndxscn(is)) {
125 if (gelf_getshdr(is, &ish) == NULL)
126 errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
128 if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) ==
130 errx(EXIT_FAILURE, "elf_strptr failed: %s",
132 if (is_remove_section(ecp, name))
138 elferr = elf_errno();
140 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
143 /* Remove reloc section if we can't find the target section. */
148 is_append_section(struct elfcopy *ecp, const char *name)
150 struct sec_action *sac;
152 sac = lookup_sec_act(ecp, name, 0);
153 if (sac != NULL && sac->append != 0 && sac->string != NULL)
160 is_compress_section(struct elfcopy *ecp, const char *name)
162 struct sec_action *sac;
164 sac = lookup_sec_act(ecp, name, 0);
165 if (sac != NULL && sac->compress != 0)
172 check_section_rename(struct elfcopy *ecp, struct section *s)
174 struct sec_action *sac;
181 sac = lookup_sec_act(ecp, s->name, 0);
182 if (sac != NULL && sac->rename)
183 s->name = sac->newname;
185 if (!strcmp(s->name, ".symtab") ||
186 !strcmp(s->name, ".strtab") ||
187 !strcmp(s->name, ".shstrtab"))
191 if (s->loadable && ecp->prefix_alloc != NULL)
192 prefix = ecp->prefix_alloc;
193 else if (ecp->prefix_sec != NULL)
194 prefix = ecp->prefix_sec;
196 if (prefix != NULL) {
197 namelen = strlen(s->name) + strlen(prefix) + 1;
198 if ((s->newname = malloc(namelen)) == NULL)
199 err(EXIT_FAILURE, "malloc failed");
200 snprintf(s->newname, namelen, "%s%s", prefix, s->name);
201 s->name = s->newname;
206 get_section_flags(struct elfcopy *ecp, const char *name)
208 struct sec_action *sac;
210 sac = lookup_sec_act(ecp, name, 0);
211 if (sac != NULL && sac->flags)
218 * Determine whether the section are debugging section.
219 * According to libbfd, debugging sections are recognized
223 is_debug_section(const char *name)
225 const char *dbg_sec[] = {
234 for(p = dbg_sec; *p; p++) {
235 if (strncmp(name, *p, strlen(*p)) == 0)
243 is_dwo_section(const char *name)
247 if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0)
253 is_print_section(struct elfcopy *ecp, const char *name)
255 struct sec_action *sac;
257 sac = lookup_sec_act(ecp, name, 0);
258 if (sac != NULL && sac->print != 0)
265 is_modify_section(struct elfcopy *ecp, const char *name)
268 if (is_append_section(ecp, name) ||
269 is_compress_section(ecp, name))
276 lookup_sec_act(struct elfcopy *ecp, const char *name, int add)
278 struct sec_action *sac;
283 STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) {
284 if (strcmp(name, sac->name) == 0)
291 if ((sac = malloc(sizeof(*sac))) == NULL)
292 errx(EXIT_FAILURE, "not enough memory");
293 memset(sac, 0, sizeof(*sac));
295 STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list);
301 free_sec_act(struct elfcopy *ecp)
303 struct sec_action *sac, *sac_temp;
305 STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) {
306 STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list);
312 insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail)
317 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
318 if (sec->off < s->off) {
319 TAILQ_INSERT_BEFORE(s, sec, sec_list);
325 TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list);
328 if (sec->pseudo == 0)
333 * First step of section creation: create scn and internal section
334 * structure, discard sections to be removed.
337 create_scn(struct elfcopy *ecp)
344 uint64_t oldndx, newndx;
345 int elferr, sec_flags;
348 * Insert a pseudo section that contains the ELF header
349 * and program header. Used as reference for section offset
350 * or load address adjustment.
352 if ((s = calloc(1, sizeof(*s))) == NULL)
353 err(EXIT_FAILURE, "calloc failed");
355 s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) +
356 gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT);
359 s->loadable = add_to_inseg_list(ecp, s);
360 insert_to_sec_list(ecp, s, 0);
362 /* Create internal .shstrtab section. */
365 if (elf_getshstrndx(ecp->ein, &indx) == 0)
366 errx(EXIT_FAILURE, "elf_getshstrndx failed: %s",
370 while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
371 if (gelf_getshdr(is, &ish) == NULL)
372 errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s",
374 if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL)
375 errx(EXIT_FAILURE, "elf_strptr failed: %s",
378 /* Skip sections to be removed. */
379 if (is_remove_section(ecp, name))
383 * Relocation section need to be remove if the section
384 * it applies will be removed.
386 if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
387 if (ish.sh_info != 0 &&
388 is_remove_reloc_sec(ecp, ish.sh_info))
392 * Section groups should be removed if symbol table will
393 * be removed. (section group's signature stored in symbol
396 if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL)
399 /* Get section flags set by user. */
400 sec_flags = get_section_flags(ecp, name);
402 /* Create internal section object. */
403 if (strcmp(name, ".shstrtab") != 0) {
404 if ((s = calloc(1, sizeof(*s))) == NULL)
405 err(EXIT_FAILURE, "calloc failed");
408 s->off = ish.sh_offset;
410 s->align = ish.sh_addralign;
411 s->type = ish.sh_type;
412 s->vma = ish.sh_addr;
415 * Search program headers to determine whether section
416 * is loadable, but if user explicitly set section flags
417 * while neither "load" nor "alloc" is set, we make the
418 * section unloadable.
421 (sec_flags & (SF_LOAD | SF_ALLOC)) == 0)
424 s->loadable = add_to_inseg_list(ecp, s);
426 /* Assuming .shstrtab is "unloadable". */
428 s->off = ish.sh_offset;
431 oldndx = newndx = SHN_UNDEF;
432 if (strcmp(name, ".symtab") != 0 &&
433 strcmp(name, ".strtab") != 0) {
434 if (!strcmp(name, ".shstrtab")) {
436 * Add sections specified by --add-section and
437 * gnu debuglink. we want these sections have
438 * smaller index than .shstrtab section.
440 if (ecp->debuglink != NULL)
441 add_gnu_debuglink(ecp);
442 if (ecp->flags & SEC_ADD)
443 insert_sections(ecp);
445 if ((s->os = elf_newscn(ecp->eout)) == NULL)
446 errx(EXIT_FAILURE, "elf_newscn failed: %s",
448 if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF)
449 errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
452 if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF)
453 errx(EXIT_FAILURE, "elf_ndxscn failed: %s",
455 if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF)
456 ecp->secndx[oldndx] = newndx;
459 * If strip action is STRIP_NONDEBUG(only keep debug),
460 * change sections type of loadable sections and section
461 * groups to SHT_NOBITS, and the content of those sections
462 * will be discarded. However, SHT_NOTE sections should
465 if (ecp->strip == STRIP_NONDEBUG) {
466 if (((ish.sh_flags & SHF_ALLOC) ||
467 (ish.sh_flags & SHF_GROUP)) &&
468 ish.sh_type != SHT_NOTE)
469 s->type = SHT_NOBITS;
472 check_section_rename(ecp, s);
474 /* create section header based on input object. */
475 if (strcmp(name, ".symtab") != 0 &&
476 strcmp(name, ".strtab") != 0 &&
477 strcmp(name, ".shstrtab") != 0)
478 copy_shdr(ecp, s, NULL, 0, sec_flags);
480 if (strcmp(name, ".symtab") == 0) {
481 ecp->flags |= SYMTAB_EXIST;
484 if (strcmp(name, ".strtab") == 0)
487 insert_to_sec_list(ecp, s, 0);
489 elferr = elf_errno();
491 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
496 insert_shtab(struct elfcopy *ecp, int tail)
498 struct section *s, *shtab;
503 * Treat section header table as a "pseudo" section, insert it
504 * into section list, so later it will get sorted and resynced
505 * just as normal sections.
507 if ((shtab = calloc(1, sizeof(*shtab))) == NULL)
508 errx(EXIT_FAILURE, "calloc failed");
511 * "shoff" of input object is used as a hint for section
514 if (gelf_getehdr(ecp->ein, &ieh) == NULL)
515 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
517 shtab->off = ieh.e_shoff;
520 /* Calculate number of sections in the output object. */
522 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
526 /* Remember there is always a null section, so we +1 here. */
527 shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT);
529 errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1));
530 shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8);
533 insert_to_sec_list(ecp, shtab, tail);
539 copy_content(struct elfcopy *ecp)
543 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
544 /* Skip pseudo section. */
548 /* Skip special sections. */
549 if (strcmp(s->name, ".symtab") == 0 ||
550 strcmp(s->name, ".strtab") == 0 ||
551 strcmp(s->name, ".shstrtab") == 0)
555 * If strip action is STRIP_ALL, relocation info need
556 * to be stripped. Skip filtering otherwisw.
558 if (ecp->strip == STRIP_ALL &&
559 (s->type == SHT_REL || s->type == SHT_RELA))
560 filter_reloc(ecp, s);
563 * The section indices in the SHT_GROUP section needs
564 * to be updated since we might have stripped some
565 * sections and changed section numbering.
567 if (s->type == SHT_GROUP)
568 update_section_group(ecp, s);
570 if (is_modify_section(ecp, s->name))
571 modify_section(ecp, s);
576 * If symbol table is modified, relocation info might
577 * need update, as symbol index may have changed.
579 if ((ecp->flags & SYMTAB_INTACT) == 0 &&
580 (ecp->flags & SYMTAB_EXIST) &&
581 (s->type == SHT_REL || s->type == SHT_RELA))
582 update_reloc(ecp, s);
584 if (is_print_section(ecp, s->name))
591 * Update section group section. The section indices in the SHT_GROUP
592 * section need update after section numbering changed.
595 update_section_group(struct elfcopy *ecp, struct section *s)
604 if (!elf_getshnum(ecp->ein, &ishnum))
605 errx(EXIT_FAILURE, "elf_getshnum failed: %s",
608 if (gelf_getshdr(s->is, &ish) == NULL)
609 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
612 if ((id = elf_getdata(s->is, NULL)) == NULL)
613 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
616 if (ish.sh_size == 0)
619 if (ish.sh_entsize == 0)
624 /* We only support COMDAT section. */
626 #define GRP_COMDAT 0x1
628 if ((*ws & GRP_COMDAT) == 0)
631 if ((s->buf = malloc(ish.sh_size)) == NULL)
632 err(EXIT_FAILURE, "malloc failed");
638 /* Copy the flag word as-is. */
641 /* Update the section indices. */
642 n = ish.sh_size / ish.sh_entsize;
643 for(i = 1, j = 1; (uint64_t)i < n; i++) {
644 if (ws[i] != SHN_UNDEF && ws[i] < ishnum &&
645 ecp->secndx[ws[i]] != 0)
646 wd[j++] = ecp->secndx[ws[i]];
655 * Filter relocation entries, only keep those entries whose
656 * symbol is in the keep list.
659 filter_reloc(struct elfcopy *ecp, struct section *s)
670 uint64_t cap, n, nrels;
673 if (gelf_getshdr(s->is, &ish) == NULL)
674 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
677 /* We don't want to touch relocation info for dynamic symbols. */
678 if ((ecp->flags & SYMTAB_EXIST) == 0) {
679 if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) {
681 * This reloc section applies to the symbol table
682 * that was stripped, so discard whole section.
689 /* Symbol table exist, check if index equals. */
690 if (ish.sh_link != elf_ndxscn(ecp->symtab->is))
694 #define COPYREL(REL, SZ) do { \
696 if ((REL##SZ = malloc(cap * \
697 sizeof(Elf##SZ##_Rel))) == NULL) \
698 err(EXIT_FAILURE, "malloc failed"); \
700 if (nrels >= cap) { \
702 if ((REL##SZ = realloc(REL##SZ, cap * \
703 sizeof(Elf##SZ##_Rel))) == NULL) \
704 err(EXIT_FAILURE, "realloc failed"); \
706 REL##SZ[nrels].r_offset = REL.r_offset; \
707 REL##SZ[nrels].r_info = REL.r_info; \
708 if (s->type == SHT_RELA) \
709 rela##SZ[nrels].r_addend = rela.r_addend; \
714 cap = 4; /* keep list is usually small. */
719 if ((id = elf_getdata(s->is, NULL)) == NULL)
720 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
722 n = ish.sh_size / ish.sh_entsize;
723 for(i = 0; (uint64_t)i < n; i++) {
724 if (s->type == SHT_REL) {
725 if (gelf_getrel(id, i, &rel) != &rel)
726 errx(EXIT_FAILURE, "gelf_getrel failed: %s",
729 if (gelf_getrela(id, i, &rela) != &rela)
730 errx(EXIT_FAILURE, "gelf_getrel failed: %s",
733 name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is),
734 GELF_R_SYM(rel.r_info));
736 errx(EXIT_FAILURE, "elf_strptr failed: %s",
738 if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) {
739 if (ecp->oec == ELFCLASS32) {
740 if (s->type == SHT_REL)
745 if (s->type == SHT_REL)
752 elferr = elf_errno();
754 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
757 if (ecp->oec == ELFCLASS32) {
758 if (s->type == SHT_REL)
763 if (s->type == SHT_REL)
768 s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL :
769 ELF_T_RELA), nrels, EV_CURRENT);
774 update_reloc(struct elfcopy *ecp, struct section *s)
783 #define UPDATEREL(REL) do { \
784 if (gelf_get##REL(od, i, &REL) != &REL) \
785 errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \
787 REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \
788 GELF_R_TYPE(REL.r_info)); \
789 if (!gelf_update_##REL(od, i, &REL)) \
790 errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \
796 if (gelf_getshdr(s->os, &osh) == NULL)
797 errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
799 /* Only process .symtab reloc info. */
800 if (osh.sh_link != elf_ndxscn(ecp->symtab->is))
802 if ((od = elf_getdata(s->os, NULL)) == NULL)
803 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
805 n = osh.sh_size / osh.sh_entsize;
806 for(i = 0; (uint64_t)i < n; i++) {
807 if (s->type == SHT_REL)
815 pad_section(struct elfcopy *ecp, struct section *s)
820 if (s == NULL || s->pad_sz == 0)
823 if ((s->pad = malloc(s->pad_sz)) == NULL)
824 err(EXIT_FAILURE, "malloc failed");
825 memset(s->pad, ecp->fill, s->pad_sz);
827 /* Create a new Elf_Data to contain the padding bytes. */
828 if ((od = elf_newdata(s->os)) == NULL)
829 errx(EXIT_FAILURE, "elf_newdata() failed: %s",
834 od->d_type = ELF_T_BYTE;
835 od->d_size = s->pad_sz;
836 od->d_version = EV_CURRENT;
838 /* Update section header. */
839 if (gelf_getshdr(s->os, &osh) == NULL)
840 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
842 osh.sh_size = s->sz + s->pad_sz;
843 if (!gelf_update_shdr(s->os, &osh))
844 errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
849 resync_sections(struct elfcopy *ecp)
851 struct section *s, *ps;
859 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
866 * Ignore TLS sections with load address 0 and without
867 * content. We don't need to adjust their file offset or
868 * VMA, only the size matters.
870 if (s->seg_tls != NULL && s->type == SHT_NOBITS &&
874 /* Align section offset. */
879 s->off = roundup(off, s->align);
882 warnx("moving loadable section %s, "
883 "is this intentional?", s->name);
884 s->off = roundup(off, s->align);
887 /* Calculate next section offset. */
889 if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL))
897 /* Count padding bytes added through --pad-to. */
901 /* Update section header accordingly. */
902 if (gelf_getshdr(s->os, &osh) == NULL)
903 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
905 osh.sh_addr = s->vma;
906 osh.sh_offset = s->off;
908 if (!gelf_update_shdr(s->os, &osh))
909 errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
912 /* Add padding for previous section, if need. */
914 if (ps->pad_sz > 0) {
915 /* Apply padding added by --pad-to. */
916 pad_section(ecp, ps);
917 } else if ((ecp->flags & GAP_FILL) &&
918 (ps->off + ps->sz < s->off)) {
920 * Fill the gap between sections by padding
921 * the section with lower address.
923 ps->pad_sz = s->off - (ps->off + ps->sz);
924 pad_section(ecp, ps);
931 /* Pad the last section, if need. */
932 if (ps != NULL && ps->pad_sz > 0)
933 pad_section(ecp, ps);
937 modify_section(struct elfcopy *ecp, struct section *s)
939 struct sec_action *sac;
940 size_t srcsz, dstsz, p, len;
941 char *b, *c, *d, *src, *end;
944 src = read_section(s, &srcsz);
945 if (src == NULL || srcsz == 0) {
946 /* For empty section, we proceed if we need to append. */
947 if (!is_append_section(ecp, s->name))
951 /* Allocate buffer needed for new section data. */
953 if (is_append_section(ecp, s->name)) {
954 sac = lookup_sec_act(ecp, s->name, 0);
955 dstsz += strlen(sac->string) + 1;
957 if ((b = malloc(dstsz)) == NULL)
958 err(EXIT_FAILURE, "malloc failed");
961 /* Compress section. */
963 if (is_compress_section(ecp, s->name)) {
965 for(c = src; c < end;) {
967 while(c + len < end && c[len] != '\0')
969 if (c + len == end) {
970 /* XXX should we warn here? */
971 strncpy(&b[p], c, len);
976 for (d = b; d < b + p; ) {
977 if (strcmp(d, c) == 0) {
984 strncpy(&b[p], c, len);
991 memcpy(b, src, srcsz);
995 /* Append section. */
996 if (is_append_section(ecp, s->name)) {
997 sac = lookup_sec_act(ecp, s->name, 0);
998 len = strlen(sac->string);
999 strncpy(&b[p], sac->string, len);
1009 print_data(const char *d, size_t sz)
1013 for (c = d; c < d + sz; c++) {
1022 print_section(struct section *s)
1027 if (s->buf != NULL && s->sz > 0) {
1028 print_data(s->buf, s->sz);
1031 while ((id = elf_getdata(s->is, id)) != NULL)
1032 print_data(id->d_buf, id->d_size);
1033 elferr = elf_errno();
1035 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1036 elf_errmsg(elferr));
1042 read_section(struct section *s, size_t *size)
1052 while ((id = elf_getdata(s->is, id)) != NULL) {
1054 b = malloc(id->d_size);
1056 b = malloc(sz + id->d_size);
1058 err(EXIT_FAILURE, "malloc or realloc failed");
1060 memcpy(&b[sz], id->d_buf, id->d_size);
1063 elferr = elf_errno();
1065 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1066 elf_errmsg(elferr));
1074 copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
1079 if (gelf_getshdr(s->is, &ish) == NULL)
1080 errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s",
1082 if (gelf_getshdr(s->os, &osh) == NULL)
1083 errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s",
1087 (void) memcpy(&osh, &ish, sizeof(ish));
1089 osh.sh_type = s->type;
1090 osh.sh_addr = s->vma;
1091 osh.sh_offset = s->off;
1092 osh.sh_size = s->sz;
1093 osh.sh_link = ish.sh_link;
1094 osh.sh_info = ish.sh_info;
1095 osh.sh_addralign = s->align;
1096 osh.sh_entsize = ish.sh_entsize;
1100 if (sec_flags & SF_ALLOC) {
1101 osh.sh_flags |= SHF_ALLOC;
1103 warnx("set SHF_ALLOC flag for "
1104 "unloadable section %s",
1107 if ((sec_flags & SF_READONLY) == 0)
1108 osh.sh_flags |= SHF_WRITE;
1109 if (sec_flags & SF_CODE)
1110 osh.sh_flags |= SHF_EXECINSTR;
1112 osh.sh_flags = ish.sh_flags;
1113 if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
1114 osh.sh_flags |= SHF_INFO_LINK;
1119 add_to_shstrtab(ecp, s->name);
1121 add_to_shstrtab(ecp, name);
1123 if (!gelf_update_shdr(s->os, &osh))
1124 errx(EXIT_FAILURE, "elf_update_shdr failed: %s",
1129 copy_data(struct section *s)
1134 if (s->nocopy && s->buf == NULL)
1137 if ((id = elf_getdata(s->is, NULL)) == NULL) {
1138 elferr = elf_errno();
1140 errx(EXIT_FAILURE, "elf_getdata() failed: %s",
1141 elf_errmsg(elferr));
1145 if ((od = elf_newdata(s->os)) == NULL)
1146 errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1150 /* Use s->buf as content if s->nocopy is set. */
1151 od->d_align = id->d_align;
1154 od->d_type = id->d_type;
1156 od->d_version = id->d_version;
1158 od->d_align = id->d_align;
1159 od->d_off = id->d_off;
1160 od->d_buf = id->d_buf;
1161 od->d_type = id->d_type;
1162 od->d_size = id->d_size;
1163 od->d_version = id->d_version;
1167 * Alignment Fixup. libelf does not allow the alignment for
1168 * Elf_Data descriptor to be set to 0. In this case we workaround
1169 * it by setting the alignment to 1.
1171 * According to the ELF ABI, alignment 0 and 1 has the same
1172 * meaning: the section has no alignment constraints.
1174 if (od->d_align == 0)
1179 create_external_section(struct elfcopy *ecp, const char *name, char *newname,
1180 void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype,
1181 uint64_t flags, uint64_t align, uint64_t vma, int loadable)
1188 if ((os = elf_newscn(ecp->eout)) == NULL)
1189 errx(EXIT_FAILURE, "elf_newscn() failed: %s",
1191 if ((s = calloc(1, sizeof(*s))) == NULL)
1192 err(EXIT_FAILURE, "calloc failed");
1194 s->newname = newname; /* needs to be free()'ed */
1199 s->loadable = loadable;
1204 insert_to_sec_list(ecp, s, 1);
1206 if (gelf_getshdr(os, &osh) == NULL)
1207 errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
1209 osh.sh_flags = flags;
1210 osh.sh_type = s->type;
1211 osh.sh_addr = s->vma;
1212 osh.sh_addralign = s->align;
1213 if (!gelf_update_shdr(os, &osh))
1214 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1216 add_to_shstrtab(ecp, name);
1218 if (buf != NULL && size != 0) {
1219 if ((od = elf_newdata(os)) == NULL)
1220 errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1222 od->d_align = align;
1227 od->d_version = EV_CURRENT;
1231 * Clear SYMTAB_INTACT, as we probably need to update/add new
1232 * STT_SECTION symbols into the symbol table.
1234 ecp->flags &= ~SYMTAB_INTACT;
1240 * Insert sections specified by --add-section to the end of section list.
1243 insert_sections(struct elfcopy *ecp)
1249 /* Put these sections in the end of current list. */
1251 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1252 if (s->type != SHT_NOBITS && s->type != SHT_NULL)
1253 off = s->off + s->sz;
1258 STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) {
1260 /* TODO: Add section header vma/lma, flag changes here */
1262 (void) create_external_section(ecp, sa->name, NULL, sa->content,
1263 sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0);
1268 add_to_shstrtab(struct elfcopy *ecp, const char *name)
1273 insert_to_strtab(s, name);
1277 update_shdr(struct elfcopy *ecp, int update_link)
1283 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
1287 if (gelf_getshdr(s->os, &osh) == NULL)
1288 errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s",
1291 /* Find section name in string table and set sh_name. */
1292 osh.sh_name = lookup_string(ecp->shstrtab, s->name);
1295 * sh_link needs to be updated, since the index of the
1296 * linked section might have changed.
1298 if (update_link && osh.sh_link != 0)
1299 osh.sh_link = ecp->secndx[osh.sh_link];
1302 * sh_info of relocation section links to the section to which
1303 * its relocation info applies. So it may need update as well.
1305 if ((s->type == SHT_REL || s->type == SHT_RELA) &&
1307 osh.sh_info = ecp->secndx[osh.sh_info];
1310 * sh_info of SHT_GROUP section needs to point to the correct
1311 * string in the symbol table.
1313 if (s->type == SHT_GROUP && (ecp->flags & SYMTAB_EXIST) &&
1314 (ecp->flags & SYMTAB_INTACT) == 0)
1315 osh.sh_info = ecp->symndx[osh.sh_info];
1317 if (!gelf_update_shdr(s->os, &osh))
1318 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1321 elferr = elf_errno();
1323 errx(EXIT_FAILURE, "elf_nextscn failed: %s",
1324 elf_errmsg(elferr));
1328 init_shstrtab(struct elfcopy *ecp)
1332 if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL)
1333 err(EXIT_FAILURE, "calloc failed");
1335 s->name = ".shstrtab";
1340 s->type = SHT_STRTAB;
1343 insert_to_strtab(s, "");
1344 insert_to_strtab(s, ".symtab");
1345 insert_to_strtab(s, ".strtab");
1346 insert_to_strtab(s, ".shstrtab");
1350 set_shstrtab(struct elfcopy *ecp)
1358 if (s->os == NULL) {
1359 /* Input object does not contain .shstrtab section */
1360 if ((s->os = elf_newscn(ecp->eout)) == NULL)
1361 errx(EXIT_FAILURE, "elf_newscn failed: %s",
1363 insert_to_sec_list(ecp, s, 1);
1366 if (gelf_getshdr(s->os, &sh) == NULL)
1367 errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s",
1370 sh.sh_addralign = 1;
1371 sh.sh_offset = s->off;
1372 sh.sh_type = SHT_STRTAB;
1378 if ((data = elf_newdata(s->os)) == NULL)
1379 errx(EXIT_FAILURE, "elf_newdata() failed: %s",
1383 * If we don't have a symbol table, skip those a few bytes
1384 * which are reserved for this in the beginning of shstrtab.
1386 if (!(ecp->flags & SYMTAB_EXIST)) {
1387 s->sz -= sizeof(".symtab\0.strtab");
1388 memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"),
1393 if (!gelf_update_shdr(s->os, &sh))
1394 errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s",
1398 data->d_buf = s->buf;
1399 data->d_size = s->sz;
1401 data->d_type = ELF_T_BYTE;
1402 data->d_version = EV_CURRENT;
1404 if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os)))
1405 errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s",
1410 add_section(struct elfcopy *ecp, const char *arg)
1418 if ((s = strchr(arg, '=')) == NULL)
1420 "illegal format for --add-section option");
1421 if ((sa = malloc(sizeof(*sa))) == NULL)
1422 err(EXIT_FAILURE, "malloc failed");
1425 if ((sa->name = malloc(len + 1)) == NULL)
1426 err(EXIT_FAILURE, "malloc failed");
1427 strncpy(sa->name, arg, len);
1428 sa->name[len] = '\0';
1431 if (stat(fn, &sb) == -1)
1432 err(EXIT_FAILURE, "stat failed");
1433 sa->size = sb.st_size;
1434 if ((sa->content = malloc(sa->size)) == NULL)
1435 err(EXIT_FAILURE, "malloc failed");
1436 if ((fp = fopen(fn, "r")) == NULL)
1437 err(EXIT_FAILURE, "can not open %s", fn);
1438 if (fread(sa->content, 1, sa->size, fp) == 0 ||
1440 err(EXIT_FAILURE, "fread failed");
1443 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1444 ecp->flags |= SEC_ADD;
1448 free_sec_add(struct elfcopy *ecp)
1450 struct sec_add *sa, *sa_temp;
1452 STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) {
1453 STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list);
1461 add_gnu_debuglink(struct elfcopy *ecp)
1470 if (ecp->debuglink == NULL)
1473 /* Read debug file content. */
1474 if ((sa = malloc(sizeof(*sa))) == NULL)
1475 err(EXIT_FAILURE, "malloc failed");
1476 if ((sa->name = strdup(".gnu_debuglink")) == NULL)
1477 err(EXIT_FAILURE, "strdup failed");
1478 if (stat(ecp->debuglink, &sb) == -1)
1479 err(EXIT_FAILURE, "stat failed");
1480 if ((buf = malloc(sb.st_size)) == NULL)
1481 err(EXIT_FAILURE, "malloc failed");
1482 if ((fp = fopen(ecp->debuglink, "r")) == NULL)
1483 err(EXIT_FAILURE, "can not open %s", ecp->debuglink);
1484 if (fread(buf, 1, sb.st_size, fp) == 0 ||
1486 err(EXIT_FAILURE, "fread failed");
1489 /* Calculate crc checksum. */
1490 crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF);
1493 /* Calculate section size and the offset to store crc checksum. */
1494 if ((fnbase = basename(ecp->debuglink)) == NULL)
1495 err(EXIT_FAILURE, "basename failed");
1496 crc_off = roundup(strlen(fnbase) + 1, 4);
1497 sa->size = crc_off + 4;
1499 /* Section content. */
1500 if ((sa->content = calloc(1, sa->size)) == NULL)
1501 err(EXIT_FAILURE, "malloc failed");
1502 strncpy(sa->content, fnbase, strlen(fnbase));
1503 if (ecp->oed == ELFDATA2LSB) {
1504 sa->content[crc_off] = crc & 0xFF;
1505 sa->content[crc_off + 1] = (crc >> 8) & 0xFF;
1506 sa->content[crc_off + 2] = (crc >> 16) & 0xFF;
1507 sa->content[crc_off + 3] = crc >> 24;
1509 sa->content[crc_off] = crc >> 24;
1510 sa->content[crc_off + 1] = (crc >> 16) & 0xFF;
1511 sa->content[crc_off + 2] = (crc >> 8) & 0xFF;
1512 sa->content[crc_off + 3] = crc & 0xFF;
1515 STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
1516 ecp->flags |= SEC_ADD;
1520 insert_to_strtab(struct section *t, const char *s)
1529 if ((t->buf = malloc(t->cap)) == NULL)
1530 err(EXIT_FAILURE, "malloc failed");
1536 for (c = b; c < b + t->sz;) {
1538 if (!append && len >= slen) {
1539 r = c + (len - slen);
1540 if (strcmp(r, s) == 0)
1542 } else if (len < slen && len != 0) {
1543 r = s + (slen - len);
1544 if (strcmp(c, r) == 0) {
1546 memmove(c, c + len + 1, t->sz - (c - b));
1554 while (t->sz + slen + 1 >= t->cap) {
1556 if ((t->buf = realloc(t->buf, t->cap)) == NULL)
1557 err(EXIT_FAILURE, "realloc failed");
1560 strncpy(&b[t->sz], s, slen);
1561 b[t->sz + slen] = '\0';
1566 lookup_string(struct section *t, const char *s)
1568 const char *b, *c, *r;
1573 for (c = b; c < b + t->sz;) {
1576 r = c + (len - slen);
1577 if (strcmp(r, s) == 0)
1586 static uint32_t crctable[256] =
1588 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
1589 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
1590 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
1591 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
1592 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
1593 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
1594 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
1595 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
1596 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
1597 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
1598 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
1599 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
1600 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
1601 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
1602 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
1603 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
1604 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
1605 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
1606 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
1607 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
1608 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
1609 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
1610 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
1611 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
1612 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
1613 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
1614 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
1615 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
1616 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
1617 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
1618 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
1619 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
1620 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
1621 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
1622 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
1623 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
1624 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
1625 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
1626 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
1627 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
1628 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
1629 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
1630 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
1631 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
1632 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
1633 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
1634 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
1635 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
1636 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
1637 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
1638 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
1639 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
1640 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
1641 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
1642 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
1643 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
1644 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
1645 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
1646 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
1647 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
1648 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
1649 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
1650 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
1651 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
1655 calc_crc32(const char *p, size_t len, uint32_t crc)
1659 for (i = 0; i < len; i++) {
1660 crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8);
1663 return (crc ^ 0xFFFFFFFF);