From owner-svn-src-stable-8@FreeBSD.ORG Sat Sep 4 13:13:01 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 3B31F10656D4; Sat, 4 Sep 2010 13:13:01 +0000 (UTC) (envelope-from kaiw@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 280B68FC16; Sat, 4 Sep 2010 13:13:01 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o84DD1DL010593; Sat, 4 Sep 2010 13:13:01 GMT (envelope-from kaiw@svn.freebsd.org) Received: (from kaiw@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o84DD0rP010578; Sat, 4 Sep 2010 13:13:00 GMT (envelope-from kaiw@svn.freebsd.org) Message-Id: <201009041313.o84DD0rP010578@svn.freebsd.org> From: Kai Wang Date: Sat, 4 Sep 2010 13:13:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212208 - stable/8/lib/libelf X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 04 Sep 2010 13:13:01 -0000 Author: kaiw Date: Sat Sep 4 13:13:00 2010 New Revision: 212208 URL: http://svn.freebsd.org/changeset/base/212208 Log: MFC r210331-r210333,r210335,r210336,r210338,r210340,r210341,r210559. r210331: Add a new ELF type denoting GNU style hash tables. r210332: Changes for supporting GNU Hash sections. r210333: Note that the *_fsize() functions are only defined for ELF types that have a fixed size. r210335: - Return zero for file sizes of ELF types that have a variable size. - Neaten a few comments. r210336: Reduce verbosity. r210338: Perform additional checks when translating between file and memory representations of ELF types. The ELF(3) API allows applications to request a conversion that is `in-place', i.e., with source and destinations data buffers being the same. However, the file and memory sizes of ELF sections that have additional internal structure, such as those of type `Elf_Note', or `Elf_GNU_Hash_Header', can be determined only known after the type-specific headers that comprise the first few words in these sections are read and translated. Pass in the size of destination buffer to type translation routines in "libelf_convert.m4" and have these routines return an error code if the translated data would not fit inside the destination buffer. r210340: - Document that the *fsize() functions return a size of 1 for Elf types that don't have a fixed size. - The *fsize() functions should return a size of 1, for variable length types. - Redefine symbol ELF_T_LAST to match the current end of the list. r210341: Add support for translating sections of type ELF_T_GNUHASH. r210559: Protect GNUHASH translation functions with #ifdef; unbreak cross toolchain build. Modified: stable/8/lib/libelf/_libelf.h stable/8/lib/libelf/elf_data.c stable/8/lib/libelf/elf_scn.c stable/8/lib/libelf/elf_types.m4 stable/8/lib/libelf/gelf_fsize.3 stable/8/lib/libelf/libelf.h stable/8/lib/libelf/libelf_align.c stable/8/lib/libelf/libelf_convert.m4 stable/8/lib/libelf/libelf_data.c stable/8/lib/libelf/libelf_ehdr.c stable/8/lib/libelf/libelf_fsize.m4 stable/8/lib/libelf/libelf_msize.m4 stable/8/lib/libelf/libelf_phdr.c stable/8/lib/libelf/libelf_xlate.c Directory Properties: stable/8/lib/libelf/ (props changed) Modified: stable/8/lib/libelf/_libelf.h ============================================================================== --- stable/8/lib/libelf/_libelf.h Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/_libelf.h Sat Sep 4 13:13:00 2010 (r212208) @@ -175,8 +175,8 @@ void *_libelf_ehdr(Elf *_e, int _elfclas int _libelf_falign(Elf_Type _t, int _elfclass); size_t _libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version, size_t count); -void (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass)) - (char *_dst, char *_src, size_t _cnt, int _byteswap); +int (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass)) + (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap); void *_libelf_getphdr(Elf *_e, int _elfclass); void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass); void _libelf_init_elf(Elf *_e, Elf_Kind _kind); Modified: stable/8/lib/libelf/elf_data.c ============================================================================== --- stable/8/lib/libelf/elf_data.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/elf_data.c Sat Sep 4 13:13:00 2010 (r212208) @@ -43,7 +43,7 @@ elf_getdata(Elf_Scn *s, Elf_Data *d) int elfclass, elftype; unsigned int sh_type; uint64_t sh_align, sh_offset, sh_size; - void (*xlate)(char *_d, char *_s, size_t _c, int _swap); + int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); if (s == NULL || (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF || (d != NULL && s != d->d_scn)) { @@ -125,11 +125,16 @@ elf_getdata(Elf_Scn *s, Elf_Data *d) } d->d_flags |= LIBELF_F_MALLOCED; - STAILQ_INSERT_TAIL(&s->s_data, d, d_next); xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass); - (*xlate)(d->d_buf, e->e_rawfile + sh_offset, count, e->e_byteorder != - LIBELF_PRIVATE(byteorder)); + if (!(*xlate)(d->d_buf, d->d_size, e->e_rawfile + sh_offset, count, + e->e_byteorder != LIBELF_PRIVATE(byteorder))) { + _libelf_release_data(d); + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } + + STAILQ_INSERT_TAIL(&s->s_data, d, d_next); return (d); } Modified: stable/8/lib/libelf/elf_scn.c ============================================================================== --- stable/8/lib/libelf/elf_scn.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/elf_scn.c Sat Sep 4 13:13:00 2010 (r212208) @@ -48,7 +48,7 @@ _libelf_load_scn(Elf *e, void *ehdr) Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; Elf_Scn *scn; - void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + int (*xlator)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); assert(e != NULL); assert(ehdr != NULL); @@ -101,7 +101,8 @@ _libelf_load_scn(Elf *e, void *ehdr) if ((scn = _libelf_allocate_scn(e, i)) == NULL) return (0); - (*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes); + (*xlator)((char *) &scn->s_shdr, sizeof(scn->s_shdr), src, + (size_t) 1, swapbytes); if (ec == ELFCLASS32) { scn->s_offset = scn->s_rawoff = Modified: stable/8/lib/libelf/elf_types.m4 ============================================================================== --- stable/8/lib/libelf/elf_types.m4 Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/elf_types.m4 Sat Sep 4 13:13:00 2010 (r212208) @@ -46,6 +46,7 @@ define(`ELF_TYPE_LIST', `CAP, Cap, 700025', `DYN, Dyn, 600102', `EHDR, Ehdr, 600102', + `GNUHASH, -, 800062', `HALF, Half, 600102', `LWORD, Lword, 700025', `MOVE, Move, 700025', Modified: stable/8/lib/libelf/gelf_fsize.3 ============================================================================== --- stable/8/lib/libelf/gelf_fsize.3 Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/gelf_fsize.3 Sat Sep 4 13:13:00 2010 (r212208) @@ -47,6 +47,8 @@ These functions return the size in bytes .Ar count numbers of objects of ELF type .Ar type . +For ELF types that are of variable length, these functions return a +size of one byte. .Pp Functions .Fn elf32_fsize Modified: stable/8/lib/libelf/libelf.h ============================================================================== --- stable/8/lib/libelf/libelf.h Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf.h Sat Sep 4 13:13:00 2010 (r212208) @@ -75,11 +75,12 @@ typedef enum { ELF_T_VNEED, ELF_T_WORD, ELF_T_XWORD, + ELF_T_GNUHASH, /* GNU style hash tables. */ ELF_T_NUM } Elf_Type; #define ELF_T_FIRST ELF_T_ADDR -#define ELF_T_LAST ELF_T_XWORD +#define ELF_T_LAST ELF_T_GNUHASH /* Commands */ typedef enum { Modified: stable/8/lib/libelf/libelf_align.c ============================================================================== --- stable/8/lib/libelf/libelf_align.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_align.c Sat Sep 4 13:13:00 2010 (r212208) @@ -51,6 +51,10 @@ struct align { .a32 = 0, \ .a64 = __alignof__(Elf64_##V) \ } +#define MALIGN_WORD() { \ + .a32 = __alignof__(int32_t), \ + .a64 = __alignof__(int64_t) \ + } #else #error Need the __alignof__ builtin. #endif @@ -92,7 +96,10 @@ static struct align malign[ELF_T_NUM] = [ELF_T_VNEED] = MALIGN(Verneed), #endif [ELF_T_WORD] = MALIGN(Word), - [ELF_T_XWORD] = MALIGN64(Xword) + [ELF_T_XWORD] = MALIGN64(Xword), +#if __FreeBSD_version >= 800062 + [ELF_T_GNUHASH] = MALIGN_WORD() +#endif }; int @@ -140,7 +147,10 @@ static struct align falign[ELF_T_NUM] = [ELF_T_VNEED] = FALIGN(4,4), #endif [ELF_T_WORD] = FALIGN(4,4), - [ELF_T_XWORD] = FALIGN(0,8) + [ELF_T_XWORD] = FALIGN(0,8), +#if __FreeBSD_version >= 800062 + [ELF_T_GNUHASH] = FALIGN(4,8) +#endif }; int Modified: stable/8/lib/libelf/libelf_convert.m4 ============================================================================== --- stable/8/lib/libelf/libelf_convert.m4 Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_convert.m4 Sat Sep 4 13:13:00 2010 (r212208) @@ -234,8 +234,10 @@ define(`IGNORE', IGNORE(MOVEP) IGNORE(NOTE) +IGNORE(GNUHASH) define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ +define(IGNORE_GNUHASH, 1) define(IGNORE_NOTE, 1) define(IGNORE_SXWORD32, 1) define(IGNORE_XWORD32, 1) @@ -274,18 +276,18 @@ define(`SIZEDEP_OFF', 1) * `$4': ELF class specifier for types, one of [`32', `64'] */ define(`MAKEPRIM_TO_F',` -static void -libelf_cvt_$1$3_tof(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt_$1$3_tof(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { Elf$4_$2 t, *s = (Elf$4_$2 *) (uintptr_t) src; size_t c; - if (dst == src && !byteswap) - return; + (void) dsz; if (!byteswap) { (void) memcpy(dst, src, count * sizeof(*s)); - return; + return (1); } for (c = 0; c < count; c++) { @@ -293,22 +295,25 @@ libelf_cvt_$1$3_tof(char *dst, char *src SWAP_$1$3(t); WRITE_$1$3(dst,t); } + + return (1); } ') define(`MAKEPRIM_TO_M',` -static void -libelf_cvt_$1$3_tom(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt_$1$3_tom(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { Elf$4_$2 t, *d = (Elf$4_$2 *) (uintptr_t) dst; size_t c; - if (dst == src && !byteswap) - return; + if (dsz < count * sizeof(Elf$4_$2)) + return (0); if (!byteswap) { (void) memcpy(dst, src, count * sizeof(*d)); - return; + return (1); } for (c = 0; c < count; c++) { @@ -316,6 +321,8 @@ libelf_cvt_$1$3_tom(char *dst, char *src SWAP_$1$3(t); *d++ = t; } + + return (1); } ') @@ -392,12 +399,15 @@ define(`READ_STRUCT', define(`MAKE_TO_F', `ifdef(`IGNORE_'$1$3,`',` -static void -libelf_cvt$3_$1_tof(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt$3_$1_tof(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { Elf$3_$2 t, *s; size_t c; + (void) dsz; + s = (Elf$3_$2 *) (uintptr_t) src; for (c = 0; c < count; c++) { t = *s++; @@ -406,13 +416,16 @@ libelf_cvt$3_$1_tof(char *dst, char *src } WRITE_STRUCT($2,$3) } + + return (1); } ')') define(`MAKE_TO_M', `ifdef(`IGNORE_'$1$3,`',` -static void -libelf_cvt$3_$1_tom(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt$3_$1_tom(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { Elf$3_$2 t, *d; char *s,*s0; @@ -422,6 +435,9 @@ libelf_cvt$3_$1_tom(char *dst, char *src d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); s0 = (char *) src + (count - 1) * fsz; + if (dsz < count * sizeof(Elf$3_$2)) + return (0); + while (count--) { s = s0; READ_STRUCT($2,$3) @@ -430,6 +446,8 @@ libelf_cvt$3_$1_tom(char *dst, char *src } *d-- = t; s0 -= fsz; } + + return (1); } ')') @@ -475,84 +493,300 @@ divert(0) * simple memcpy suffices for both directions of conversion. */ -static void -libelf_cvt_BYTE_tox(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt_BYTE_tox(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { (void) byteswap; + if (dsz < count) + return (0); if (dst != src) (void) memcpy(dst, src, count); + return (1); } +MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) + +#if __FreeBSD_version >= 800062 +/* + * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit + * words. Bloom filter data comes next, followed by hash buckets and the + * hash chain. + * + * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit + * wide on ELFCLASS32 objects. The other objects in this section are 32 + * bits wide. + * + * Argument `srcsz' denotes the number of bytes to be converted. In the + * 32-bit case we need to translate `srcsz' to a count of 32-bit words. + */ + +static int +libelf_cvt32_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz, + int byteswap) +{ + return (libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t), + byteswap)); +} + +static int +libelf_cvt32_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz, + int byteswap) +{ + return (libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t), + byteswap)); +} + +static int +libelf_cvt64_GNUHASH_tom(char *dst, size_t dsz, char *src, size_t srcsz, + int byteswap) +{ + size_t sz; + uint64_t t64, *bloom64; + Elf_GNU_Hash_Header *gh; + uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32; + uint32_t *buckets, *chains; + + sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */ + if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz) + return (0); + + /* Read in the section header and byteswap if needed. */ + READ_WORD(src, nbuckets); + READ_WORD(src, symndx); + READ_WORD(src, maskwords); + READ_WORD(src, shift2); + + srcsz -= sz; + + if (byteswap) { + SWAP_WORD(nbuckets); + SWAP_WORD(symndx); + SWAP_WORD(maskwords); + SWAP_WORD(shift2); + } + + /* Check source buffer and destination buffer sizes. */ + sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t); + if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header)) + return (0); + + gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst; + gh->gh_nbuckets = nbuckets; + gh->gh_symndx = symndx; + gh->gh_maskwords = maskwords; + gh->gh_shift2 = shift2; + + dsz -= sizeof(Elf_GNU_Hash_Header); + dst += sizeof(Elf_GNU_Hash_Header); + + bloom64 = (uint64_t *) (uintptr_t) dst; + + /* Copy bloom filter data. */ + for (n = 0; n < maskwords; n++) { + READ_XWORD(src, t64); + if (byteswap) + SWAP_XWORD(t64); + bloom64[n] = t64; + } + + /* The hash buckets follows the bloom filter. */ + dst += maskwords * sizeof(uint64_t); + buckets = (uint32_t *) (uintptr_t) dst; + + for (n = 0; n < nbuckets; n++) { + READ_WORD(src, t32); + if (byteswap) + SWAP_WORD(t32); + buckets[n] = t32; + } + + dst += nbuckets * sizeof(uint32_t); + + /* The hash chain follows the hash buckets. */ + dsz -= sz; + srcsz -= sz; + + if (dsz < srcsz) /* Destination lacks space. */ + return (0); + + nchains = srcsz / sizeof(uint32_t); + chains = (uint32_t *) (uintptr_t) dst; + + for (n = 0; n < nchains; n++) { + READ_WORD(src, t32); + if (byteswap) + SWAP_WORD(t32); + *chains++ = t32; + } + + return (1); +} + +static int +libelf_cvt64_GNUHASH_tof(char *dst, size_t dsz, char *src, size_t srcsz, + int byteswap) +{ + uint32_t *s32; + size_t sz, hdrsz; + uint64_t *s64, t64; + Elf_GNU_Hash_Header *gh; + uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32; + + hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */ + if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header)) + return (0); + + gh = (Elf_GNU_Hash_Header *) (uintptr_t) src; + + t0 = nbuckets = gh->gh_nbuckets; + t1 = gh->gh_symndx; + t2 = maskwords = gh->gh_maskwords; + t3 = gh->gh_shift2; + + src += sizeof(Elf_GNU_Hash_Header); + srcsz -= sizeof(Elf_GNU_Hash_Header); + dsz -= hdrsz; + + sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords * + sizeof(uint64_t); + + if (srcsz < sz || dsz < sz) + return (0); + + /* Write out the header. */ + if (byteswap) { + SWAP_WORD(t0); + SWAP_WORD(t1); + SWAP_WORD(t2); + SWAP_WORD(t3); + } + + WRITE_WORD(dst, t0); + WRITE_WORD(dst, t1); + WRITE_WORD(dst, t2); + WRITE_WORD(dst, t3); + + /* Copy the bloom filter and the hash table. */ + s64 = (uint64_t *) (uintptr_t) src; + for (n = 0; n < maskwords; n++) { + t64 = *s64++; + if (byteswap) + SWAP_XWORD(t64); + WRITE_WORD64(dst, t64); + } + + s32 = (uint32_t *) s64; + for (n = 0; n < nbuckets; n++) { + t32 = *s32++; + if (byteswap) + SWAP_WORD(t32); + WRITE_WORD(dst, t32); + } + + srcsz -= sz; + dsz -= sz; + + /* Copy out the hash chains. */ + if (dsz < srcsz) + return (0); + + nchains = srcsz / sizeof(uint32_t); + for (n = 0; n < nchains; n++) { + t32 = *s32++; + if (byteswap) + SWAP_WORD(t32); + WRITE_WORD(dst, t32); + } + + return (1); +} +#endif + /* * Elf_Note structures comprise a fixed size header followed by variable * length strings. The fixed size header needs to be byte swapped, but * not the strings. * * Argument `count' denotes the total number of bytes to be converted. + * The destination buffer needs to be at least `count' bytes in size. */ -static void -libelf_cvt_NOTE_tom(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { uint32_t namesz, descsz, type; Elf_Note *en; - size_t sz; + size_t sz, hdrsz; - if (dst == src && !byteswap) - return; + if (dsz < count) /* Destination buffer is too small. */ + return (0); + + hdrsz = 3 * sizeof(uint32_t); + if (count < hdrsz) /* Source too small. */ + return (0); if (!byteswap) { (void) memcpy(dst, src, count); - return; + return (1); } - while (count > sizeof(Elf_Note)) { - + /* Process all notes in the section. */ + while (count > hdrsz) { + /* Read the note header. */ READ_WORD(src, namesz); READ_WORD(src, descsz); READ_WORD(src, type); - if (byteswap) { - SWAP_WORD(namesz); - SWAP_WORD(descsz); - SWAP_WORD(type); - } + /* Translate. */ + SWAP_WORD(namesz); + SWAP_WORD(descsz); + SWAP_WORD(type); + /* Copy out the translated note header. */ en = (Elf_Note *) (uintptr_t) dst; en->n_namesz = namesz; en->n_descsz = descsz; en->n_type = type; + dsz -= sizeof(Elf_Note); dst += sizeof(Elf_Note); + count -= hdrsz; ROUNDUP2(namesz, 4); ROUNDUP2(descsz, 4); sz = namesz + descsz; - if (count < sz) - sz = count; + if (count < sz || dsz < sz) /* Buffers are too small. */ + return (0); (void) memcpy(dst, src, sz); src += sz; dst += sz; + count -= sz; + dsz -= sz; } + + return (1); } -static void -libelf_cvt_NOTE_tof(char *dst, char *src, size_t count, int byteswap) +static int +libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count, + int byteswap) { uint32_t namesz, descsz, type; Elf_Note *en; size_t sz; - if (dst == src && !byteswap) - return; + if (dsz < count) + return (0); if (!byteswap) { (void) memcpy(dst, src, count); - return; + return (1); } while (count > sizeof(Elf_Note)) { @@ -562,12 +796,9 @@ libelf_cvt_NOTE_tof(char *dst, char *src descsz = en->n_descsz; type = en->n_type; - if (byteswap) { - SWAP_WORD(namesz); - SWAP_WORD(descsz); - SWAP_WORD(type); - } - + SWAP_WORD(namesz); + SWAP_WORD(descsz); + SWAP_WORD(type); WRITE_WORD(dst, namesz); WRITE_WORD(dst, descsz); @@ -589,15 +820,19 @@ libelf_cvt_NOTE_tof(char *dst, char *src dst += sz; count -= sz; } -} -MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) + return (1); +} struct converters { - void (*tof32)(char *dst, char *src, size_t cnt, int byteswap); - void (*tom32)(char *dst, char *src, size_t cnt, int byteswap); - void (*tof64)(char *dst, char *src, size_t cnt, int byteswap); - void (*tom64)(char *dst, char *src, size_t cnt, int byteswap); + int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt, + int byteswap); + int (*tom32)(char *dst, size_t dsz, char *src, size_t cnt, + int byteswap); + int (*tof64)(char *dst, size_t dsz, char *src, size_t cnt, + int byteswap); + int (*tom64)(char *dst, size_t dsz, char *src, size_t cnt, + int byteswap); }; divert(-1) @@ -639,6 +874,16 @@ CONVERTER_NAMES(ELF_TYPE_LIST) .tof64 = libelf_cvt_BYTE_tox, .tom64 = libelf_cvt_BYTE_tox }, + +#if __FreeBSD_version >= 800062 + [ELF_T_GNUHASH] = { + .tof32 = libelf_cvt32_GNUHASH_tof, + .tom32 = libelf_cvt32_GNUHASH_tom, + .tof64 = libelf_cvt64_GNUHASH_tof, + .tom64 = libelf_cvt64_GNUHASH_tom + }, +#endif + [ELF_T_NOTE] = { .tof32 = libelf_cvt_NOTE_tof, .tom32 = libelf_cvt_NOTE_tom, @@ -647,8 +892,8 @@ CONVERTER_NAMES(ELF_TYPE_LIST) } }; -void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) - (char *_dst, char *_src, size_t _cnt, int _byteswap) +int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) + (char *_dst, size_t dsz, char *_src, size_t _cnt, int _byteswap) { assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); Modified: stable/8/lib/libelf/libelf_data.c ============================================================================== --- stable/8/lib/libelf/libelf_data.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_data.c Sat Sep 4 13:13:00 2010 (r212208) @@ -42,6 +42,10 @@ _libelf_xlate_shtype(uint32_t sht) return (ELF_T_SYM); case SHT_FINI_ARRAY: return (ELF_T_ADDR); +#if __FreeBSD_version >= 800062 + case SHT_GNU_HASH: + return (ELF_T_GNUHASH); +#endif case SHT_GROUP: return (ELF_T_WORD); case SHT_HASH: Modified: stable/8/lib/libelf/libelf_ehdr.c ============================================================================== --- stable/8/lib/libelf/libelf_ehdr.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_ehdr.c Sat Sep 4 13:13:00 2010 (r212208) @@ -46,7 +46,7 @@ _libelf_load_extended(Elf *e, int ec, ui { Elf_Scn *scn; size_t fsz; - void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + int (*xlator)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); uint32_t shtype; assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); @@ -63,7 +63,8 @@ _libelf_load_extended(Elf *e, int ec, ui return (0); xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); - (*xlator)((char *) &scn->s_shdr, e->e_rawfile + shoff, (size_t) 1, + (*xlator)((char *) &scn->s_shdr, sizeof(scn->s_shdr), + e->e_rawfile + shoff, (size_t) 1, e->e_byteorder != LIBELF_PRIVATE(byteorder)); #define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \ @@ -105,7 +106,7 @@ _libelf_ehdr(Elf *e, int ec, int allocat size_t fsz, msz; uint16_t phnum, shnum, strndx; uint64_t shoff; - void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + int (*xlator)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); assert(ec == ELFCLASS32 || ec == ELFCLASS64); @@ -167,7 +168,7 @@ _libelf_ehdr(Elf *e, int ec, int allocat return (ehdr); xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec); - (*xlator)(ehdr, e->e_rawfile, (size_t) 1, + (*xlator)(ehdr, msz, e->e_rawfile, (size_t) 1, e->e_byteorder != LIBELF_PRIVATE(byteorder)); /* Modified: stable/8/lib/libelf/libelf_fsize.m4 ============================================================================== --- stable/8/lib/libelf/libelf_fsize.m4 Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_fsize.m4 Sat Sep 4 13:13:00 2010 (r212208) @@ -43,15 +43,18 @@ include(SRCDIR`/elf_types.m4') * representations. */ -/* `Basic' types */ +/* `Basic' types. */ define(`BYTE_SIZE', 1) define(`IDENT_SIZE', `EI_NIDENT') -define(`NOTE_SIZE', 1) /* Elf_Note structures have variable length. */ -/* Currently unimplemented types */ +/* Types that have variable length. */ +define(`GNUHASH_SIZE', 1) +define(`NOTE_SIZE', 1) + +/* Currently unimplemented types. */ define(`MOVEP_SIZE', 0) -/* Overrides for 32 bit types that do not exist */ +/* Overrides for 32 bit types that do not exist. */ define(`XWORD_SIZE32', 0) define(`SXWORD_SIZE32', 0) Modified: stable/8/lib/libelf/libelf_msize.m4 ============================================================================== --- stable/8/lib/libelf/libelf_msize.m4 Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_msize.m4 Sat Sep 4 13:13:00 2010 (r212208) @@ -49,6 +49,7 @@ divert(-1) include(SRCDIR`/elf_types.m4') define(BYTE_SIZE, 1) +define(GNUHASH_SIZE, 1) define(NOTE_SIZE, 1) /* Modified: stable/8/lib/libelf/libelf_phdr.c ============================================================================== --- stable/8/lib/libelf/libelf_phdr.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_phdr.c Sat Sep 4 13:13:00 2010 (r212208) @@ -45,7 +45,7 @@ _libelf_getphdr(Elf *e, int ec) Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; void *ehdr, *phdr; - void (*xlator)(char *_d, char *_s, size_t _c, int _swap); + int (*xlator)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap); assert(ec == ELFCLASS32 || ec == ELFCLASS64); @@ -103,7 +103,7 @@ _libelf_getphdr(Elf *e, int ec) xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec); - (*xlator)(phdr, e->e_rawfile + phoff, phnum, + (*xlator)(phdr, phnum * msz, e->e_rawfile + phoff, phnum, e->e_byteorder != LIBELF_PRIVATE(byteorder)); return (phdr); Modified: stable/8/lib/libelf/libelf_xlate.c ============================================================================== --- stable/8/lib/libelf/libelf_xlate.c Sat Sep 4 13:00:28 2010 (r212207) +++ stable/8/lib/libelf/libelf_xlate.c Sat Sep 4 13:13:00 2010 (r212208) @@ -48,6 +48,7 @@ Elf_Data * _libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, int elfclass, int direction) { + int byteswap; size_t cnt, dsz, fsz, msz; uintptr_t sb, se, db, de; @@ -132,12 +133,17 @@ _libelf_xlate(Elf_Data *dst, const Elf_D dst->d_type = src->d_type; dst->d_size = dsz; + byteswap = encoding != LIBELF_PRIVATE(byteorder); + if (src->d_size == 0 || - (db == sb && encoding == LIBELF_PRIVATE(byteorder) && fsz == msz)) + (db == sb && !byteswap && fsz == msz)) return (dst); /* nothing more to do */ - (_libelf_get_translator(src->d_type, direction, elfclass))(dst->d_buf, - src->d_buf, cnt, encoding != LIBELF_PRIVATE(byteorder)); + if (!(_libelf_get_translator(src->d_type, direction, elfclass)) + (dst->d_buf, dsz, src->d_buf, cnt, byteswap)) { + LIBELF_SET_ERROR(DATA, 0); + return (NULL); + } return (dst); }