diff options
author | Ed Maste <emaste@FreeBSD.org> | 2016-05-19 20:06:56 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2016-05-19 20:06:56 +0000 |
commit | a7f03fcfe7109df232200b8b5e1f715a18ba7d74 (patch) | |
tree | 5d850df4522f52e077ecb35866e624861ceeb1f6 /elfcopy | |
parent | 7c9f2b63d3a1c147cf1bd709b562d6273908d5b6 (diff) |
Notes
Diffstat (limited to 'elfcopy')
-rw-r--r-- | elfcopy/ascii.c | 4 | ||||
-rw-r--r-- | elfcopy/binary.c | 9 | ||||
-rw-r--r-- | elfcopy/elfcopy.1 | 19 | ||||
-rw-r--r-- | elfcopy/elfcopy.h | 9 | ||||
-rw-r--r-- | elfcopy/main.c | 19 | ||||
-rw-r--r-- | elfcopy/sections.c | 22 | ||||
-rw-r--r-- | elfcopy/segments.c | 277 | ||||
-rw-r--r-- | elfcopy/symbols.c | 8 |
8 files changed, 253 insertions, 114 deletions
diff --git a/elfcopy/ascii.c b/elfcopy/ascii.c index cad4eb8a91eb1..fb1edb3cce462 100644 --- a/elfcopy/ascii.c +++ b/elfcopy/ascii.c @@ -36,7 +36,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: ascii.c 3177 2015-03-30 18:19:41Z emaste $"); +ELFTC_VCSID("$Id: ascii.c 3446 2016-05-03 01:31:17Z emaste $"); static void append_data(struct section *s, const void *buf, size_t sz); static char hex_digit(uint8_t n); @@ -187,7 +187,7 @@ create_srec(struct elfcopy *ecp, int ifd, int ofd, const char *ofn) if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); - /* Generate S{7,8,9} end of block recrod. */ + /* Generate S{7,8,9} end of block record. */ if (gelf_getehdr(e, &eh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); diff --git a/elfcopy/binary.c b/elfcopy/binary.c index 7c834a9aaa34d..ad86a6533c55a 100644 --- a/elfcopy/binary.c +++ b/elfcopy/binary.c @@ -26,6 +26,7 @@ #include <sys/param.h> #include <sys/stat.h> +#include <ctype.h> #include <err.h> #include <gelf.h> #include <stdio.h> @@ -35,7 +36,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: binary.c 3270 2015-12-11 18:48:56Z emaste $"); +ELFTC_VCSID("$Id: binary.c 3445 2016-04-20 19:08:30Z emaste $"); /* * Convert ELF object to `binary'. Sections with SHF_ALLOC flag set @@ -213,9 +214,9 @@ create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn) if ((sym_basename = strdup(ifn)) == NULL) err(1, "strdup"); - p = sym_basename; - while ((p = strchr(p, '.')) != NULL) - *p++ = '_'; + for (p = sym_basename; *p != '\0'; p++) + if (!isalnum(*p)) + *p = '_'; #define _GEN_SYMNAME(S) do { \ snprintf(name, sizeof(name), "%s%s%s", "_binary_", sym_basename, S); \ } while (0) diff --git a/elfcopy/elfcopy.1 b/elfcopy/elfcopy.1 index b7b0ce48dfa1f..672885a8132b1 100644 --- a/elfcopy/elfcopy.1 +++ b/elfcopy/elfcopy.1 @@ -21,9 +21,9 @@ .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elfcopy.1 3381 2016-01-30 19:39:47Z jkoshy $ +.\" $Id: elfcopy.1 3426 2016-03-05 13:32:28Z emaste $ .\" -.Dd January 29, 2016 +.Dd March 5, 2016 .Os .Dt ELFCOPY 1 .Sh NAME @@ -67,7 +67,10 @@ .Op Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val .Op Fl -extract-dwo .Op Fl -gap-fill Ns = Ns Ar val +.Op Fl -globalize-symbol Ns = Ns ar symbolname +.Op Fl -globalize-symbols Ns = Ns Ar filename .Op Fl -localize-hidden +.Op Fl -localize-symbols Ns = Ns Ar filename .Op Fl -no-adjust-warnings | Fl -no-change-warnings .Op Fl -only-keep-debug .Op Fl -pad-to Ns = Ns Ar address @@ -239,9 +242,21 @@ Copy only .dwo debug sections to the output file. Fill the gaps between sections with the byte value specified by the argument .Ar val . +.It Fl -globalize-symbol Ns = Ns Ar symbolname +Make the symbol named by argument +.Ar symbolname +global, so that it is visible outside of the file in which it is defined. +.It Fl -globalize-symbols Ns = Ns Ar filename +Make each symbol listed in the file specified by +.Ar filename +global. .It Fl -localize-hidden Make all hidden symbols local to the output file. This includes symbols with internal visiblity. +.It Fl -localize-symbols Ns = Ns Ar filename +Make each symbol listed in the file specified by +.Ar filename +local to the output file. .It Fl -no-adjust-warnings | Fl -no-change-warnings Do not issue a warning if the section specified by the options .Fl -change-section-address , diff --git a/elfcopy/elfcopy.h b/elfcopy/elfcopy.h index 614c0e7e65bdf..5593a9a40218d 100644 --- a/elfcopy/elfcopy.h +++ b/elfcopy/elfcopy.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfcopy.h 3310 2016-01-10 09:10:54Z kaiwang27 $ + * $Id: elfcopy.h 3446 2016-05-03 01:31:17Z emaste $ */ #include <sys/queue.h> @@ -139,7 +139,8 @@ struct section { /* Internal data structure for segments. */ struct segment { - uint64_t addr; /* load addr */ + uint64_t vaddr; /* virtual addr (VMA) */ + uint64_t paddr; /* physical addr (LMA) */ uint64_t off; /* file offset */ uint64_t fsz; /* file size */ uint64_t msz; /* memory size */ @@ -177,7 +178,7 @@ struct elfcopy { Elftc_Bfd_Target_Flavor otf; /* flavour of output object */ const char *otgt; /* output target name */ int oec; /* elfclass of output object */ - unsigned char oed; /* endianess of output object */ + unsigned char oed; /* endianness of output object */ int oem; /* EM_XXX of output object */ int abi; /* OSABI of output object */ Elf *ein; /* ELF descriptor of input object */ @@ -237,7 +238,7 @@ struct elfcopy { uint64_t *secndx; /* section index map. */ uint64_t *symndx; /* symbol index map. */ unsigned char *v_rel; /* symbols needed by relocation. */ - unsigned char *v_grp; /* symbols refered by section group. */ + unsigned char *v_grp; /* symbols referred by section group. */ unsigned char *v_secsym; /* sections with section symbol. */ STAILQ_HEAD(, segment) v_seg; /* list of segments. */ STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */ diff --git a/elfcopy/main.c b/elfcopy/main.c index b51ba4e3ac38a..ebc0c92a1c01e 100644 --- a/elfcopy/main.c +++ b/elfcopy/main.c @@ -39,7 +39,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: main.c 3399 2016-02-12 18:07:56Z emaste $"); +ELFTC_VCSID("$Id: main.c 3446 2016-05-03 01:31:17Z emaste $"); enum options { @@ -209,6 +209,7 @@ static struct { {"openbsd", ELFOSABI_OPENBSD}, {"openvms", ELFOSABI_OPENVMS}, {"nsk", ELFOSABI_NSK}, + {"cloudabi", ELFOSABI_CLOUDABI}, {"arm", ELFOSABI_ARM}, {"standalone", ELFOSABI_STANDALONE}, {NULL, 0} @@ -235,7 +236,7 @@ static void strip_main(struct elfcopy *ecp, int argc, char **argv); static void strip_usage(void); /* - * An ELF object usually has a sturcture described by the + * An ELF object usually has a structure described by the * diagram below. * _____________ * | | @@ -641,6 +642,18 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst) * ELF object before processing. */ if (ecp->itf != ETF_ELF) { + /* + * If the output object is not an ELF file, choose an arbitrary + * ELF format for the intermediate file. srec, ihex and binary + * formats are independent of class, endianness and machine + * type so these choices do not affect the output. + */ + if (ecp->otf != ETF_ELF) { + if (ecp->oec == ELFCLASSNONE) + ecp->oec = ELFCLASS64; + if (ecp->oed == ELFDATANONE) + ecp->oed = ELFDATA2LSB; + } create_tempfile(&elftemp, &efd); if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", @@ -1434,7 +1447,7 @@ Usage: %s [options] infile [outfile]\n\ sections.\n\ --only-keep-debug Copy only debugging information.\n\ --output-target=FORMAT Use the specified format for the output.\n\ - --pad-to=ADDRESS Pad the output object upto the given address.\n\ + --pad-to=ADDRESS Pad the output object up to the given address.\n\ --prefix-alloc-sections=STRING\n\ Prefix the section names of all the allocated\n\ sections with STRING.\n\ diff --git a/elfcopy/sections.c b/elfcopy/sections.c index ff41015faeef8..bd703e9065841 100644 --- a/elfcopy/sections.c +++ b/elfcopy/sections.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: sections.c 3346 2016-01-17 20:09:15Z kaiwang27 $"); +ELFTC_VCSID("$Id: sections.c 3443 2016-04-15 18:57:54Z kaiwang27 $"); static void add_gnu_debuglink(struct elfcopy *ecp); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); @@ -343,7 +343,7 @@ create_scn(struct elfcopy *ecp) GElf_Shdr ish; size_t indx; uint64_t oldndx, newndx; - int elferr, sec_flags; + int elferr, sec_flags, reorder; /* * Insert a pseudo section that contains the ELF header @@ -367,6 +367,7 @@ create_scn(struct elfcopy *ecp) errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", elf_errmsg(-1)); + reorder = 0; is = NULL; while ((is = elf_nextscn(ecp->ein, is)) != NULL) { if (gelf_getshdr(is, &ish) == NULL) @@ -482,8 +483,20 @@ create_scn(struct elfcopy *ecp) /* create section header based on input object. */ if (strcmp(name, ".symtab") != 0 && strcmp(name, ".strtab") != 0 && - strcmp(name, ".shstrtab") != 0) + strcmp(name, ".shstrtab") != 0) { copy_shdr(ecp, s, NULL, 0, sec_flags); + /* + * elfcopy puts .symtab, .strtab and .shstrtab + * sections in the end of the output object. + * If the input objects have more sections + * after any of these 3 sections, the section + * table will be reordered. section symbols + * should be regenerated for relocations. + */ + if (reorder) + ecp->flags &= ~SYMTAB_INTACT; + } else + reorder = 1; if (strcmp(name, ".symtab") == 0) { ecp->flags |= SYMTAB_EXIST; @@ -1519,6 +1532,9 @@ add_gnu_debuglink(struct elfcopy *ecp) err(EXIT_FAILURE, "strdup failed"); if (stat(ecp->debuglink, &sb) == -1) err(EXIT_FAILURE, "stat failed"); + if (sb.st_size == 0) + errx(EXIT_FAILURE, "empty debug link target %s", + ecp->debuglink); if ((buf = malloc(sb.st_size)) == NULL) err(EXIT_FAILURE, "malloc failed"); if ((fp = fopen(ecp->debuglink, "r")) == NULL) diff --git a/elfcopy/segments.c b/elfcopy/segments.c index 8ce0b83abe809..9a26bba88cfcf 100644 --- a/elfcopy/segments.c +++ b/elfcopy/segments.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: segments.c 3397 2016-02-12 14:35:19Z emaste $"); +ELFTC_VCSID("$Id: segments.c 3449 2016-05-03 13:59:29Z emaste $"); static void insert_to_inseg_list(struct segment *seg, struct section *sec); @@ -72,12 +72,12 @@ add_to_inseg_list(struct elfcopy *ecp, struct section *s) */ loadable = 0; STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { - if (s->off < seg->off || (s->vma < seg->addr && !s->pseudo)) + if (s->off < seg->off || (s->vma < seg->vaddr && !s->pseudo)) continue; if (s->off + s->sz > seg->off + seg->fsz && s->type != SHT_NOBITS) continue; - if (s->vma + s->sz > seg->addr + seg->msz) + if (s->vma + s->sz > seg->vaddr + seg->msz) continue; insert_to_inseg_list(seg, s); @@ -85,7 +85,12 @@ add_to_inseg_list(struct elfcopy *ecp, struct section *s) s->seg = seg; else if (seg->type == PT_TLS) s->seg_tls = seg; - s->lma = seg->addr + (s->off - seg->off); + if (s->pseudo) + s->vma = seg->vaddr + (s->off - seg->off); + if (seg->paddr > 0) + s->lma = seg->paddr + (s->off - seg->off); + else + s->lma = 0; loadable = 1; } @@ -98,7 +103,7 @@ adjust_addr(struct elfcopy *ecp) struct section *s, *s0; struct segment *seg; struct sec_action *sac; - uint64_t dl, lma, start, end; + uint64_t dl, vma, lma, start, end; int found, i; /* @@ -110,59 +115,52 @@ adjust_addr(struct elfcopy *ecp) if (!s->loadable) continue; + /* Apply global VMA adjustment. */ + if (ecp->change_addr != 0) + s->vma += ecp->change_addr; + /* Apply global LMA adjustment. */ - if (ecp->change_addr != 0 && s->seg != NULL) + if (ecp->change_addr != 0 && s->seg != NULL && + s->seg->paddr > 0) s->lma += ecp->change_addr; - - if (!s->pseudo) { - /* Apply global VMA adjustment. */ - if (ecp->change_addr != 0) - s->vma += ecp->change_addr; - - /* Apply section VMA adjustment. */ - sac = lookup_sec_act(ecp, s->name, 0); - if (sac == NULL) - continue; - if (sac->setvma) - s->vma = sac->vma; - if (sac->vma_adjust != 0) - s->vma += sac->vma_adjust; - } } /* - * Apply sections LMA change in the second iteration. + * Apply sections VMA change in the second iteration. */ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { - /* - * Only loadable section that's inside a segment can have - * LMA adjusted. - */ - if (!s->loadable || s->seg == NULL) + if (!s->loadable) continue; /* - * Check if there is a LMA change request for this + * Check if there is a VMA change request for this * section. */ sac = lookup_sec_act(ecp, s->name, 0); if (sac == NULL) continue; - if (!sac->setlma && sac->lma_adjust == 0) + vma = s->vma; + if (sac->setvma) + vma = sac->vma; + if (sac->vma_adjust != 0) + vma += sac->vma_adjust; + if (vma == s->vma) continue; - lma = s->lma; - if (sac->setlma) - lma = sac->lma; - if (sac->lma_adjust != 0) - lma += sac->lma_adjust; - if (lma == s->lma) + + /* + * No need to make segment adjustment if the section doesn't + * belong to any segment. + */ + if (s->seg == NULL) { + s->vma = vma; continue; + } /* - * Check if the LMA change is viable. + * Check if the VMA change is viable. * - * 1. Check if the new LMA is properly aligned accroding to + * 1. Check if the new VMA is properly aligned accroding to * section alignment. * * 2. Compute the new extent of segment that contains this @@ -170,37 +168,36 @@ adjust_addr(struct elfcopy *ecp) * segments. */ #ifdef DEBUG - printf("LMA for section %s: %#jx\n", s->name, lma); + printf("VMA for section %s: %#jx\n", s->name, vma); #endif - if (lma % s->align != 0) - errx(EXIT_FAILURE, "The load address %#jx for " + if (vma % s->align != 0) + errx(EXIT_FAILURE, "The VMA %#jx for " "section %s is not aligned to %ju", - (uintmax_t) lma, s->name, (uintmax_t) s->align); + (uintmax_t) vma, s->name, (uintmax_t) s->align); - if (lma < s->lma) { + if (vma < s->vma) { /* Move section to lower address. */ - if (lma < s->lma - s->seg->addr) + if (vma < s->vma - s->seg->vaddr) errx(EXIT_FAILURE, "Not enough space to move " - "section %s load address to %#jx", s->name, - (uintmax_t) lma); - start = lma - (s->lma - s->seg->addr); + "section %s VMA to %#jx", s->name, + (uintmax_t) vma); + start = vma - (s->vma - s->seg->vaddr); if (s == s->seg->v_sec[s->seg->nsec - 1]) end = start + s->seg->msz; else - end = s->seg->addr + s->seg->msz; - + end = s->seg->vaddr + s->seg->msz; } else { /* Move section to upper address. */ if (s == s->seg->v_sec[0]) - start = lma; + start = vma; else - start = s->seg->addr; - end = lma + (s->seg->addr + s->seg->msz - s->lma); + start = s->seg->vaddr; + end = vma + (s->seg->vaddr + s->seg->msz - s->vma); if (end < start) errx(EXIT_FAILURE, "Not enough space to move " - "section %s load address to %#jx", s->name, - (uintmax_t) lma); + "section %s VMA to %#jx", s->name, + (uintmax_t) vma); } #ifdef DEBUG @@ -211,34 +208,34 @@ adjust_addr(struct elfcopy *ecp) STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (seg == s->seg || seg->type != PT_LOAD) continue; - if (start > seg->addr + seg->msz) + if (start > seg->vaddr + seg->msz) continue; - if (end < seg->addr) + if (end < seg->vaddr) continue; errx(EXIT_FAILURE, "The extent of segment containing " "section %s overlaps with segment(%#jx,%#jx)", - s->name, (uintmax_t) seg->addr, - (uintmax_t) (seg->addr + seg->msz)); + s->name, (uintmax_t) seg->vaddr, + (uintmax_t) (seg->vaddr + seg->msz)); } /* - * Update section LMA and file offset. + * Update section VMA and file offset. */ - if (lma < s->lma) { + if (vma < s->vma) { /* - * To move a section to lower load address, we decrease - * the load addresses of the section and all the - * sections that are before it, and we increase the - * file offsets of all the sections that are after it. + * To move a section to lower VMA, we decrease + * the VMA of the section and all the sections that + * are before it, and we increase the file offsets + * of all the sections that are after it. */ - dl = s->lma - lma; + dl = s->vma - vma; for (i = 0; i < s->seg->nsec; i++) { s0 = s->seg->v_sec[i]; - s0->lma -= dl; + s0->vma -= dl; #ifdef DEBUG - printf("section %s LMA set to %#jx\n", - s0->name, (uintmax_t) s0->lma); + printf("section %s VMA set to %#jx\n", + s0->name, (uintmax_t) s0->vma); #endif if (s0 == s) break; @@ -253,13 +250,13 @@ adjust_addr(struct elfcopy *ecp) } } else { /* - * To move a section to upper load address, we increase - * the load addresses of the section and all the - * sections that are after it, and we increase the - * their file offsets too unless the section in question + * To move a section to upper VMA, we increase + * the VMA of the section and all the sections that + * are after it, and we increase the their file + * offsets too unless the section in question * is the first in its containing segment. */ - dl = lma - s->lma; + dl = vma - s->vma; for (i = 0; i < s->seg->nsec; i++) if (s->seg->v_sec[i] == s) break; @@ -269,9 +266,9 @@ adjust_addr(struct elfcopy *ecp) s->name); for (; i < s->seg->nsec; i++) { s0 = s->seg->v_sec[i]; - s0->lma += dl; + s0->vma += dl; #ifdef DEBUG - printf("section %s LMA set to %#jx\n", + printf("section %s VMA set to %#jx\n", s0->name, (uintmax_t) s0->lma); #endif if (s != s->seg->v_sec[0]) { @@ -292,9 +289,8 @@ adjust_addr(struct elfcopy *ecp) if (ecp->pad_to != 0) { /* - * Find the section with highest load address. + * Find the section with highest VMA. */ - s = NULL; STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (seg->type != PT_LOAD) @@ -308,26 +304,113 @@ adjust_addr(struct elfcopy *ecp) s = seg->v_sec[i]; else { s0 = seg->v_sec[i]; - if (s0->lma > s->lma) + if (s0->vma > s->vma) s = s0; } } if (s == NULL) - goto issue_warn; + goto adjust_lma; /* No need to pad if the pad_to address is lower. */ - if (ecp->pad_to <= s->lma + s->sz) - goto issue_warn; + if (ecp->pad_to <= s->vma + s->sz) + goto adjust_lma; - s->pad_sz = ecp->pad_to - (s->lma + s->sz); + s->pad_sz = ecp->pad_to - (s->vma + s->sz); #ifdef DEBUG - printf("pad section %s load to address %#jx by %#jx\n", s->name, + printf("pad section %s VMA to address %#jx by %#jx\n", s->name, (uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz); #endif } -issue_warn: + +adjust_lma: + + /* + * Apply sections LMA change in the third iteration. + */ + TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { + + /* + * Only loadable section that's inside a segment can have + * LMA adjusted. Also, if LMA of the containing segment is + * set to 0, it probably means we should ignore the LMA. + */ + if (!s->loadable || s->seg == NULL || s->seg->paddr == 0) + continue; + + /* + * Check if there is a LMA change request for this + * section. + */ + sac = lookup_sec_act(ecp, s->name, 0); + if (sac == NULL) + continue; + if (!sac->setlma && sac->lma_adjust == 0) + continue; + lma = s->lma; + if (sac->setlma) + lma = sac->lma; + if (sac->lma_adjust != 0) + lma += sac->lma_adjust; + if (lma == s->lma) + continue; + +#ifdef DEBUG + printf("LMA for section %s: %#jx\n", s->name, lma); +#endif + + /* Check alignment. */ + if (lma % s->align != 0) + errx(EXIT_FAILURE, "The LMA %#jx for " + "section %s is not aligned to %ju", + (uintmax_t) lma, s->name, (uintmax_t) s->align); + + /* + * Update section LMA. + */ + + if (lma < s->lma) { + /* + * To move a section to lower LMA, we decrease + * the LMA of the section and all the sections that + * are before it. + */ + dl = s->lma - lma; + for (i = 0; i < s->seg->nsec; i++) { + s0 = s->seg->v_sec[i]; + s0->lma -= dl; +#ifdef DEBUG + printf("section %s LMA set to %#jx\n", + s0->name, (uintmax_t) s0->lma); +#endif + if (s0 == s) + break; + } + } else { + /* + * To move a section to upper LMA, we increase + * the LMA of the section and all the sections that + * are after it. + */ + dl = lma - s->lma; + for (i = 0; i < s->seg->nsec; i++) + if (s->seg->v_sec[i] == s) + break; + if (i >= s->seg->nsec) + errx(EXIT_FAILURE, "Internal: section `%s' not" + " found in its containing segement", + s->name); + for (; i < s->seg->nsec; i++) { + s0 = s->seg->v_sec[i]; + s0->lma += dl; +#ifdef DEBUG + printf("section %s LMA set to %#jx\n", + s0->name, (uintmax_t) s0->lma); +#endif + } + } + } /* * Issue a warning if there are VMA/LMA adjust requests for @@ -385,8 +468,7 @@ setup_phdr(struct elfcopy *ecp) { struct segment *seg; GElf_Phdr iphdr; - size_t iphnum; - int i; + size_t iphnum, i; if (elf_getphnum(ecp->ein, &iphnum) == 0) errx(EXIT_FAILURE, "elf_getphnum failed: %s", @@ -402,13 +484,14 @@ setup_phdr(struct elfcopy *ecp) return; } - for (i = 0; (size_t)i < iphnum; i++) { + for (i = 0; i < iphnum; i++) { if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) errx(EXIT_FAILURE, "gelf_getphdr failed: %s", elf_errmsg(-1)); if ((seg = calloc(1, sizeof(*seg))) == NULL) err(EXIT_FAILURE, "calloc failed"); - seg->addr = iphdr.p_vaddr; + seg->vaddr = iphdr.p_vaddr; + seg->paddr = iphdr.p_paddr; seg->off = iphdr.p_offset; seg->fsz = iphdr.p_filesz; seg->msz = iphdr.p_memsz; @@ -429,20 +512,30 @@ copy_phdr(struct elfcopy *ecp) if (seg->type == PT_PHDR) { if (!TAILQ_EMPTY(&ecp->v_sec)) { s = TAILQ_FIRST(&ecp->v_sec); - if (s->pseudo) - seg->addr = s->lma + + if (s->pseudo) { + seg->vaddr = s->vma + + gelf_fsize(ecp->eout, ELF_T_EHDR, + 1, EV_CURRENT); + seg->paddr = s->lma + gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); + } } seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); continue; } + if (seg->nsec > 0) { + s = seg->v_sec[0]; + seg->vaddr = s->vma; + seg->paddr = s->lma; + } + seg->fsz = seg->msz = 0; for (i = 0; i < seg->nsec; i++) { s = seg->v_sec[i]; - seg->msz = s->vma + s->sz - seg->addr; + seg->msz = s->vma + s->sz - seg->vaddr; if (s->type != SHT_NOBITS) seg->fsz = s->off + s->sz - seg->off; } @@ -481,8 +574,8 @@ copy_phdr(struct elfcopy *ecp) elf_errmsg(-1)); ophdr.p_type = iphdr.p_type; - ophdr.p_vaddr = seg->addr; - ophdr.p_paddr = seg->addr; + ophdr.p_vaddr = seg->vaddr; + ophdr.p_paddr = seg->paddr; ophdr.p_flags = iphdr.p_flags; ophdr.p_align = iphdr.p_align; ophdr.p_offset = seg->off; diff --git a/elfcopy/symbols.c b/elfcopy/symbols.c index ae6193c212fea..d072da8a1aba5 100644 --- a/elfcopy/symbols.c +++ b/elfcopy/symbols.c @@ -34,7 +34,7 @@ #include "elfcopy.h" -ELFTC_VCSID("$Id: symbols.c 3376 2016-01-26 18:41:39Z emaste $"); +ELFTC_VCSID("$Id: symbols.c 3446 2016-05-03 01:31:17Z emaste $"); /* Symbol table buffer structure. */ struct symbuf { @@ -162,7 +162,7 @@ is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s) if (BIT_ISSET(ecp->v_rel, i)) return (1); - /* Symbols refered by COMDAT sections are needed. */ + /* Symbols referred by COMDAT sections are needed. */ if (BIT_ISSET(ecp->v_grp, i)) return (1); @@ -252,7 +252,7 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, } /* - * Mark symbols refered by relocation entries. + * Mark symbols referred by relocation entries. */ static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc) @@ -1159,7 +1159,7 @@ lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op) if ((s->op & op) == 0) continue; if (name == NULL || !strcmp(name, s->name)) - return (s); + return (s); if ((ecp->flags & WILDCARD) == 0) continue; |