
    dX#                         d dl Z d dlmZ ddlmZ ddlmZ ddlmZ  edd	      Z	 ed
d      Z
d Zd d d d d d edZ G d de      Z G d de      Zy)    N)
namedtuple   )struct_parse
DWARFError   )_iter_CUs_in_section
RangeEntryz=entry_offset entry_length begin_offset end_offset is_absoluteBaseAddressEntryzentry_offset base_addressc                     |j                   j                  || j                        }t        | j                  | j
                  ||| j                  z   d      S NT)	dwarfinfoget_addrstart_indexr
   entry_offsetentry_lengthlength)ecustart_offsets      7/usr/lib/python3/dist-packages/elftools/dwarf/ranges.py_translate_startx_lengthr      sD    <<((Q]];LannannlLSTS[S[D[]abb    c                 B    t        | j                  | j                        S N)r   r   addressr   r   s     r   <lambda>r      s    *:1>>199*U r   c                 p    t        | j                  | j                  | j                  | j                  d      S )NF)r
   r   r   r   
end_offsetr   s     r   r   r      s*    *Q^^Q^^UVUcUcefeqeqsx*y r   c                 p    t        | j                  | j                  | j                  | j                  d      S r   )r
   r   r   start_addressend_addressr   s     r   r   r      s*    *Q^^Q^^UVUdUdfgfsfsuy*z r   c                     t        | j                  | j                  | j                  | j                  | j                  z   d      S r   )r
   r   r   r"   r   r   s     r   r   r      sI    *Q^^Q^^UVUdUdfgfufuxy  yA  yA  gA  CG  +H r   c                 v    t        | j                  |j                  j                  || j                              S r   )r   r   r   r   indexr   s     r   r   r      s+    *:1>>2<<K`K`acefelelKm*n r   c           	          t        | j                  | j                  |j                  j	                  || j
                        |j                  j	                  || j                        d      S r   )r
   r   r   r   r   r   	end_indexr   s     r   r   r       s    *Q^^Q^^UWUaUaUjUjkmopo|o|U}  @B  @L  @L  @U  @U  VX  Z[  Ze  Ze  @f  hl  +m r   )DW_RLE_base_addressDW_RLE_offset_pairDW_RLE_start_endDW_RLE_start_lengthDW_RLE_base_addressxDW_RLE_startx_endxDW_RLE_startx_lengthc                   8    e Zd ZdZd	dZd	dZd Zd Zd Zd Z	y)
RangeListsPairzFor those binaries that contain both a debug_ranges and a debug_rnglists section,
    it holds a RangeLists object for both and forwards API calls to the right one based
    on the CU version.
    Nc                 P    t        ||d|      | _        t        ||d|      | _        y )N      )
RangeLists_ranges	_rnglists)selfstreamv4streamv5structsr   s        r   __init__zRangeListsPair.__init__)   s&    !(GQ	B#Hgq)Dr   c                     |t        d      |j                  j                  dk\  r| j                  n| j                  }|j                  ||      S )zhForwards the call to either v4 section or v5 one,
        depending on DWARF version in the CU.
        z*For this binary, "cu" needs to be providedr4   )r   headerversionr7   r6   get_range_list_at_offset)r8   offsetr   sections       r   r@   z'RangeListsPair.get_range_list_at_offset-   sH     :KLL$&II$5$5$:$..//;;r   c                 8    | j                   j                  |      S )z?Gets an untranslated v5 rangelist from the v5 section.
        )r7   get_range_list_at_offset_exr8   rA   s     r   rD   z*RangeListsPair.get_range_list_at_offset_ex6   s     ~~99&AAr   c                     t        d      )zTricky proposition, since the structure of ranges and rnglists
        is not identical. A realistic readelf implementation needs to be aware of both.
        z/Iterating through two sections is not supportedr   r8   s    r   iter_range_listszRangeListsPair.iter_range_lists;   s     JKKr   c                 6    | j                   j                         S )zSee RangeLists.iter_CUs()
        
        CU structure is only present in DWARFv5 rnglists sections. A well written
        section dumper should check if one is present.
        )r7   iter_CUsrG   s    r   rJ   zRangeListsPair.iter_CUsA   s     ~~&&((r   c                 8    | j                   j                  |      S )zSee RangeLists.iter_CU_range_lists_ex()

        CU structure is only present in DWARFv5 rnglists sections. A well written
        section dumper should check if one is present.
        )r7   iter_CU_range_lists_ex)r8   r   s     r   rL   z%RangeListsPair.iter_CU_range_lists_exI   s     ~~44R88r   r   )
__name__
__module____qualname____doc__r<   r@   rD   rH   rJ   rL    r   r   r1   r1   $   s(    E<B
L)9r   r1   c                   B    e Zd ZdZd ZddZd Zd Zd Zd Z	d	 Z
d
 Zy)r5   a   A single range list is a Python list consisting of RangeEntry or
        BaseAddressEntry objects.

        Since v0.29, two new parameters - version and dwarfinfo

        version is used to distinguish DWARFv5 rnglists section from
        the DWARF<=4 ranges section. Only the 4/5 distinction matters.

        The dwarfinfo is needed for enumeration, because enumeration
        requires scanning the DIEs, because ranges may overlap, even on DWARF<=4
    c                     || _         || _        d| j                  j                  dz  z  dz
  | _        || _        || _        y )Nr      r   )streamr;   address_size	_max_addrr?   
_dwarfinfo)r8   rU   r;   r?   r   s        r   r<   zRangeLists.__init__]   s>    t||881<=A#r   Nc                 x    | j                   j                  |t        j                         | j	                  |      S )z Get a range list at the given offset in the section.

            The cu argument is necessary if the ranges section is a
            DWARFv5 debug_rnglists one, and the target rangelist
            contains indirect encodings
        )rU   seekosSEEK_SET_parse_range_list_from_stream)r8   rA   r   s      r   r@   z#RangeLists.get_range_list_at_offsetd   s-     	-11"55r   c                 X    t        | j                  j                  | j                  |      S )zpGet a DWARF v5 range list, addresses and offsets unresolved,
        at the given offset in the section
        )r   r;   Dwarf_rnglists_entriesrU   rE   s     r   rD   z&RangeLists.get_range_list_at_offset_exn   s!     DLL??fUUr   c              #     K   | j                   dk\  }| j                  j                         D ci c]J  }|j                         D ]5  }d|j                  v r%|d   dk\  |k(  r|j                  d   j
                  |7 L }}}t        |j                               }|j                          |D ]  }| j                  |||           yc c}}w w)z Yields all range lists found in the section according to readelf rules.
        Scans the DIEs for rangelist offsets, then pulls those.
        Returned rangelists are always translated into lists of BaseAddressEntry/RangeEntry objects.
        r4   DW_AT_rangesr?   N)
r?   rX   rJ   	iter_DIEs
attributesvaluelistkeyssortr@   )r8   ver5r   diecu_mapall_offsetsrA   s          r   rH   zRangeLists.iter_range_listst   s      ||q  oo..0R||~R/R	]a5GD4P ..066; R6 R R 6;;=)! 	HF//vGG	HRs   -CAC	>ACc                     | j                   dk  rt        d      t        | j                  j	                               j
                  }t        | j                  ||j                        S )zWFor DWARF5 returns an array of objects, where each one has an array of offsets
        r4   z6CU iteration in rnglists is not supported with DWARF<5)	r?   r   nextrX   rJ   r;   r	   rU   Dwarf_rnglists_CU_header)r8   r;   s     r   rJ   zRangeLists.iter_CUs   sR     <<!UVVt//12::#DKK':Z:Z[[r   c              #     K   | j                   }|j                  |j                  |j                  rdnd|j                  z  z          |j                         |j                  |j                  z   k  rNt        | j                  j                  |       |j                         |j                  |j                  z   k  rMyyw)zbFor DWARF5, returns untranslated rangelists in the CU, where CU comes from iter_CUs above
        @       N)rU   rZ   offset_table_offsetis64offset_counttelloffset_after_lengthunit_lengthr   r;   r_   )r8   r   rU   s      r   rL   z!RangeLists.iter_CU_range_lists_ex   s      B**BGGbr-VVWkkmb44r~~EEt||BBFKK kkmb44r~~EEs   B<C?Cc                 4    t        |j                     ||      S )zTranslates entries in a DWARFv5 rangelist from raw parsed format to 
        a list of BaseAddressEntry/RangeEntry, using the CU
        entry_translate
entry_type)r8   entryr   s      r   translate_v5_entryzRangeLists.translate_v5_entry   s     u//0;;r   c           	      x   | j                   dk\  r<t        fdt        | j                  j                  | j
                        D              S g }	 | j
                  j                         }t        | j                  j                  d      | j
                        }t        | j                  j                  d      | j
                        }|dk(  r|dk(  r	 |S || j                  k(  r|j                  t        ||             n:|j                  t        || j
                  j                         |z
  ||d             )Nr4   c              3   P   K   | ]  }t        |j                     |        y wr   ry   ).0r|   r   s     r   	<genexpr>z;RangeLists._parse_range_list_from_stream.<locals>.<genexpr>   s-      S ((8(89%D Ss   #& r   )r   base_addressF)r   r   begin_offsetr    is_absolute)r?   re   r   r;   r_   rU   ru   Dwarf_target_addrrW   appendr   r
   )r8   r   lstr   r   r    s    `    r   r]   z(RangeLists._parse_range_list_from_stream   s   <<1 S C CT[[QS S S C#{{//1+LL2226 E)LL2226E
1$q J "T^^3JJ/\Xbcd JJz%1%)[[%5%5%7,%F%1#-$) + , r   r   )rM   rN   rO   rP   r<   r@   rD   rH   rJ   rL   r}   r]   rQ   r   r   r5   r5   Q   s3    
$6VH4\L<r   r5   )r[   collectionsr   common.utilsr   common.exceptionsr   
dwarf_utilr	   r
   r   r   rz   objectr1   r5   rQ   r   r   <module>r      sz    
 " ' * , &ef
02MN c Vyz Hn m4+9V +9Zq qr   