OSDN Git Service

2019/03/04(Mon) 20:23
authorKoine Yuusuke(koinec) <koinec@users.osdn.me>
Mon, 4 Mar 2019 11:23:01 +0000 (20:23 +0900)
committerKoine Yuusuke(koinec) <koinec@users.osdn.me>
Mon, 4 Mar 2019 11:23:01 +0000 (20:23 +0900)
 (LibGoblin)
  * CreateFile drd64_libgoblin_elf_hash.[ch]

libgoblin/Makefile
libgoblin/drd64_libgoblin.h
libgoblin/drd64_libgoblin_elf_dynsym.c
libgoblin/drd64_libgoblin_elf_hash.c [new file with mode: 0644]
libgoblin/drd64_libgoblin_elf_hash.h [new file with mode: 0644]

index a0fe4ae..903e001 100644 (file)
@@ -61,6 +61,7 @@ OBJS = drd64_libgoblin_api.o \
                drd64_libgoblin_elf.o \
                drd64_libgoblin_elf_dynamic.o \
                drd64_libgoblin_elf_dynsym.o \
+               drd64_libgoblin_elf_hash.o \
                drd64_libgoblin_elf_symtab.o \
                drd64_libgoblin_elf_proghdr.o \
                drd64_libgoblin_elf_section.o \
@@ -88,6 +89,7 @@ HEADER = drd64_libgoblin.h \
                drd64_libgoblin_elf.h \
                drd64_libgoblin_elf_dynamic.h \
                drd64_libgoblin_elf_dynsym.h \
+               drd64_libgoblin_elf_hash.h \
                drd64_libgoblin_elf_symtab.h \
                drd64_libgoblin_elf_proghdr.h \
                drd64_libgoblin_elf_section.h \
@@ -177,6 +179,9 @@ drd64_libgoblin_elf_dynamic.o: drd64_libgoblin_elf_dynamic.c $(HEADER)
 drd64_libgoblin_elf_dynsym.o: drd64_libgoblin_elf_dynsym.c $(HEADER)
        $(CC) -c -o drd64_libgoblin_elf_dynsym.o $(FLAGS_DEBUG) \
                                drd64_libgoblin_elf_dynsym.c
+drd64_libgoblin_elf_hash.o: drd64_libgoblin_elf_hash.c $(HEADER)
+       $(CC) -c -o drd64_libgoblin_elf_hash.o $(FLAGS_DEBUG) \
+                               drd64_libgoblin_elf_hash.c
 drd64_libgoblin_elf_symtab.o: drd64_libgoblin_elf_symtab.c $(HEADER)
        $(CC) -c -o drd64_libgoblin_elf_symtab.o $(FLAGS_DEBUG) \
                                drd64_libgoblin_elf_symtab.c
index a095749..2d94a63 100644 (file)
@@ -83,6 +83,7 @@ Comment:
 #include"drd64_libgoblin_elf.h"
 #include"drd64_libgoblin_elf_dynamic.h"
 #include"drd64_libgoblin_elf_dynsym.h"
+#include"drd64_libgoblin_elf_hash.h"
 #include"drd64_libgoblin_elf_symtab.h"
 #include"drd64_libgoblin_elf_proghdr.h"
 #include"drd64_libgoblin_elf_section.h"
index 0292e38..2378e13 100644 (file)
@@ -150,9 +150,11 @@ int
        ELF64_DynSym_ReadSection(
                        LibGoblin_BinaryInfo    *p_binfo )
 {
+       char    str_symname[256];
+       char    *pstr_symname;
        Byte    *pb_dynstr;
-       //Byte  *pb_now;
        int             i_bid;
+       int             i_result;
        DWord   dw_cnt;
        DWord   dw_sym;
        DWord   dw_vermax;
@@ -168,6 +170,7 @@ int
        //LibGoblin_SrcFile             *p_srcfile;
        LibGoblin_ObjectInfo    *p_obj;
        LibGoblin_ProgramInfo   *p_pginfo;
+       LibGoblin_BinaryInfo    *p_binlib;
 
 
        // Check exist .dynsym section ---
@@ -218,6 +221,9 @@ int
                        continue;
                }
 
+               pstr_symname    =  (char *)(pb_dynstr + p_sym->st_name);
+               strncpy( str_symname, pstr_symname, 256);
+
                // Search DynSym_Version ---
                i_bid           = p_binfo->i_id;
                if( 1 < *pw_gnuver )    {
@@ -225,6 +231,8 @@ int
                        for( dw_cnt = 0; dw_cnt < dw_vermax; dw_cnt++, p_vernow++ )     {
                                if( *pw_gnuver == p_vernow->dw_other )  {
                                        i_bid   = p_vernow->i_binfo_id;
+                                       //strcat( str_symname, "@");
+                                       //strcat( str_symname, p_vernow->pstr_vername );
                                        break;
                                }
                        }
@@ -239,6 +247,10 @@ int
 
                do      {
                        // Check Hash
+                       p_binlib        = BinaryInfo_GetBinInfo( i_bid );
+               printf(" debug: [%2ld] %s (%s)\n", dw_sym, str_symname, p_binlib->str_filename );
+                       i_result        = ELF64_GnuHash_SearchDynSym( p_binlib, str_symname );
+               printf(" %d\n", i_result );
 
                        i_bid   = BinInfo_SearchNextSlave( p_binfo->i_id, i_bid );
                } while( -0x01 != i_bid );
diff --git a/libgoblin/drd64_libgoblin_elf_hash.c b/libgoblin/drd64_libgoblin_elf_hash.c
new file mode 100644 (file)
index 0000000..7aa5caf
--- /dev/null
@@ -0,0 +1,308 @@
+/*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 ----------------------------------- */
diff --git a/libgoblin/drd64_libgoblin_elf_hash.h b/libgoblin/drd64_libgoblin_elf_hash.h
new file mode 100644 (file)
index 0000000..9d112e2
--- /dev/null
@@ -0,0 +1,59 @@
+/*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 ----------------------------------- */