diff options
author | kaiw <kaiw@FreeBSD.org> | 2010-09-09 18:51:50 +0000 |
---|---|---|
committer | kaiw <kaiw@FreeBSD.org> | 2010-09-09 18:51:50 +0000 |
commit | 18f75881f89be44207befb312f5d2186a126cfaa (patch) | |
tree | a62678f29ad4dfd75799e44f28c34cbf9312d2bc /lib/libelf | |
parent | f2b9e3d89d72552e7139e0a05436a14a599a0328 (diff) | |
download | FreeBSD-src-18f75881f89be44207befb312f5d2186a126cfaa.zip FreeBSD-src-18f75881f89be44207befb312f5d2186a126cfaa.tar.gz |
libelf is overly strict about the type and alignment of Elf_Data
objects inside one ELF section, which prevents the creation of a ELF
section with mixed data types. For example, gcc LTO use libelf to
create a .gnu_lto_XXX section that contains integers and a string
table, which doesn't work with our libelf implementation.
The changes made in this commit include:
* Allow Elf_Data type to be different than section type.
* Relax Elf_Data alignment check.
* Align each Elf_Data by their own alignment instead of section alignment.
MFC after: 1 month
Diffstat (limited to 'lib/libelf')
-rw-r--r-- | lib/libelf/elf_update.c | 17 |
1 files changed, 6 insertions, 11 deletions
diff --git a/lib/libelf/elf_update.c b/lib/libelf/elf_update.c index 69bbaac..5880c07 100644 --- a/lib/libelf/elf_update.c +++ b/lib/libelf/elf_update.c @@ -141,7 +141,7 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) /* Compute the section alignment. */ STAILQ_FOREACH(d, &s->s_data, d_next) { - if (d->d_type != elftype) { + if (d->d_type > ELF_T_LAST) { LIBELF_SET_ERROR(DATA, 0); return (0); } @@ -149,11 +149,7 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) LIBELF_SET_ERROR(VERSION, 0); return (0); } - if ((d_align = d->d_align) % sh_align) { - LIBELF_SET_ERROR(LAYOUT, 0); - return (0); - } - if (d_align == 0 || (d_align & (d_align - 1))) { + if ((d_align = d->d_align) == 0 || (d_align & (d_align - 1))) { LIBELF_SET_ERROR(DATA, 0); return (0); } @@ -168,7 +164,7 @@ _libelf_compute_section_extents(Elf *e, Elf_Scn *s, off_t *rc) if ((uint64_t) d->d_off + d->d_size > scn_size) scn_size = d->d_off + d->d_size; } else { - scn_size = roundup2(scn_size, scn_alignment); + scn_size = roundup2(scn_size, d->d_align); d->d_off = scn_size; scn_size += d->d_size; } @@ -560,8 +556,6 @@ _libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc) elftype = _libelf_xlate_shtype(sh_type); assert(elftype >= ELF_T_FIRST && elftype <= ELF_T_LAST); - msz = _libelf_msize(elftype, ec, e->e_version); - sh_off = s->s_offset; assert(sh_off % _libelf_falign(elftype, ec) == 0); @@ -608,6 +602,8 @@ _libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc) STAILQ_FOREACH(d, &s->s_data, d_next) { + 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); @@ -615,13 +611,12 @@ _libelf_write_scn(Elf *e, char *nf, Elf_Scn *s, off_t rc) rc = sh_off + d->d_off; assert(d->d_buf != NULL); - assert(d->d_type == (Elf_Type) elftype); assert(d->d_version == e->e_version); assert(d->d_size % msz == 0); nobjects = d->d_size / msz; - fsz = _libelf_fsize(elftype, ec, e->e_version, nobjects); + fsz = _libelf_fsize(d->d_type, ec, e->e_version, nobjects); dst.d_buf = nf + rc; dst.d_size = fsz; |