
    dB                         d dl Z ddlmZ ddlmZ  G d de      Z G d d	ee      Z G d
 de      Z G d dee      Z	y)    N   )struct_parse   )Sectionc                   2    e Zd ZdZd Zd Zd Zed        Zy)ELFHashTablea   Representation of an ELF hash table to find symbols in the
        symbol table - useful for super-stripped binaries without section
        headers where only the start of the symbol table is known from the
        dynamic segment. The layout and contents are nicely described at
        https://flapenguin.me/2017/04/24/elf-lookup-dt-hash/.

        The symboltable argument needs to implement a get_symbol() method -
        in a regular ELF file, this will be the linked symbol table section
        as indicated by the sh_link attribute. For super-stripped binaries,
        one should use the DynamicSegment object as the symboltable as it
        supports symbol lookup without access to a symbol table section.
    c                     || _         || _        t        | j                   j                  j                  | j                   j
                  |      | _        y )N)elffile_symboltabler   structsElf_Hashstreamparamsselfr
   start_offsetsymboltables       3/usr/lib/python3/dist-packages/elftools/elf/hash.py__init__zELFHashTable.__init__   s?    '"4<<#7#7#@#@#'<<#6#6#/1    c                      | j                   d   S )zC Get the number of symbols from the hash table parameters.
        nchains)r   )r   s    r   get_number_of_symbolsz"ELFHashTable.get_number_of_symbols%   s     {{9%%r   c                 "   | j                   d   dk(  ry| j                  |      | j                   d   z  }| j                   d   |   }|dk7  rD| j                  j                  |      }|j                  |k(  r|S | j                   d   |   }|dk7  rDy)D Look up a symbol from this hash table with the given name.
        nbucketsr   Nbucketschains)r   elf_hashr   
get_symbolname)r   r!   hvalsymndxsyms        r   r    zELFHashTable.get_symbol*   s     ;;z"a'}}T"T[[%<<Y'-k##..v6Cxx4
[[*62F	 k
 r   c                     t        | t              s| j                  d      } d}d}t        |       D ]"  }|dz  |z   }|dz  }|dk7  r||dz	  z  }|| z  }$ |S )z9 Compute the hash value for a given symbol name.
        utf-8r      l      `    
isinstancebytesencode	bytearray)r!   hxcs       r   r   zELFHashTable.elf_hash8   su     $&;;w'D4 	Aa1AJAAva2g!GA	 r   N)	__name__
__module____qualname____doc__r   r   r    staticmethodr    r   r   r   r      s*    1&
  r   r   c                       e Zd ZdZd Zy)ELFHashSectionz Section representation of an ELF hash table. In regular ELF files, this
        allows us to use the common functions defined on Section objects when
        dealing with the hash table.
    c                 j    t        j                  | |||       t        j                  | || d   |       y N	sh_offset)r   r   r   r   headerr!   r
   r   s        r   r   zELFHashSection.__init__N   /    vtW5dGT+->Lr   Nr1   r2   r3   r4   r   r6   r   r   r8   r8   I       Mr   r8   c                   8    e Zd ZdZd Zd Zd Zd Zed        Z	y)GNUHashTablea   Representation of a GNU hash table to find symbols in the
        symbol table - useful for super-stripped binaries without section
        headers where only the start of the symbol table is known from the
        dynamic segment. The layout and contents are nicely described at
        https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/.

        The symboltable argument needs to implement a get_symbol() method -
        in a regular ELF file, this will be the linked symbol table section
        as indicated by the sh_link attribute. For super-stripped binaries,
        one should use the DynamicSegment object as the symboltable as it
        supports symbol lookup without access to a symbol table section.
    c                 *   || _         || _        t        | j                   j                  j                  | j                   j
                  |      | _        | j                   j                  j                  d      j                         | _	        | j                   j                  j                  d      j                         | _        |d| j                  z  z   | j                  d   | j                  z  z   | j                  d   | j                  z  z   | _        y )N r'   
bloom_sizer   )r
   r   r   r   Gnu_Hashr   r   Elf_wordsizeof	_wordsize	Elf_xword
_xwordsize
_chain_posr   s       r   r   zGNUHashTable.__init__`   s    '"4<<#7#7#@#@#'<<#6#6#/1 --66r:AAC,,..88<CCE&T^^);;KK%78KK
#dnn45r   c                    t        | j                  d         }|| j                  d   k  r| j                  d   S | j                  || j                  d   z
  | j                  z  z   }| j                  j
                  j                  |       | j                  j                  rdnd}	 t        j                  || j                  j
                  j                  | j                              d   }|dz  r|dz   S |dz  }V)z Get the number of symbols in the hash table by finding the bucket
            with the highest symbol index and walking to the end of its chain.
        r   	symoffset<I>Ir   r   )maxr   rL   rI   r
   r   seeklittle_endianstructunpackread)r   max_idxmax_chain_poshash_formatcur_hashs        r   r   z"GNUHashTable.get_number_of_symbolsm   s    
 dkk),-T[[--;;{++ t{{;//4>>AB  /"ll88dd }}[$,,2E2E2J2J4>>2Z[\]^H!|{"qLG r   c                     | j                   j                  }|| j                  d   z	  }t        ||z        | j                  d   z  }d||z  z  d||z  z  z  }| j                  d   |   |z  |k(  S )z Helper function to check if the given hash could be in the hash
            table by testing it against the bloom filter.
        bloom_shiftrE   r   bloom)r
   elfclassr   int)r   H1	arch_bitsH2word_idxBITMASKs         r   _matches_bloomzGNUHashTable._matches_bloom   s|     LL))	4;;}--rI~&\)BBi(Q2	>-BCG$X.8WDDr   c                    | j                  |      }| j                  |      sy| j                  d   || j                  d   z     }|| j                  d   k  ry| j                  j                  j                  | j                  || j                  d   z
  | j                  z  z          | j                  j                  rdnd}	 t        j                  || j                  j                  j                  | j                              d   }|dz  |dz  k(  r,| j                  j                  |      }||j                  k(  r|S |dz  r	 y|dz  })	r   Nr   r   rN   rO   rP   r   r   )gnu_hashre   r   r
   r   rR   rL   rI   rS   rT   rU   rV   r   r    r!   )r   r!   namehashsymidxrY   rZ   symbols          r   r    zGNUHashTable.get_symbol   s,    ==&""8,Y'4;;z3J(JKDKK,,  FT[[=U4UY]YgYg3g!gh"ll88dd}}[$,,2E2E2J2J4>>2Z[\]^H!|x!|+**55f=6;;&!M!| aKF r   c                     t        | t              s| j                  d      } d}t        |       D ]
  }|dz  |z   } |dz  S )zC Compute the GNU-style hash value for a given symbol name.
        r&   i  !   l    r)   )keyr.   r0   s      r   rg   zGNUHashTable.gnu_hash   sK     #u%**W%C3 	AB
A	:~r   N)
r1   r2   r3   r4   r   r   re   r    r5   rg   r6   r   r   rB   rB   S   s0    5.E2  r   rB   c                       e Zd ZdZd Zy)GNUHashSectionz Section representation of a GNU hash table. In regular ELF files, this
        allows us to use the common functions defined on Section objects when
        dealing with the hash table.
    c                 j    t        j                  | |||       t        j                  | || d   |       y r:   )r   r   rB   r<   s        r   r   zGNUHashSection.__init__   r>   r   Nr?   r6   r   r   ro   ro      r@   r   ro   )
rT   common.utilsr   sectionsr   objectr   r8   rB   ro   r6   r   r   <module>rt      sL     ' 66 6rMWl M]6 ]@MWl Mr   