Index: _libelf_config.h =================================================================== --- _libelf_config.h (revision 281) +++ _libelf_config.h (working copy) @@ -62,6 +62,7 @@ #define LIBELF_CONFIG_MOVE 1 #define LIBELF_CONFIG_MOVEP 1 #define LIBELF_CONFIG_SYMINFO 1 +#define LIBELF_CONFIG_GNUHASH 1 #endif /* __FreeBSD_version__ >= 700025 */ #define LIBELF_VCSID(ID) __FBSDID(ID) Index: libelf_fsize.m4 =================================================================== --- libelf_fsize.m4 (revision 281) +++ libelf_fsize.m4 (working copy) @@ -46,6 +46,7 @@ /* `Basic' types */ define(`BYTE_SIZE', 1) +define(`GNUHASH_SIZE', 1) define(`IDENT_SIZE', `EI_NIDENT') define(`NOTE_SIZE', 1) /* Elf_Note structures have variable length. */ Index: libelf_align.c =================================================================== --- libelf_align.c (revision 281) +++ libelf_align.c (working copy) @@ -64,6 +64,9 @@ #endif [ELF_T_DYN] = MALIGN(Dyn), [ELF_T_EHDR] = MALIGN(Ehdr), +#if LIBELF_CONFIG_GNUHASH + [ELF_T_GNUHASH] = { .a32 = 4, .a64 = 8 }, +#endif [ELF_T_HALF] = MALIGN(Half), #if LIBELF_CONFIG_LWORD [ELF_T_LWORD] = MALIGN(Lword), @@ -116,6 +119,9 @@ #endif [ELF_T_DYN] = FALIGN(4,8), [ELF_T_EHDR] = FALIGN(4,8), +#if LIBELF_CONFIG_GNUHASH + [ELF_T_GNUHASH] = FALIGN(4,8), +#endif [ELF_T_HALF] = FALIGN(2,2), #if LIBELF_CONFIG_LWORD [ELF_T_LWORD] = FALIGN(8,8), Index: elf_types.m4 =================================================================== --- elf_types.m4 (revision 281) +++ elf_types.m4 (working copy) @@ -40,6 +40,7 @@ `CAP, Cap', `DYN, Dyn', `EHDR, Ehdr', + `GNUHASH, -', `HALF, Half', `LWORD, Lword', `MOVE, Move', Index: libelf.h =================================================================== --- libelf.h (revision 281) +++ libelf.h (working copy) @@ -64,6 +64,7 @@ ELF_T_CAP, ELF_T_DYN, ELF_T_EHDR, + ELF_T_GNUHASH, ELF_T_HALF, ELF_T_LWORD, ELF_T_MOVE, Index: libelf_msize.m4 =================================================================== --- libelf_msize.m4 (revision 281) +++ libelf_msize.m4 (working copy) @@ -45,6 +45,7 @@ include(SRCDIR`/elf_types.m4') define(BYTE_SIZE, 1) +define(GNUHASH_SIZE, 1) define(NOTE_SIZE, 1) /* Index: libelf_data.c =================================================================== --- libelf_data.c (revision 281) +++ libelf_data.c (working copy) @@ -44,6 +44,10 @@ case SHT_FINI_ARRAY: return (ELF_T_ADDR); #endif +#if defined(SHT_GNU_HASH) + case SHT_GNU_HASH: + return (ELF_T_GNUHASH); +#endif #if defined(SHT_GROUP) case SHT_GROUP: return (ELF_T_WORD); Index: libelf_convert.m4 =================================================================== --- libelf_convert.m4 (revision 281) +++ libelf_convert.m4 (working copy) @@ -228,10 +228,12 @@ `define(IGNORE_$1`'32, 1) define(IGNORE_$1`'64, 1)') +IGNORE(GNUHASH) IGNORE(MOVEP) IGNORE(NOTE) 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) @@ -589,6 +591,140 @@ } #endif /* LIBELF_CONFIG_NOTE */ +#if LIBELF_CONFIG_GNUHASH +/* + * GNU-style hash section consists of only 32-bit words in ELFCLASS32 + * objects, while it has mixed element size (64-bit bloom filter words, + * 32-bit header, hash buckets and hash chains words.) for ELFCLASS64 + * objects. + */ +static void +libelf_cvt64_GNUHASH_tom(char *dst, char *src, size_t count, int byteswap) +{ + uint32_t nbuckets, symndx, maskwords, shift2, t1, i; + uint32_t *header, *bc; + uint64_t *bloom, t2; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count); + return; + } + + if (count >= 4 * sizeof(uint32_t)) { + READ_WORD(src, nbuckets); + READ_WORD(src, symndx); + READ_WORD(src, maskwords); + READ_WORD(src, shift2); + count -= 4 * sizeof(uint32_t); + } else + return; + + SWAP_WORD(nbuckets); + SWAP_WORD(symndx); + SWAP_WORD(maskwords); + SWAP_WORD(shift2); + + header = (uint32_t *) (uintptr_t) dst; + header[0] = nbuckets; + header[1] = symndx; + header[2] = maskwords; + header[3] = shift2; + + if (count <= 0) + return; + + dst += 4 * sizeof(uint32_t); + bloom = (uint64_t *) (uintptr_t) dst; + + for (i = 0; count > 0 && i < maskwords; i++) { + READ_XWORD(src, t2); + SWAP_XWORD(t2); + bloom[i] = t2; + count -= sizeof(uint64_t); + } + + if (count <= 0) + return; + + /* The rest (buckets + chains) are all 32bit values. */ + dst += maskwords * sizeof(uint64_t); + bc = (uint32_t *) (uintptr_t) dst; + + while (count > 0) { + READ_WORD(src, t1); + SWAP_WORD(t1); + *bc++ = t1; + count -= sizeof(uint32_t); + } +} + +static void +libelf_cvt64_GNUHASH_tof(char *dst, char *src, size_t count, int byteswap) +{ + uint32_t nbuckets, symndx, maskwords, mw, shift2, t1, i; + uint32_t *header, *bc; + uint64_t *bloom, t2; + + if (dst == src && !byteswap) + return; + + if (!byteswap) { + (void) memcpy(dst, src, count); + return; + } + + header = (uint32_t *) (uintptr_t) src; + nbuckets = header[0]; + symndx = header[1]; + mw = maskwords = header[2]; + shift2 = header[3]; + + SWAP_WORD(nbuckets); + SWAP_WORD(symndx); + SWAP_WORD(maskwords); + SWAP_WORD(shift2); + + if (count >= 4 * sizeof(uint32_t)) { + WRITE_WORD(dst, nbuckets); + WRITE_WORD(dst, symndx); + WRITE_WORD(dst, maskwords); + WRITE_WORD(dst, shift2); + count -= 4 * sizeof(uint32_t); + } else + return; + + if (count <= 0) + return; + + src += 4 * sizeof(uint32_t); + + bloom = (uint64_t *) (uintptr_t) src; + for (i = 0; count > 0 && i < mw; i++) { + t2 = bloom[i]; + SWAP_XWORD(t2); + WRITE_XWORD(dst, t2); + count -= sizeof(uint64_t); + } + + if (count <= 0) + return; + + /* The rest (buckets + chains) are all 32bit values. */ + src += mw * sizeof(uint64_t); + bc = (uint32_t *) (uintptr_t) src; + + while (count > 0) { + t1 = *bc++; + SWAP_WORD(t1); + WRITE_WORD(dst, t1); + count -= sizeof(uint32_t); + } +} +#endif /* LIBELF_CONFIG_GNUHASH */ + MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) struct converters { @@ -643,8 +779,16 @@ .tom32 = libelf_cvt_NOTE_tom, .tof64 = libelf_cvt_NOTE_tof, .tom64 = libelf_cvt_NOTE_tom + }, +#endif /* LIBELF_CONFIG_NOTE */ +#if LIBELF_CONFIG_GNUHASH + [ELF_T_GNUHASH] = { + .tof32 = libelf_cvt_WORD_tof, + .tom32 = libelf_cvt_WORD_tom, + .tof64 = libelf_cvt64_GNUHASH_tof, + .tom64 = libelf_cvt64_GNUHASH_tom } -#endif /* LIBELF_CONFIG_NOTE */ +#endif /* LIBELF_CONFIG_GNUHASH */ }; void (*_libelf_get_translator(Elf_Type t, int direction, int elfclass))