Date: Wed, 21 Jul 2010 10:57:22 +0000 (UTC) From: Kai Wang <kaiw@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r210341 - head/lib/libelf Message-ID: <201007211057.o6LAvMCf095386@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kaiw Date: Wed Jul 21 10:57:22 2010 New Revision: 210341 URL: http://svn.freebsd.org/changeset/base/210341 Log: Add support for translating sections of type ELF_T_GNUHASH. Obtained from: elftoolchain MFC after: 1 month Modified: head/lib/libelf/elf_types.m4 head/lib/libelf/libelf_convert.m4 Modified: head/lib/libelf/elf_types.m4 ============================================================================== --- head/lib/libelf/elf_types.m4 Wed Jul 21 10:39:29 2010 (r210340) +++ head/lib/libelf/elf_types.m4 Wed Jul 21 10:57:22 2010 (r210341) @@ -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: head/lib/libelf/libelf_convert.m4 ============================================================================== --- head/lib/libelf/libelf_convert.m4 Wed Jul 21 10:39:29 2010 (r210340) +++ head/lib/libelf/libelf_convert.m4 Wed Jul 21 10:57:22 2010 (r210341) @@ -234,6 +234,7 @@ define(`IGNORE', IGNORE(MOVEP) IGNORE(NOTE) +IGNORE(GNUHASH) define(IGNORE_BYTE, 1) /* 'lator, leave 'em bytes alone */ define(IGNORE_GNUHASH, 1) @@ -504,12 +505,209 @@ libelf_cvt_BYTE_tox(char *dst, size_t ds return (1); } +MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) + +/* + * 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); +} + /* * 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 int libelf_cvt_NOTE_tom(char *dst, size_t dsz, char *src, size_t count, @@ -567,6 +765,7 @@ libelf_cvt_NOTE_tom(char *dst, size_t ds dst += sz; count -= sz; + dsz -= sz; } return (1); @@ -623,8 +822,6 @@ libelf_cvt_NOTE_tof(char *dst, size_t ds return (1); } -MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) - struct converters { int (*tof32)(char *dst, size_t dsz, char *src, size_t cnt, int byteswap); @@ -675,6 +872,14 @@ CONVERTER_NAMES(ELF_TYPE_LIST) .tof64 = libelf_cvt_BYTE_tox, .tom64 = libelf_cvt_BYTE_tox }, + + [ELF_T_GNUHASH] = { + .tof32 = libelf_cvt32_GNUHASH_tof, + .tom32 = libelf_cvt32_GNUHASH_tom, + .tof64 = libelf_cvt64_GNUHASH_tof, + .tom64 = libelf_cvt64_GNUHASH_tom + }, + [ELF_T_NOTE] = { .tof32 = libelf_cvt_NOTE_tof, .tom32 = libelf_cvt_NOTE_tom,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007211057.o6LAvMCf095386>