Add support for translating sections of type ELF_T_GNUHASH.
Obtained from: elftoolchain MFC after: 1 month
This commit is contained in:
parent
fff07a4233
commit
1d69e83ddd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=210341
@ -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',
|
||||
|
@ -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 dsz, char *src, size_t count,
|
||||
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 dsz, char *src, size_t count,
|
||||
dst += sz;
|
||||
|
||||
count -= sz;
|
||||
dsz -= sz;
|
||||
}
|
||||
|
||||
return (1);
|
||||
@ -623,8 +822,6 @@ libelf_cvt_NOTE_tof(char *dst, size_t dsz, char *src, size_t count,
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user