summaryrefslogtreecommitdiff
path: root/elfcopy
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2016-05-19 20:06:56 +0000
committerEd Maste <emaste@FreeBSD.org>2016-05-19 20:06:56 +0000
commita7f03fcfe7109df232200b8b5e1f715a18ba7d74 (patch)
tree5d850df4522f52e077ecb35866e624861ceeb1f6 /elfcopy
parent7c9f2b63d3a1c147cf1bd709b562d6273908d5b6 (diff)
Notes
Diffstat (limited to 'elfcopy')
-rw-r--r--elfcopy/ascii.c4
-rw-r--r--elfcopy/binary.c9
-rw-r--r--elfcopy/elfcopy.119
-rw-r--r--elfcopy/elfcopy.h9
-rw-r--r--elfcopy/main.c19
-rw-r--r--elfcopy/sections.c22
-rw-r--r--elfcopy/segments.c277
-rw-r--r--elfcopy/symbols.c8
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;