
    d                         d dl Z d dlZd dlmZ d dlmZ ddlmZ d dlmZ d dl	Z	ddl
mZmZmZ  ej                  dd	      Z G d
 de      Zy)    N)OrderedDict)Mapping   )struct_parse)bisect_right)CStringStructIfNameLUTEntryzcu_ofs die_ofsc                   N    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
dd
Zd Zd Zy	)NameLUTaO  
    A "Name LUT" holds any of the tables specified by .debug_pubtypes or
    .debug_pubnames sections. This is basically a dictionary where the key is
    the symbol name (either a public variable, function or a type), and the
    value is the tuple (cu_offset, die_offset) corresponding to the variable.
    The die_offset is an absolute offset (meaning, it can be used to search the
    CU by iterating until a match is obtained).

    An ordered dictionary is used to preserve the CU order (i.e, items are
    stored on a per-CU basis (as it was originally in the .debug_* section).

    Usage:

    The NameLUT walks and talks like a dictionary and hence it can be used as
    such. Some examples below:

    # get the pubnames (a NameLUT from DWARF info).
    pubnames = dwarf_info.get_pubnames()

    # lookup a variable.
    entry1 = pubnames["var_name1"]
    entry2 = pubnames.get("var_name2", default=<default_var>)
    print(entry2.cu_ofs)
    ...

    # iterate over items.
    for (name, entry) in pubnames.items():
      # do stuff with name, entry.cu_ofs, entry.die_ofs

    # iterate over items on a per-CU basis.
    import itertools
    for cu_ofs, item_list in itertools.groupby(pubnames.items(),
        key = lambda x: x[1].cu_ofs):
      # items are now grouped by cu_ofs.
      # item_list is an iterator yeilding NameLUTEntry'ies belonging
      # to cu_ofs.
      # We can parse the CU at cu_offset and use the parsed CU results
      # to parse the pubname DIEs in the CU listed by item_list.
      for item in item_list:
        # work with item which is part of the CU with cu_ofs.

    c                 J    || _         || _        || _        d | _        d | _        y N)_stream_size_structs_entries_cu_headers)selfstreamsizestructss       8/usr/lib/python3/dist-packages/elftools/dwarf/namelut.py__init__zNameLUT.__init__@   s&    
    c                 l    | j                   | j                         \  | _         | _        | j                   S )a  
        Returns the parsed NameLUT entries. The returned object is a dictionary
        with the symbol name as the key and NameLUTEntry(cu_ofs, die_ofs) as
        the value.

        This is useful when dealing with very large ELF files with millions of
        entries. The returned entries can be pickled to a file and restored by
        calling set_entries on subsequent loads.
        )r   _get_entriesr   r   s    r   get_entrieszNameLUT.get_entriesJ   s0     == .2.?.?.A+DM4+}}r   c                      || _         || _        y)a  
        Set the NameLUT entries from an external source. The input is a
        dictionary with the symbol name as the key and NameLUTEntry(cu_ofs,
        die_ofs) as the value.

        This option is useful when dealing with very large ELF files with
        millions of entries. The entries can be parsed once and pickled to a
        file and can be restored via this function on subsequent loads.
        N)r   r   )r   entries
cu_headerss      r   set_entrieszNameLUT.set_entriesX   s      %r   c                 ~    | j                   | j                         \  | _         | _        t        | j                         S )z?
        Returns the number of entries in the NameLUT.
        )r   r   r   lenr   s    r   __len__zNameLUT.__len__e   s5     == .2.?.?.A+DM4+4==!!r   c                     | j                   | j                         \  | _         | _        | j                   j                  |      S )z{
        Returns a namedtuple - NameLUTEntry(cu_ofs, die_ofs) - that corresponds
        to the given symbol name.
        r   r   r   get)r   names     r   __getitem__zNameLUT.__getitem__m   s;    
 == .2.?.?.A+DM4+}}  &&r   c                 ~    | j                   | j                         \  | _         | _        t        | j                         S )z@
        Returns an iterator to the NameLUT dictionary.
        )r   r   r   iterr   s    r   __iter__zNameLUT.__iter__v   s5     == .2.?.?.A+DM4+DMM""r   c                     | j                   | j                         \  | _         | _        | j                   j                         S )z7
        Returns the NameLUT dictionary items.
        )r   r   r   itemsr   s    r   r0   zNameLUT.items~   s9     == .2.?.?.A+DM4+}}""$$r   Nc                     | j                   | j                         \  | _         | _        | j                   j                  ||      S )z
        Returns NameLUTEntry(cu_ofs, die_ofs) for the provided symbol name or
        None if the symbol does not exist in the corresponding section.
        r(   )r   r*   defaults      r   r)   zNameLUT.get   s=    
 == .2.?.?.A+DM4+}}  w//r   c                 l    | j                   | j                         \  | _        | _         | j                   S )zF
        Returns all CU headers. Mainly required for readelf.
        )r   r   r   r   s    r   get_cu_headerszNameLUT.get_cu_headers   s4     #.2.?.?.A+DM4+r   c           
         | j                   j                  d       t               }g }d}t        d| j                  j                  d      t        d t        d                  }|| j                  k  rt        | j                  j                  | j                   |      }|j                  |       ||j                  z   | j                  j                         z   }|j                  }	 t        || j                         }|j                  dk(  rn7t!        |||j                  z         ||j"                  j%                  d      <   ]|| j                  k  r||fS )zt
        Parse the (name, cu_ofs, die_ofs) information from this section and
        store as a dictionary.
        r   Dwarf_offset_name_pairdie_ofsc                     | d   S )Nr7    )ctxs    r   <lambda>z&NameLUT._get_entries.<locals>.<lambda>   s
    s9~ r   r*   )cu_ofsr7   zutf-8)r   seekr   r	   r   Dwarf_offsetr
   r   r   r   Dwarf_nameLUT_headerappendunit_lengthinitial_length_field_sizedebug_info_offsetr7   r   r*   decode)r   r!   r"   offsetentry_structnamelut_hdr
hdr_cu_ofsentrys           r   r   zNameLUT._get_entries   s:    	!-

 6**95-wv?A
 tzz! 't}}'I'ILL&*Kk*{666]]<<>?F
 %66J $\4<<@ ==A%6B!+",u}}"<7>

))'23  tzz!6 $$r   r   )__name__
__module____qualname____doc__r   r   r#   r&   r+   r.   r0   r)   r4   r   r9   r   r   r   r      s:    )V &"'#%0 .%r   r   )oscollectionsr   collections.abcr   common.utilsr   bisectr   math	constructr   r	   r
   
namedtupler   r   r9   r   r   <module>rV      sE    
  # # '   + +%{%%n6FGr%g r%r   