
    dEF              	           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
 edd      Z edd      Zd Zd d d d d d d edZ G d de      Z G d de      Z G d de      Zy)    N)
namedtuple   
DWARFError)struct_parse   )_iter_CUs_in_sectionLocationExprloc_exprLocationEntryzFentry_offset entry_length begin_offset end_offset loc_expr is_absoluteBaseAddressEntryz&entry_offset entry_length base_addressLocationViewPairzentry_offset begin endc                     |j                   j                  || j                        }t        | j                  | j
                  ||| j                  z   | j                  d      S NT)	dwarfinfoget_addrstart_indexr   entry_offsetentry_lengthlengthr   )ecustart_offsets      >/usr/lib/python3/dist-packages/elftools/dwarf/locationlists.py_translate_startx_lengthr      sM    <<((Q]];L|VWV^V^G^`a`j`jlpqq    c                 X    t        | j                  | j                  | j                        S N)r   r   r   addressr   r   s     r   <lambda>r!      s    -=annann^_^g^g-h r   c                     t        | j                  | j                  | j                  | j                  | j
                  d      S )NF)r   r   r   r   
end_offsetr   r    s     r   r!   r!      sB    ]1>>1>>[\[i[iklkwkwyz  zD  zD  FK  .L r   c                     t        | j                  | j                  | j                  | j                  | j                  z   | j
                  d      S r   )r   r   r   start_addressr   r   r    s     r   r!   r!      s^    ]1>>1>>[\[j[jlml{l{~  G  G  mG  IJ  IS  IS  UY  .Z r   c                     t        | j                  | j                  | j                  | j                  | j
                  d      S r   )r   r   r   r%   end_addressr   r    s     r   r!   r!      sB    ]1>>1>>[\[j[jlmlyly{|  |F  |F  HL  .M r   c                 ^    t        | j                  | j                  dd| j                  d      S )NT)r   r   r   r   r    s     r   r!   r!      s'    ]1>>1>>[]_acdcmcmos-t r   c                     t        | j                  | j                  |j                  j	                  || j
                              S r   )r   r   r   r   r   indexr    s     r   r!   r!      s;    -=annann^`^j^j^s^stvxyxx  _A  .B r   c           	          t        | j                  | j                  |j                  j	                  || j
                        |j                  j	                  || j                        | j                  d      S r   )r   r   r   r   r   r   	end_indexr   r    s     r   r!   r!       s    ]1>>1>>[][g[g[p[pqsuv  vC  vC  \D  FH  FR  FR  F[  F[  \^  `a  `k  `k  Fl  no  nx  nx  z~  . r   )DW_LLE_base_addressDW_LLE_offset_pairDW_LLE_start_lengthDW_LLE_start_endDW_LLE_default_locationDW_LLE_base_addressxDW_LLE_startx_endxDW_LLE_startx_lengthc                   ,    e Zd ZdZddZddZd Zd Zy)LocationListsPairzFor those binaries that contain both a debug_loc and a debug_loclists section,
    it holds a LocationLists object for both and forwards API calls to the right one.
    Nc                 P    t        ||d|      | _        t        ||d|      | _        y )N      )LocationLists_loc	_loclists)selfstreamv4streamv5structsr   s        r   __init__zLocationListsPair.__init__(   s&    !(GQ	B	&x!YGr   c                     |t        d      |j                  j                  j                  dk\  r| j                  n| j
                  }|j                  ||      S )z9See LocationLists.get_location_list_at_offset().
        +For this binary, "die" needs to be providedr:   )r   r   headerversionr=   r<   get_location_list_at_offset)r>   offsetdiesections       r   rG   z-LocationListsPair.get_location_list_at_offset,   sL     ;LMM$'FFMM$9$9Q$>$..DII2263??r   c                     t        d      )zTricky proposition, since the structure of loc and loclists
        is not identical. A realistic readelf implementation needs to be aware of both
        /Iterating through two sections is not supportedr   r>   s    r   iter_location_listsz%LocationListsPair.iter_location_lists4   s     JKKr   c                     t        d      )zTSee LocationLists.iter_CUs()

        There are no CUs in DWARFv4 sections.
        rL   r   rM   s    r   iter_CUszLocationListsPair.iter_CUs:   s    
 JKKr   r   )__name__
__module____qualname____doc__rB   rG   rN   rP    r   r   r7   r7   $   s    H@LLr   r7   c                   F    e Zd ZdZddZddZd Zd Zd ZddZ	d	 Z
d
 Zy)r;   a   A single location list is a Python list consisting of LocationEntry or
        BaseAddressEntry objects.

        Starting with DWARF5, it may also contain LocationViewPair, but only
        if scanning the section, never when requested for a DIE attribute.

        The default location entries are returned as LocationEntry with
        begin_offset == end_offset == -1

        Version determines whether the executable contains a debug_loc
        section, or a DWARFv5 style debug_loclists one. Only the 4/5
        distinction matters.

        Dwarfinfo is only needed for DWARFv5 location entry encodings
        that contain references to other sections (e. g. DW_LLE_startx_endx),
        and only for location list enumeration.
    Nc                     || _         || _        || _        || _        d| j                  j                  dz  z  dz
  | _        y )Nr      r   )streamrA   r   rF   address_size	_max_addr)r>   rY   rA   rF   r   s        r   rB   zLocationLists.__init__S   s>    "t||881<=Ar   c                    | j                   dk\  r|t        d      | j                  j                  |t        j
                         | j                   dk\  r| j                  |j                        S | j                         S )z Get a location list at the given offset in the section.
        Passing the die is only neccessary in DWARF5+, for decoding
        location entry encodings that contain references to other sections.
        r:   rD   )	rF   r   rY   seekosSEEK_SET#_parse_location_list_from_stream_v5r    _parse_location_list_from_stream)r>   rH   rI   s      r   rG   z)LocationLists.get_location_list_at_offsetZ   sr    
 <<1LMM-CG<<STCTt77?  	BZ^ZZ  [B  	Br   c              #   @  K   | j                   dk\  }| j                  }|j                  dt        j                         |j                         }|j                  dt        j                         t               }t               }t               }| j                  j                         D ]:  }|d   }|dk\  |k(  s|j                         D ]  }	d|	j                  v rd|	j                  v r#t        j                  |	j                  d   |      sJ |	j                  d   j                  }
|	j                  d   j                  }|||
<   |||<   |j!                  |
       |	j                  D ]u  }|	j                  |   }|dk7  sd|	j                  vs&t        j#                  ||      s=t        j                  ||      sT|j                  }|j!                  |       |||<   w  = t%        |      }|j'                          |rd}|j                         |k  rt)        | j*                  j,                  |      }|j                   dk(  sJ |j.                  |j0                  z   }|j                         |k  r||   }||j                         k(  r@| j3                  |      }| j5                  ||j                                  }||z    |dz  }n'||kD  r|}|j                  |t        j                         |j                         |k  r|j                         |k  ryy|D ]y  }|j7                  ||      }||   j8                  j                   dk  s2|j                  |t        j                         | j3                  |      }| j;                         }||z    { yw)z Iterates through location lists and view pairs. Returns lists of
        LocationEntry, BaseAddressEntry, and LocationViewPair objects.
        r:   r   rF   DW_AT_GNU_locviewsDW_AT_locationr   N)rF   rY   r]   r^   SEEK_ENDtellr_   setdictr   rP   	iter_DIEs
attributesLocationParser_attribute_has_loc_listvalueaddattribute_has_locationlistsortr   rA   Dwarf_loclists_CU_headeroffset_after_lengthunit_length_parse_locview_pairsr`   getrE   ra   )r>   ver5rY   endposall_offsetslocviewscu_mapr   cu_verrI   views_offsetlist_offsetkeyattroffset_index	cu_headercu_end_offsetnext_offsetlocview_pairsentriesrH   s                        r   rN   z!LocationLists.iter_location_listsd   sC    $ ||q Ar{{#Ar{{# e6..))+ 	5B	]F!$<<> 5C ,s~~=/3>>A*BB3>>RbCcekln  m'*~~6J'K'Q'Q&)nn5E&F&L&L1<..0{+#5  #~~ 5"~~c2 $448LTWTbTb8b*AA$O*BB4P*.**K'OOK824F;/55	50 ;' L++-&(()N)NPVW	 ((A-.- !* = =	@U@U U kkmm3"-l";K"fkkm3(,(A(A((K"&"J"J6RXR]R]R_K`"a+g55$)&6*7KK= kkmm3 ++-&(2 & 2&ll66:+&--559KK4$($=$=h$GM"CCEG''112s3   B5N8CNN#N:ENN5NAN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
        r:   z6CU iteration in loclists is not supported with DWARF<5)	rF   r   nextr   rP   rA   r	   rY   rr   )r>   rA   s     r   rP   zLocationLists.iter_CUs   sR     <<!UVVt~~..0199#DKK':Z:Z[[r   c           
         g }	 | j                   j                         }t        | j                  j	                  d      | j                         }t        | j                  j	                  d      | j                         }|dk(  r|dk(  r	 |S || j
                  k(  r;| j                   j                         |z
  }|j                  t        |||             nt        | j                  j                  d      | j                         }t        |      D cg c]1  }t        | j                  j                  d      | j                         3 }}| j                   j                         |z
  }|j                  t        |||||d             c c}w )N r   )r   r   base_addressF)r   r   begin_offsetr#   r   is_absolute)rY   rf   r   rA   Dwarf_target_addrr[   appendr   Dwarf_uint16rangeDwarf_uint8r   )	r>   lstr   r   r#   r   expr_lenir   s	            r   ra   z.LocationLists._parse_location_list_from_stream   sd   ;;++-L'..r2DKKAL%..r2DKKAJq Z1_( 
' /#{{//1L@

+T`oyz{ (LL--b14;;@ */x:$% ))A)A")E)-6 : :  ${{//1L@

=!-!-!-)%"') *+ ":s   6Fc                     t        | j                  j                  | j                        D cg c]  }t	        |j
                     ||       c}S c c}w )a   Returns an array with BaseAddressEntry and LocationEntry.
            No terminator entries.

            The cu argument is necessary if the section is a
            DWARFv5 debug_loclists one, and the target loclist
            contains indirect encodings.
        )r   rA   Dwarf_loclists_entriesrY   entry_translate
entry_type)r>   r   entrys      r   r`   z1LocationLists._parse_location_list_from_stream_v5   sO     DLL??MO   0 01%< O 	O Os    Ac                 V   |j                   }|j                  |z
  }|j                  }|dk(  rt        |||j                        S |dk(  r.t        |||j                  |j                  |j                  d      S |dk(  r;t        |||j                  |j                  |j                  z   |j                  d      S |dk(  r.t        |||j                  |j                  |j                  d      S |dk(  rt        ||dd|j                  d      S |d	v rt        d
|d      t        dd|      )Nr.   r/   Fr0   Tr1   r2   r)   )r3   r4   r5   zLocation list entry type z is not supported yetzUnknown DW_LLE code: )r   entry_end_offsetr   r   r   r   r   r#   r   r%   r   r'   NotImplementedErrorr   )r>   r   rI   offlentypes         r   _translate_entry_v5z!LocationLists._translate_entry_v5   s2     $$s*((#Cemm<<)) c5+=+=u?O?OQVQ_Q_afgg** c5+>+>@S@SV[VbVb@bdidrdrtxyy'' c5+>+>@Q@QSXSaSacghh.. c2r5>>4HH[[ &\`&bccU$GHHr   c                    | j                   }|j                  |j                         d       }g }||j                         |k  rnt        | j                  j
                  |      }|j                  t        |j                  |j                  |j                               |j                         |k  rn|j                         |k(  sJ |S r   )rY   rv   rf   r   rA   Dwarf_locview_pairr   r   r   beginend)r>   rz   rY   r~   pairspairs         r   ru   z"LocationLists._parse_locview_pairs  s    ll6;;=$7"++-+-#DLL$C$CVL-d.?.?TXXVW ++-+- ;;=K/0/r   )r9   Nr   )rQ   rR   rS   rT   rB   rG   rN   rP   ra   r`   r   ru   rU   r   r   r;   r;   A   s7    "BB\2|\@
OI,	r   r;   c                   ^    e Zd ZdZd Zed        Zd	dZed        Zed        Z	ed        Z
y)
rk   a   A parser for location information in DIEs.
        Handles both location information contained within the attribute
        itself (represented as a LocationExpr object) and references to
        location lists in the .debug_loc section (represented as a
        list).
    c                     || _         y r   )location_lists)r>   r   s     r   rB   zLocationParser.__init__"  s
    ,r   c                     t         j                  |       xr. t         j                  | |      xs t         j                  | |      S )zB Checks if a DIE attribute contains location information.
        )rk   _attribute_is_loclistptr_class_attribute_has_loc_exprrl   r   dwarf_versions     r   ro   z%LocationParser.attribute_has_location%  sD     ==dC N77mL M77mL	Or   Nc                     | j                  ||      r`| j                  ||      rt        |j                        S | j	                  ||      r&| j
                  j                  |j                  |      S yt        d      )zY Parses a DIE attribute and returns either a LocationExpr or
            a list.
        z,Attribute does not have location informationN)ro   r   r
   rm   rl   r   rG   
ValueError)r>   r   r   rI   s       r   parse_from_attributez#LocationParser.parse_from_attribute-  sy     &&t];++D-@#DJJ//--dMB**FFJJ% % C KLLr   c                     |dk  xr- | j                   j                  d      xr | j                  dk(   xs | j                   dk(  S )Nr9   DW_FORM_blockDW_AT_const_valueDW_FORM_exprloc)form
startswithnamer   s     r   r   z&LocationParser._attribute_has_loc_expr@  sL    " 1tyy';';O'L 1		000+II**	,r   c                 p    |dk  xr  | j                   dv xr | j                  dk(   xs | j                   dv S )Nr9   )DW_FORM_data1DW_FORM_data2DW_FORM_data4DW_FORM_data8r   )DW_FORM_sec_offsetDW_FORM_loclistx)r   r   r   s     r   rl   z&LocationParser._attribute_has_loc_listF  sL    " 6bb6YY"555H 		GG	Ir   c                     | j                   dv S )N)rd   DW_AT_string_lengthr   DW_AT_return_addrDW_AT_data_member_locationDW_AT_frame_baseDW_AT_segmentDW_AT_static_linkDW_AT_use_locationDW_AT_vtable_elem_locationDW_AT_call_valueDW_AT_GNU_call_site_valueDW_AT_GNU_call_site_targetDW_AT_GNU_call_site_data_value)r   )r   s    r   r   z-LocationParser._attribute_is_loclistptr_classM  s    		 	A 	A 		Br   r   )rQ   rR   rS   rT   rB   staticmethodro   r   r   rl   r   rU   r   r   rk   rk     sh    - O OM& , ,
 I I 
B 
Br   rk   )r^   collectionsr   common.exceptionsr   common.utilsr   
dwarf_utilr	   r
   r   r   r   r   r   objectr7   r;   rk   rU   r   r   <module>r      s    
 " * ' ,.*5?,tu02Z[ 02JK r  i  L  Z  Mt  B  7	L L:XF Xt=BV =Br   