--- /dev/null
+/*DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64
+
+ D r . D e a m o n 6 4
+ for INTEL64(R), AMD64(R)
+
+ Copyright(C) 2007-2009 Koine Yuusuke(koinec). All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY Koine Yuusuke(koinec) ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Koine Yuusuke(koinec) OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64*/
+
+/* File Info -----------------------------------------------------------
+File: drd64_.c
+Function:
+Comment:
+----------------------------------------------------------------------*/
+
+#define DRD64_SRC_LIBGOBLIN_ELF_HASH
+#include"drd64_libgoblin.h"
+
+
+/*----------------------------------------------------------------------
+ .gnu.hash Section Analye Information from the following site.
+ * Oracle Solaris Blog
+ - GNU Hash Elf Section by Ali Bahrami, PRINCIPAL SOFTWARE ENGINEER
+ (https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2)
+ * ELF: better symbol lookup via DT_GNU_HASH by FLAPENGUIN
+ (https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/)
+ Thanks!!
+----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+----------------------------------------------------------------------*/
+// typedef struct {
+// const char *os_dynstr; // Dynamic string table
+// Sym *os_dynsym; // Dynamic symbol table
+// Word os_nbuckets; // # hash buckets
+// Word os_symndx; // Index of 1st dynsym in hash
+// Word os_maskwords_bm; // # Bloom filter words, minus 1
+// Word os_shift2; // Bloom filter hash shift
+// const BloomWord *os_bloom; // Bloom filter words
+// const Word *os_buckets; // Hash buckets
+// const Word *os_hashval; // Hash value array
+// } obj_state_t;
+
+LIBGOBLIN_ELF_HASH_EXTERN
+int
+ ELF64_GnuHash_SearchDynSym(
+ LibGoblin_BinaryInfo *p_binfo,
+ char *pstr_symname )
+{
+ int i_ret = -0x0f;
+ Byte *pb_dynstr;
+ Byte *pb_dynsym;
+ Byte *pb_gnuhash;
+ DWord dw_nbuckets;
+ DWord dw_symoffset;
+ DWord dw_bloom_sz;
+ DWord dw_bloom_shift;
+ QWord *pqw_bloom;
+ DWord *pdw_buckets;
+ DWord *pdw_chain;
+ LibGoblin_SectionInfo *psec_gnuhash;
+ LibGoblin_SectionInfo *psec_dynsym;
+ LibGoblin_SectionInfo *psec_dynstr;
+ Elf64_Sym *p_dynsym;
+ Elf64_Sym *p_symnow; //const Sym *sym;
+
+ DWord dw_namehash;
+ QWord qw_word;
+ QWord qw_mask;
+ DWord dw_symix;
+ DWord dw_hash;
+ char *pstr_dynname;
+
+ psec_dynsym = LibGoblin_Section_GetSectionInfo_fid(
+ p_binfo, LIBGOBLIN_SECTION_ID_DYNSYM );
+ if( NULL == psec_dynsym ) {
+ return -0x01;
+ }
+ pb_dynsym = psec_dynsym->pb_data;
+ p_dynsym = (Elf64_Sym *)pb_dynsym;
+
+ psec_dynstr = LibGoblin_Section_GetSectionInfo_fid(
+ p_binfo, LIBGOBLIN_SECTION_ID_DYNSTR );
+ if( NULL == psec_dynstr ) {
+ return -0x01;
+ }
+ pb_dynstr = psec_dynstr->pb_data;
+
+ psec_gnuhash = LibGoblin_Section_GetSectionInfo_fid(
+ p_binfo, LIBGOBLIN_SECTION_ID_GNU_HASH );
+ if( NULL == psec_gnuhash ) {
+ return -0x01;
+ }
+ pb_gnuhash = psec_gnuhash->pb_data;
+
+ dw_nbuckets = *((DWord *)(pb_gnuhash));
+ dw_symoffset = *((DWord *)(pb_gnuhash + 4));
+ dw_bloom_sz = *((DWord *)(pb_gnuhash + 8));
+ dw_bloom_shift = *((DWord *)(pb_gnuhash + 12));
+ pqw_bloom = (QWord *)(pb_gnuhash + 16);
+ pdw_buckets = (DWord *)(pb_gnuhash + (sizeof(QWord) * dw_bloom_sz) + 16);
+ pdw_chain = (DWord *)(pb_gnuhash + (sizeof(QWord) * dw_bloom_sz)
+ + (sizeof(DWord) * dw_nbuckets) + 16);
+
+printf(" [GNUHASH] nbuckets= %ld, symoffset= %ld, BloomSize= %ld, BloomShift= %ld\n",
+ dw_nbuckets, dw_symoffset, dw_bloom_sz, dw_bloom_shift );
+
+ dw_namehash = Common_CalcDJBhash( pstr_symname );
+ qw_word = *(pqw_bloom + ((dw_namehash / 64) % dw_bloom_sz));
+ qw_mask = 0x00 | ((QWord)0x01 << (dw_namehash % 64)) | ((QWord)0x01 << ((dw_namehash >> dw_bloom_shift) % 64));
+printf(" [GNUHASH] namehash= %08xh, word=%16lx, mask=%16lx and=%16lx\n",
+ dw_namehash, qw_word, qw_mask, (qw_word & qw_mask) );
+
+ if((qw_word & qw_mask) != qw_mask) { return -0x02; }
+
+ dw_symix = *(pdw_buckets + (dw_namehash % dw_nbuckets));
+ if( dw_symix < dw_symoffset ) { return -0x03; }
+
+ while( 1 ) {
+ p_symnow = (p_dynsym + dw_symix);
+ pstr_dynname = (char *)(pb_dynstr + p_symnow->st_name);
+
+ dw_hash = *(pdw_chain + (dw_symix - dw_symoffset));
+
+
+ if(((dw_namehash | 1) == (dw_hash | 1)) && !strcmp(pstr_dynname, pstr_symname)) {
+ i_ret = dw_symix & 0x7fffffff;
+ break;
+ }
+
+ if( dw_hash & 1 ) { break; }
+
+ dw_symix++;
+ }
+
+
+ return i_ret;
+}
+
+
+
+/*----------------------------------------------------------------------
+----------------------------------------------------------------------*/
+// typedef struct {
+// const char *os_dynstr; // Dynamic string table
+// Sym *os_dynsym; // Dynamic symbol table
+// Word os_nbuckets; // # hash buckets
+// Word os_symndx; // Index of 1st dynsym in hash
+// Word os_maskwords_bm; // # Bloom filter words, minus 1
+// Word os_shift2; // Bloom filter hash shift
+// const BloomWord *os_bloom; // Bloom filter words
+// const Word *os_buckets; // Hash buckets
+// const Word *os_hashval; // Hash value array
+// } obj_state_t;
+/*
+LIBGOBLIN_ELF_HASH_EXTERN
+int
+ ELF64_GnuHash_SearchDynSym(
+ LibGoblin_BinaryInfo *p_binfo,
+ char *pstr_symname )
+{
+ int i_ret = -0x0f;
+ Byte *pb_dynstr;
+ Byte *pb_dynsym;
+ Byte *pb_gnuhash;
+ DWord dw_nbuckets;
+ DWord dw_symoffset;
+ DWord dw_bloom_sz;
+ DWord dw_bloom_shift;
+ DWord dw_hash1; //Word h1;
+ DWord dw_hash2; //Word h2;
+ DWord dw_c; //Word c;
+ DWord dw_n; //Word n;
+ DWord dw_bitmask; //Word bitmask;
+ QWord *pqw_bloom;
+ DWord *pdw_buckets;
+ DWord *pdw_chain;
+ DWord *pdw_hashval; //Word *hashval;
+ LibGoblin_SectionInfo *psec_gnuhash;
+ LibGoblin_SectionInfo *psec_dynsym;
+ LibGoblin_SectionInfo *psec_dynstr;
+ Elf64_Sym *p_dynsym;
+ Elf64_Sym *p_symnow; //const Sym *sym;
+
+ psec_dynsym = LibGoblin_Section_GetSectionInfo_fid(
+ p_binfo, LIBGOBLIN_SECTION_ID_DYNSYM );
+ if( NULL == psec_dynsym ) {
+ return -0x01;
+ }
+ pb_dynsym = psec_dynsym->pb_data;
+ p_dynsym = (Elf64_Sym *)pb_dynsym;
+
+ psec_dynstr = LibGoblin_Section_GetSectionInfo_fid(
+ p_binfo, LIBGOBLIN_SECTION_ID_DYNSTR );
+ if( NULL == psec_dynstr ) {
+ return -0x01;
+ }
+ pb_dynstr = psec_dynstr->pb_data;
+
+ psec_gnuhash = LibGoblin_Section_GetSectionInfo_fid(
+ p_binfo, LIBGOBLIN_SECTION_ID_GNU_HASH );
+ if( NULL == psec_gnuhash ) {
+ return -0x01;
+ }
+ pb_gnuhash = psec_gnuhash->pb_data;
+
+ dw_nbuckets = *((DWord *)(pb_gnuhash));
+ dw_symoffset = *((DWord *)(pb_gnuhash + 4));
+ dw_bloom_sz = *((DWord *)(pb_gnuhash + 8));
+ dw_bloom_shift = *((DWord *)(pb_gnuhash + 12));
+ pqw_bloom = *((QWord *)(pb_gnuhash + 16));
+ pdw_buckets = (DWord *)(pb_gnuhash + (sizeof(QWord) * dw_bloom_sz) + 16);
+ pdw_chain = (DWord *)(pb_gnuhash + (sizeof(QWord) * dw_bloom_sz)
+ + (sizeof(DWord) * dw_nbuckets) + 16);
+
+ // Hash the name, generate the "second" hash from it for the Bloom filter.
+ // h1 = dl_new_hash(symname);
+ dw_hash1 = Common_CalcDJBhash( pstr_symname );
+ // h2 = h1 >> os->os_shift2;
+ dw_hash2 = dw_hash1 >> dw_bloom_shift;
+printf(" [GNUHASH] h1= %08x, h2= %08x\n", dw_hash1, dw_hash2);
+
+ // Test against the Bloom filter
+ // c = sizeof (BloomWord) * 8;
+ dw_c = sizeof(QWord) * 8;
+ // n = (h1 / c) & os->os_maskwords_bm;
+ dw_n = (dw_hash1 / dw_c) & (dw_bloom_sz - 1);
+ // bitmask = (1 << (h1 % c)) | (1 << (h2 % c));
+ dw_bitmask = (1 << (dw_hash1 % dw_c)) | ( 1 << (dw_hash2 % dw_c));
+printf(" [GNUHASH] C= %ld, N= %ld BitMask=%08xh\n", dw_c, dw_n, dw_bitmask);
+ // if ((os->os_bloom[n] & bitmask) != bitmask) return (NULL);
+ if((*(pqw_bloom + dw_n) & dw_bitmask) != dw_bitmask) { return -0x02; }
+
+ // Locate the hash chain, and corresponding hash value element
+ // n = os->os_buckets[h1 % os->os_nbuckets];
+ dw_n = *(pdw_buckets + (dw_hash1 % dw_nbuckets));
+ // Empty hash chain, symbol not present
+ // if (n == 0) return (NULL);
+ if( 0 == dw_n ) { return -0x03; }
+
+ // sym = &os->os_dynsym[n];
+ p_symnow = (p_dynsym + dw_n);
+ // hashval = &os->os_hashval[n - os->os_symndx];
+ pdw_hashval = (pdw_chain + (dw_n - dw_symoffset));
+
+ // Walk the chain until the symbol is found or the chain is exhausted.
+ // for (h1 &= ~1; 1; sym++) {
+ for( dw_hash1 &= ~1; 1; p_symnow++,dw_n++ ) {
+ // h2 = *hashval++;
+ dw_hash2 = *pdw_hashval++;
+
+ // Compare the strings to verify match. Note that
+ // a given hash chain can contain different hash values.
+ // We'd get the right result by comparing every string,
+ // but comparing the hash values first lets us
+ // screen obvious mismatches at very low cost and avoid
+ // the relatively expensive string compare.
+ //
+ // We are intentionally glossing over some things here:
+ // - We could test sym->st_name for 0, which indicates
+ // a NULL string, and avoid a strcmp() in that case.
+ // - The real runtime linker must also take symbol
+ // versioning into account. This is an orthogonal issue
+ // to hashing, and is left out of this example for simplicity.
+ //
+ // A real implementation might test (h1 == (h2 & ~1), and then
+ // call a (possibly inline) function to validate the rest.
+
+ // if ((h1 == (h2 & ~1)) &&
+ // !strcmp(symname, os->os_dynstr + sym->st_name))
+ // return (sym);
+ if(( dw_hash1 == (dw_hash2 & ~1)) &&
+ !strcmp( pstr_symname, (char *)(pb_dynstr + p_symnow->st_name))) {
+ i_ret = (int)(dw_n & 0x7fffffff);
+ break;
+ }
+
+ // Done if at end of chain
+ // if (h2 & 1) break;
+ if( dw_hash2 & 1 ) { break; }
+ }
+
+ return i_ret;
+}
+*/
+
+/* EOF of drd64_.c ----------------------------------- */
--- /dev/null
+/*DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64
+
+ D r . D e a m o n 6 4
+ for INTEL64(R), AMD64(R)
+
+ Copyright(C) 2007-2009 Koine Yuusuke(koinec). All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY Koine Yuusuke(koinec) ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Koine Yuusuke(koinec) OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64DrDeAmOn64*/
+
+/* File Info -----------------------------------------------------------
+File: drd64_.h
+Function: Header
+Comment:
+----------------------------------------------------------------------*/
+
+#ifndef DRD64_HEADER_LIBGOBLIN_ELF_HASH
+#define DRD64_HEADER_LIBGOBLIN_ELF_HASH
+
+#include"drd64_libgoblin.h"
+
+#ifdef DRD64_SRC_LIBGOBLIN_ELF_HASH
+ #define LIBGOBLIN_ELF_HASH_EXTERN
+#else
+ #define LIBGOBLIN_ELF_HASH_EXTERN extern
+#endif
+
+
+#ifdef DRD64_SRC_LIBGOBLIN_ELF_HASH
+#endif
+
+LIBGOBLIN_ELF_HASH_EXTERN
+ int ELF64_GnuHash_SearchDynSym( LibGoblin_BinaryInfo *p_binfo, char *pstr_symname );
+
+
+
+#endif /* DRD64_HEADER_LIBGOBLIN_BINFO */
+
+/* EOF of drd64_.h ----------------------------------- */