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,
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to