summaryrefslogtreecommitdiffstats
path: root/rtemstoolkit/elftoolchain/libelf/elf_update.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemstoolkit/elftoolchain/libelf/elf_update.c')
-rw-r--r--rtemstoolkit/elftoolchain/libelf/elf_update.c179
1 files changed, 105 insertions, 74 deletions
diff --git a/rtemstoolkit/elftoolchain/libelf/elf_update.c b/rtemstoolkit/elftoolchain/libelf/elf_update.c
index 9806131..6cc109d 100644
--- a/rtemstoolkit/elftoolchain/libelf/elf_update.c
+++ b/rtemstoolkit/elftoolchain/libelf/elf_update.c
@@ -24,7 +24,7 @@
* SUCH DAMAGE.
*/
-#include <sys/mman.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <assert.h>
@@ -37,7 +37,11 @@
#include "_libelf.h"
-LIBELF_VCSID("$Id: elf_update.c 1922 2011-09-23 08:04:33Z jkoshy $");
+#if ELFTC_HAVE_MMAP
+#include <sys/mman.h>
+#endif
+
+ELFTC_VCSID("$Id: elf_update.c 3190 2015-05-04 15:23:08Z jkoshy $");
/*
* Layout strategy:
@@ -106,14 +110,14 @@ SLIST_HEAD(_Elf_Extent_List, _Elf_Extent);
static int
_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
{
- int ec;
- size_t fsz, msz;
Elf_Data *d;
- Elf32_Shdr *shdr32;
- Elf64_Shdr *shdr64;
+ size_t fsz, msz;
+ int ec, elftype;
uint32_t sh_type;
uint64_t d_align;
- unsigned int elftype;
+ Elf32_Shdr *shdr32;
+ Elf64_Shdr *shdr64;
+ struct _Libelf_Data *ld;
uint64_t scn_size, scn_alignment;
uint64_t sh_align, sh_entsize, sh_offset, sh_size;
@@ -187,7 +191,9 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
*/
scn_size = 0L;
scn_alignment = 0;
- STAILQ_FOREACH(d, &s->s_data, d_next) {
+ STAILQ_FOREACH(ld, &s->s_data, d_next) {
+
+ d = &ld->d_data;
/*
* The data buffer's type is known.
@@ -246,7 +252,7 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
scn_size = roundup2(scn_size, d->d_align);
d->d_off = scn_size;
fsz = _libelf_fsize(d->d_type, ec, d->d_version,
- d->d_size / msz);
+ (size_t) d->d_size / msz);
scn_size += fsz;
}
@@ -265,8 +271,10 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
* offsets and alignment for sanity.
*/
if (e->e_flags & ELF_F_LAYOUT) {
- if (scn_alignment > sh_align || sh_offset % sh_align ||
- sh_size < scn_size) {
+ if (scn_alignment > sh_align ||
+ sh_offset % sh_align ||
+ sh_size < scn_size ||
+ sh_offset % _libelf_falign(elftype, ec)) {
LIBELF_SET_ERROR(LAYOUT, 0);
return (0);
}
@@ -300,7 +308,7 @@ computeoffset:
* Compute the new offset for the section based on
* the section's alignment needs.
*/
- sh_offset = roundup(rc, sh_align);
+ sh_offset = roundup((uint64_t) rc, sh_align);
/*
* Update the section header.
@@ -464,7 +472,7 @@ _libelf_resync_sections(Elf *e, off_t rc, struct _Elf_Extent_List *extents)
return ((off_t) -1);
if ((size_t) rc < s->s_offset + s->s_size)
- rc = s->s_offset + s->s_size;
+ rc = (off_t) (s->s_offset + s->s_size);
}
return (rc);
@@ -495,7 +503,7 @@ _libelf_resync_sections(Elf *e, off_t rc, struct _Elf_Extent_List *extents)
static off_t
_libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
{
- int ec, eh_class, eh_type;
+ int ec, eh_class;
unsigned int eh_byteorder, eh_version;
size_t align, fsz;
size_t phnum, shnum;
@@ -522,19 +530,22 @@ _libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
if (ec == ELFCLASS32) {
eh_byteorder = eh32->e_ident[EI_DATA];
eh_class = eh32->e_ident[EI_CLASS];
- phoff = (uint64_t) eh32->e_phoff;
- shoff = (uint64_t) eh32->e_shoff;
- eh_type = eh32->e_type;
+ phoff = (off_t) eh32->e_phoff;
+ shoff = (off_t) eh32->e_shoff;
eh_version = eh32->e_version;
} else {
eh_byteorder = eh64->e_ident[EI_DATA];
eh_class = eh64->e_ident[EI_CLASS];
- phoff = eh64->e_phoff;
- shoff = eh64->e_shoff;
- eh_type = eh64->e_type;
+ phoff = (off_t) eh64->e_phoff;
+ shoff = (off_t) eh64->e_shoff;
eh_version = eh64->e_version;
}
+ if (phoff < 0 || shoff < 0) {
+ LIBELF_SET_ERROR(HEADER, 0);
+ return ((off_t) -1);
+ }
+
if (eh_version == EV_NONE)
eh_version = EV_CURRENT;
@@ -559,18 +570,20 @@ _libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
e->e_byteorder = eh_byteorder;
#define INITIALIZE_EHDR(E,EC,V) do { \
+ unsigned int _version = (unsigned int) (V); \
(E)->e_ident[EI_MAG0] = ELFMAG0; \
(E)->e_ident[EI_MAG1] = ELFMAG1; \
(E)->e_ident[EI_MAG2] = ELFMAG2; \
(E)->e_ident[EI_MAG3] = ELFMAG3; \
- (E)->e_ident[EI_CLASS] = (EC); \
- (E)->e_ident[EI_VERSION] = (V); \
- (E)->e_ehsize = _libelf_fsize(ELF_T_EHDR, (EC), (V), \
- (size_t) 1); \
- (E)->e_phentsize = (phnum == 0) ? 0 : _libelf_fsize( \
- ELF_T_PHDR, (EC), (V), (size_t) 1); \
- (E)->e_shentsize = _libelf_fsize(ELF_T_SHDR, (EC), (V), \
- (size_t) 1); \
+ (E)->e_ident[EI_CLASS] = (unsigned char) (EC); \
+ (E)->e_ident[EI_VERSION] = (_version & 0xFFU); \
+ (E)->e_ehsize = (uint16_t) _libelf_fsize(ELF_T_EHDR, \
+ (EC), _version, (size_t) 1); \
+ (E)->e_phentsize = (uint16_t) ((phnum == 0) ? 0 : \
+ _libelf_fsize(ELF_T_PHDR, (EC), _version, \
+ (size_t) 1)); \
+ (E)->e_shentsize = (uint16_t) _libelf_fsize(ELF_T_SHDR, \
+ (EC), _version, (size_t) 1); \
} while (0)
if (ec == ELFCLASS32)
@@ -580,9 +593,10 @@ _libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
(void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY);
- rc += _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1);
+ rc += (off_t) _libelf_fsize(ELF_T_EHDR, ec, eh_version, (size_t) 1);
- if (!_libelf_insert_extent(extents, ELF_EXTENT_EHDR, 0, rc, ehdr))
+ if (!_libelf_insert_extent(extents, ELF_EXTENT_EHDR, 0, (uint64_t) rc,
+ ehdr))
return ((off_t) -1);
/*
@@ -603,20 +617,20 @@ _libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
return ((off_t) -1);
}
- if (phoff % align) {
+ if (phoff % (off_t) align) {
LIBELF_SET_ERROR(LAYOUT, 0);
return ((off_t) -1);
}
} else
- phoff = roundup(rc, align);
+ phoff = roundup(rc, (off_t) align);
- rc = phoff + fsz;
+ rc = phoff + (off_t) fsz;
phdr = _libelf_getphdr(e, ec);
- if (!_libelf_insert_extent(extents, ELF_EXTENT_PHDR, phoff,
- fsz, phdr))
+ if (!_libelf_insert_extent(extents, ELF_EXTENT_PHDR,
+ (uint64_t) phoff, fsz, phdr))
return ((off_t) -1);
} else
phoff = 0;
@@ -651,18 +665,18 @@ _libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
align = _libelf_falign(ELF_T_SHDR, ec);
if (e->e_flags & ELF_F_LAYOUT) {
- if (shoff % align) {
+ if (shoff % (off_t) align) {
LIBELF_SET_ERROR(LAYOUT, 0);
return ((off_t) -1);
}
} else
- shoff = roundup(rc, align);
+ shoff = roundup(rc, (off_t) align);
- if (shoff + fsz > (size_t) rc)
- rc = shoff + fsz;
+ if (shoff + (off_t) fsz > rc)
+ rc = shoff + (off_t) fsz;
- if (!_libelf_insert_extent(extents, ELF_EXTENT_SHDR, shoff,
- fsz, NULL))
+ if (!_libelf_insert_extent(extents, ELF_EXTENT_SHDR,
+ (uint64_t) shoff, fsz, NULL))
return ((off_t) -1);
} else
shoff = 0;
@@ -695,21 +709,23 @@ _libelf_resync_elf(Elf *e, struct _Elf_Extent_List *extents)
* Write out the contents of an ELF section.
*/
-static size_t
-_libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
+static off_t
+_libelf_write_scn(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
{
int ec;
- size_t fsz, msz, nobjects, rc;
- uint32_t sh_type;
- uint64_t sh_off, sh_size;
- int elftype;
+ off_t rc;
Elf_Scn *s;
+ int elftype;
Elf_Data *d, dst;
+ uint32_t sh_type;
+ struct _Libelf_Data *ld;
+ uint64_t sh_off, sh_size;
+ size_t fsz, msz, nobjects;
assert(ex->ex_type == ELF_EXTENT_SECTION);
s = ex->ex_desc;
- rc = ex->ex_start;
+ rc = (off_t) ex->ex_start;
if ((ec = e->e_class) == ELFCLASS32) {
sh_type = s->s_shdr.s_shdr32.sh_type;
@@ -744,21 +760,26 @@ _libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
if ((d = elf_rawdata(s, NULL)) == NULL)
return ((off_t) -1);
- STAILQ_FOREACH(d, &s->s_rawdata, d_next) {
+ STAILQ_FOREACH(ld, &s->s_rawdata, d_next) {
+
+ d = &ld->d_data;
+
if ((uint64_t) rc < sh_off + d->d_off)
(void) memset(nf + rc,
- LIBELF_PRIVATE(fillchar), sh_off +
- d->d_off - rc);
- rc = sh_off + d->d_off;
+ LIBELF_PRIVATE(fillchar),
+ (size_t) (sh_off + d->d_off -
+ (uint64_t) rc));
+ rc = (off_t) (sh_off + d->d_off);
assert(d->d_buf != NULL);
assert(d->d_type == ELF_T_BYTE);
assert(d->d_version == e->e_version);
(void) memcpy(nf + rc,
- e->e_rawfile + s->s_rawoff + d->d_off, d->d_size);
+ e->e_rawfile + s->s_rawoff + d->d_off,
+ (size_t) d->d_size);
- rc += d->d_size;
+ rc += (off_t) d->d_size;
}
return (rc);
@@ -772,21 +793,24 @@ _libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
dst.d_version = e->e_version;
- STAILQ_FOREACH(d, &s->s_data, d_next) {
+ STAILQ_FOREACH(ld, &s->s_data, d_next) {
+
+ d = &ld->d_data;
msz = _libelf_msize(d->d_type, ec, e->e_version);
if ((uint64_t) rc < sh_off + d->d_off)
(void) memset(nf + rc,
- LIBELF_PRIVATE(fillchar), sh_off + d->d_off - rc);
+ LIBELF_PRIVATE(fillchar),
+ (size_t) (sh_off + d->d_off - (uint64_t) rc));
- rc = sh_off + d->d_off;
+ rc = (off_t) (sh_off + d->d_off);
assert(d->d_buf != NULL);
assert(d->d_version == e->e_version);
assert(d->d_size % msz == 0);
- nobjects = d->d_size / msz;
+ nobjects = (size_t) (d->d_size / msz);
fsz = _libelf_fsize(d->d_type, ec, e->e_version, nobjects);
@@ -797,10 +821,10 @@ _libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
NULL)
return ((off_t) -1);
- rc += fsz;
+ rc += (off_t) fsz;
}
- return ((off_t) rc);
+ return (rc);
}
/*
@@ -808,7 +832,7 @@ _libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
*/
static off_t
-_libelf_write_ehdr(Elf *e, char *nf, struct _Elf_Extent *ex)
+_libelf_write_ehdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
{
int ec;
void *ehdr;
@@ -849,7 +873,7 @@ _libelf_write_ehdr(Elf *e, char *nf, struct _Elf_Extent *ex)
*/
static off_t
-_libelf_write_phdr(Elf *e, char *nf, struct _Elf_Extent *ex)
+_libelf_write_phdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
{
int ec;
void *ehdr;
@@ -898,7 +922,7 @@ _libelf_write_phdr(Elf *e, char *nf, struct _Elf_Extent *ex)
NULL)
return ((off_t) -1);
- return (phoff + fsz);
+ return ((off_t) (phoff + fsz));
}
/*
@@ -906,7 +930,7 @@ _libelf_write_phdr(Elf *e, char *nf, struct _Elf_Extent *ex)
*/
static off_t
-_libelf_write_shdr(Elf *e, char *nf, struct _Elf_Extent *ex)
+_libelf_write_shdr(Elf *e, unsigned char *nf, struct _Elf_Extent *ex)
{
int ec;
void *ehdr;
@@ -958,7 +982,7 @@ _libelf_write_shdr(Elf *e, char *nf, struct _Elf_Extent *ex)
return ((off_t) -1);
}
- return (ex->ex_start + nscn * fsz);
+ return ((off_t) (ex->ex_start + nscn * fsz));
}
/*
@@ -982,9 +1006,9 @@ static off_t
_libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
{
off_t nrc, rc;
- char *newfile;
Elf_Scn *scn, *tscn;
struct _Elf_Extent *ex;
+ unsigned char *newfile;
assert(e->e_kind == ELF_K_ELF);
assert(e->e_cmd == ELF_C_RDWR || e->e_cmd == ELF_C_WRITE);
@@ -1001,7 +1025,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
/* Fill inter-extent gaps. */
if (ex->ex_start > (size_t) rc)
(void) memset(newfile + rc, LIBELF_PRIVATE(fillchar),
- ex->ex_start - rc);
+ (size_t) (ex->ex_start - (uint64_t) rc));
switch (ex->ex_type) {
case ELF_EXTENT_EHDR:
@@ -1047,6 +1071,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
LIBELF_SET_ERROR(IO, errno);
goto error;
}
+#if ELFTC_HAVE_MMAP
if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
assert(e->e_rawfile != NULL);
assert(e->e_cmd == ELF_C_RDWR);
@@ -1055,6 +1080,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
goto error;
}
}
+#endif
}
/*
@@ -1071,21 +1097,26 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
*/
if (e->e_cmd == ELF_C_RDWR) {
assert(e->e_rawfile != NULL);
- if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
+ assert((e->e_flags & LIBELF_F_RAWFILE_MALLOC) ||
+ (e->e_flags & LIBELF_F_RAWFILE_MMAP));
+ if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) {
+ free(e->e_rawfile);
+ e->e_rawfile = newfile;
+ newfile = NULL;
+ }
+#if ELFTC_HAVE_MMAP
+ else if (e->e_flags & LIBELF_F_RAWFILE_MMAP) {
if ((e->e_rawfile = mmap(NULL, (size_t) newsize,
PROT_READ, MAP_PRIVATE, e->e_fd, (off_t) 0)) ==
MAP_FAILED) {
LIBELF_SET_ERROR(IO, errno);
goto error;
}
- } else if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) {
- free(e->e_rawfile);
- e->e_rawfile = newfile;
- newfile = NULL;
}
+#endif /* ELFTC_HAVE_MMAP */
/* Record the new size of the file. */
- e->e_rawsize = newsize;
+ e->e_rawsize = (size_t) newsize;
} else {
/* File opened in ELF_C_WRITE mode. */
assert(e->e_rawfile == NULL);
@@ -1176,7 +1207,7 @@ elf_update(Elf *e, Elf_Cmd c)
goto done;
}
- return (_libelf_write_elf(e, rc, &extents));
+ rc = _libelf_write_elf(e, rc, &extents);
done:
_libelf_release_extents(&extents);