aboutsummaryrefslogtreecommitdiff
path: root/libelf/elf_update.c
diff options
context:
space:
mode:
Diffstat (limited to 'libelf/elf_update.c')
-rw-r--r--libelf/elf_update.c117
1 files changed, 64 insertions, 53 deletions
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
index b589233c8e4a..70a7c2e21e25 100644
--- a/libelf/elf_update.c
+++ b/libelf/elf_update.c
@@ -41,7 +41,7 @@
#include <sys/mman.h>
#endif
-ELFTC_VCSID("$Id: elf_update.c 2931 2013-03-23 11:41:07Z jkoshy $");
+ELFTC_VCSID("$Id: elf_update.c 3013 2014-03-23 06:16:59Z jkoshy $");
/*
* Layout strategy:
@@ -110,14 +110,13 @@ SLIST_HEAD(_Elf_Extent_List, _Elf_Extent);
static int
_libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t rc)
{
- int ec;
Elf_Data *d;
size_t fsz, msz;
+ int ec, elftype;
uint32_t sh_type;
uint64_t d_align;
Elf32_Shdr *shdr32;
Elf64_Shdr *shdr64;
- unsigned int elftype;
struct _Libelf_Data *ld;
uint64_t scn_size, scn_alignment;
uint64_t sh_align, sh_entsize, sh_offset, sh_size;
@@ -253,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;
}
@@ -307,7 +306,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.
@@ -471,7 +470,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);
@@ -529,17 +528,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;
+ 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;
+ 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;
@@ -564,18 +568,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)
@@ -585,9 +591,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);
/*
@@ -608,20 +615,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;
@@ -656,18 +663,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;
@@ -700,22 +707,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;
+ 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, rc;
+ 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;
@@ -756,18 +764,20 @@ _libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
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);
@@ -789,15 +799,16 @@ _libelf_write_scn(Elf *e, char *nf, struct _Elf_Extent *ex)
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);
@@ -808,10 +819,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);
}
/*
@@ -819,7 +830,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;
@@ -860,7 +871,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;
@@ -909,7 +920,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));
}
/*
@@ -917,7 +928,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;
@@ -969,7 +980,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));
}
/*
@@ -993,9 +1004,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);
@@ -1012,7 +1023,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:
@@ -1103,7 +1114,7 @@ _libelf_write_elf(Elf *e, off_t newsize, struct _Elf_Extent_List *extents)
#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);