
    dyu                        d dl Z d dlmZ ddlmZmZmZmZ ddlm	Z	m
Z
 ddlmZ ddlmZ dd	l  G d
 de      Zd Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      Z edd      ZdZdZi Z e e       jA                               D ]!  Z!e!jE                  d      se!e e       e!   <   # y)     N)
namedtuple   )struct_parsedwarf_assertpreserve_stream_pos	iterbytes)StructSwitch   )DW_EH_encoding_flags)DWARFStructs)*c                   `    e Zd ZdZ	 ddZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zed        Zy)CallFrameInfoa   DWARF CFI (Call Frame Info)

    Note that this also supports unwinding information as found in .eh_frame
    sections: its format differs slightly from the one in .debug_frame. See
    <http://www.airs.com/blog/archives/460>.

        stream, size:
            A stream holding the .debug_frame section, and the size of the
            section in it.

        address:
            Virtual address for this section. This is used to decode relative
            addresses.

        base_structs:
            The structs to be used as the base for parsing this section.
            Eventually, each entry gets its own structs based on the initial
            length field it starts with. The address_size, however, is taken
            from base_structs. This appears to be a limitation of the DWARFv3
            standard, fixed in v4.
            A discussion I had on dwarf-discuss confirms this.
            So for DWARFv4 we'll take the address size from the CIE header,
            but for earlier versions will use the elfclass of the containing
            file; more sophisticated methods are used by libdwarf and others,
            such as guessing which CU contains which FDEs (based on their
            address ranges) and taking the address_size from those CUs.
    c                 f    || _         || _        || _        || _        d | _        i | _        || _        y N)streamsizeaddressbase_structsentries_entry_cachefor_eh_frame)selfr   r   r   r   r   s         :/usr/lib/python3/dist-packages/elftools/dwarf/callframe.py__init__zCallFrameInfo.__init__/   s:    	(
 
 )    c                 \    | j                   | j                         | _         | j                   S )z Get a list of entries that constitute this CFI. The list consists
            of CIE or FDE objects, in the order of their appearance in the
            section.
        )r   _parse_entriesr   s    r   get_entrieszCallFrameInfo.get_entriesA   s(    
 <<..0DL||r   c                     g }d}|| j                   k  rJ|j                  | j                  |             | j                  j	                         }|| j                   k  rJ|S )Nr   )r   append_parse_entry_atr   tell)r   r   offsets      r   r   zCallFrameInfo._parse_entriesL   sV    tyy NN4//78[[%%'F tyy  r   c           	         || j                   v r| j                   |   S t        | j                  j                  d      | j                  |      }| j
                  r|dk(  rt        |      S |dk(  rdnd}t        | j                  j                  || j                  j                        }t        |j                  d      | j                        }| j
                  r|dk(  }n|dk(  xr |dk(  xs |dk(  }|r<| j
                  r|j                  n|j                  }t        || j                  |      }n| j                  ||      }| j
                  s;|j                  dk\  r,t        |j                  |j                  |j                        }|r| j!                  ||      \  }	}
n| j#                  |||      }| j%                  |      }	|j&                  j)                  d	t*        d
         }|t*        d
   k7  r8| j-                  || j                  j/                         t1        |	      z
  |      }nd}||j2                  z   |j5                         z   }| j7                  || j                  j/                         |      }|rt9        |||
|	|      | j                   |<   n2| j#                  |||      }t;        ||||||	      | j                   |<   | j                   |   S )z Parse an entry from self.stream starting with the given offset.
            Return the entry object. self.stream will point right after the
            entry.
         r   l    @       )little_endiandwarf_formataddress_sizel       LSDA_encodingDW_EH_PE_omitN)headerinstructionsr&   augmentation_dictaugmentation_bytesstructs)r1   r2   r&   r5   cier4   lsda_pointer)r   r   r   Dwarf_uint32r   r   ZEROr   r+   r-   Dwarf_offsetEH_CIE_headerDwarf_CIE_header_parse_fde_headerdwarf_versionr,   _parse_cie_augmentation_parse_cie_for_fde_read_augmentation_datar3   getr   _parse_lsda_pointerr%   lenlengthinitial_length_field_size_parse_instructionsCIEFDE)r   r&   entry_lengthr,   entry_structsCIE_idis_CIEheader_structr1   	aug_bytesaug_dictr6   lsda_encodingr7   
end_offsetr2   s                   r   r$   zCallFrameInfo._parse_entry_atT   s   
 T&&&$$V,,#**2.VE !2<)Z7rR$++99%**779 &&r*DKK9 q[F #<*(< -,,   $ 1 1 +88*;;  "t{{F4F ++M6BF
   ]%@%@A%E(+99*77#002M "&">">M#+Ix ))&&-HC44]CI1155oG[\kGlmM 4_ EE#778<8H8H8JSQZ^8[8E G  $ V]]"3356 	 //4;;++-z; (+L"*#,%	)'Df% ))&&-HC(+L%3#,)	)Df%   ((r   c                 N   g }||k  rt        |j                  d      | j                  |      }g }|t        z  }|t        z  }|t
        k(  r|g}n|t        k(  r)|t        |j                  d      | j                        g}n|t        k(  r|g}n|t        t        t        fv rg }n|t        k(  r(t        |j                  d      | j                        g}n|t        k(  r(t        |j                  d      | j                        g}n^|t        k(  r(t        |j!                  d      | j                        g}n-|t"        k(  r(t        |j%                  d      | j                        g}n|t&        t(        t*        t,        fv rLt        |j                  d      | j                        t        |j                  d      | j                        g}n|t.        t0        t2        t4        t6        fv r(t        |j                  d      | j                        g}nS|t8        k(  r(t        |j;                  d      | j                        g}n"|t<        k(  r%t        |j>                  d   | j                        g}n|t@        tB        fv rIt        |j                  d      | j                        t        |j>                  d   | j                        g}n|tD        tF        tH        fv rKt        |j                  d      | j                        t        |j;                  d      | j                        g}n?|tJ        k(  r't        |j                  d      | j                        g}ntM        dd|z         |jO                  tQ        ||             | j                  jS                         }||k  r|S )z Parse a list of CFI instructions from self.stream, starting with
            the offset and until (not including) end_offset.
            Return a list of CallFrameInstruction objects.
        r(   DW_FORM_blockFzUnknown CFI opcode: 0x%xopcodeargs)*r   Dwarf_uint8r   _PRIMARY_MASK_PRIMARY_ARG_MASKDW_CFA_advance_locDW_CFA_offsetDwarf_uleb128DW_CFA_restore
DW_CFA_nopDW_CFA_remember_stateDW_CFA_restore_stateDW_CFA_set_locDwarf_target_addrDW_CFA_advance_loc1DW_CFA_advance_loc2Dwarf_uint16DW_CFA_advance_loc4r8   DW_CFA_offset_extendedDW_CFA_registerDW_CFA_def_cfaDW_CFA_val_offsetDW_CFA_restore_extendedDW_CFA_undefinedDW_CFA_same_valueDW_CFA_def_cfa_registerDW_CFA_def_cfa_offsetDW_CFA_def_cfa_offset_sfDwarf_sleb128DW_CFA_def_cfa_expressionDwarf_dw_formDW_CFA_expressionDW_CFA_val_expressionDW_CFA_offset_extended_sfDW_CFA_def_cfa_sfDW_CFA_val_offset_sfDW_CFA_GNU_args_sizer   r#   CallFrameInstructionr%   )	r   r5   r&   rR   r2   rV   rW   primaryprimary_args	            r   rG   z!CallFrameInfo._parse_instructions   sL   
 z!!'"5"5b"94;;OFD},G #44K,,#}M) !6!6r!:DKKHJ N*#}J(=02 2>) !:!:2!>LN..$W%8%8%<dkkJK..$W%9%9"%=t{{KL..$W%9%9"%=t{{KL2O*,=? ? !!6!6r!:DKKH !6!6r!:DKKHJ 35E-/F13 3 %W%:%:2%>LM33$W%:%:2%>LM44$))/:DKKI J-/DEE !6!6r!:DKKH --o>MN 5-/CE E !!6!6r!:DKKH !6!6r!:DKKHJ //$W%:%:2%>LMU$>$GH 4F NO[[%%'Fs z!t r   c                     | j                   r|d   }||j                  dz  z   |z
  }n|d   }t        | j                        5  | j	                  |      cddd       S # 1 sw Y   yxY w)z3 Parse the CIE that corresponds to an FDE.
        CIE_pointer   N)r   r,   r   r   r$   )r   
fde_offset
fde_headerrK   cie_displacement
cie_offsets         r   r@   z CallFrameInfo._parse_cie_for_fde   st       *-8$}'A'AQ'FF,-J $M2J !- 	4''
3	4 	4 	4s   AA&c                 B   |j                  d      }|sdi fS |j                  d      sJ dj                  t        |                   |j	                  d      |j                  d      |j                  d      dt        d	|j                  d
      t        dd | j                  |      j                         D ci c]  \  }}| |d       c}}            d}g }i }t        |      D ]#  }		 ||	   }
|
du rd||
<   |j                  |
       % | j                  j                         }t        dg| }|j                  t!        || j                  |             | j                  j#                  |       | j%                  |      }||fS c c}}w # t        $ r Y  w xY w)z Parse CIE augmentation data from the annotation string in `header`.

        Return a tuple that contains 1) the augmentation data as a string
        (without the length field) and 2) the augmentation data as a dict.
        augmentationr(      zz!Unhandled augmentation string: {}rE   r/   FDE_encodingTpersonalityencodingfunctionc                      | j                   dz  S )N   )r   )ctxs    r   <lambda>z7CallFrameInfo._parse_cie_augmentation.<locals>.<lambda>  s    s||d/B r   )r      L   R   S   PAugmentation_Data)rB   
startswithformatreprr]   rX   r	   r
   _eh_encoding_to_fielditemsr   KeyErrorr#   r   r%   updater   seekrA   )r   r1   rK   r   encfld_consavailable_fieldsfieldsrP   bfldr&   structrO   s                 r   r?   z%CallFrameInfo._parse_cie_augmentation  s    zz.18O &&t, 	L/66tL7IJ	L,  --h7++O<++N;))*5z#B 11-@FFHEJ%X *--EJ KL
  <( 		#A&q) d{ $c"		#  !!#+5f5VT[[&AB 00?	8$$AEJ  s   9F-F	FFc                     | j                   syt        t        d|j                  d            | j                        d   }| j                  j                  |      S )z Read augmentation data.

        This assumes that the augmentation string starts with 'z', i.e. that
        augmentation data is prefixed by a length field, which is not returned.
        r   Dummy_Augmentation_DatarE   )r   r   r	   r]   r   read)r   rK   augmentation_data_lengths      r   rA   z%CallFrameInfo._read_augmentation_dataA  s]       #/, ..x8:KK$ "$#  {{ 899r   c                 :   |t         d   k7  sJ |dz  }|dz  }| j                  |      }t        t        d ||   d            | j                  |      d   }|t         d   k(  r	 |S |t         d   k(  r|| j
                  |z   z  }|S J d	j                  |             )
a}   Parse bytes to get an LSDA pointer.

        The basic encoding (lower four bits of the encoding) describes how the values are encoded in a CIE or an FDE.
        The modifier (upper four bits of the encoding) describes how the raw values, after decoded using a basic
        encoding, should be modified before using.

        Ref: https://www.airs.com/blog/archives/460
        r0   r      r   LSDA_pointer)
stream_posDW_EH_PE_absptrDW_EH_PE_pcrelz5Unsupported encoding modifier for LSDA pointer: {:#x})r   r   r   r	   r   r   r   )r   r5   stream_offsetr   basic_encodingmodifierformatsptrs           r   rC   z!CallFrameInfo._parse_lsda_pointerP  s     /@@@@!Dd?,,W5&*7>*>:<KKM3 4BC
 +,=>> 
 -.>??4<<-//C
 
 cQXXYabb5r   c                    | j                   s!t        |j                  | j                  |      S |j	                  d      |j                  d      g}t        t        dg| | j                  |      }| j                  |||      }| j                  j                         }|j                  d   }|t        d   k7  sJ |dz  }|dz  }	| j                  |      }
|j                   |
|   d             |j                   |
|   d	             t        t        d
g| | j                  |      }|	dk(  r	 |S |	t        d   k(  r|dxx   | j                  |z   z  cc<   |S J dj                  |             )zB Compute a struct to parse the header of the current FDE.
        rE   r   eh_frame_minimal_headerr   r0   r   r   initial_locationaddress_rangeDwarf_FDE_headerr   r   zUnsupported encoding: {:#x})r   r   r   r   Dwarf_initial_lengthr:   r	   r@   r%   r3   r   r   r#   r   r   )r   rK   r&   r   minimal_headerr6   initial_location_offsetr   r   encoding_modifierr   results               r   r=   zCallFrameInfo._parse_fde_headero  s       > > &( (  44X>,,];=
 &f-F '6.4'67;{{FL%%fnmL"&++"2"2"4
 ((8/@@@@!D$tO ,,];-gn-.@AB-gn-o>?f%7A&A"kk63 !  "67G"HH %&668&
  I7>>xHH5r   c                 \   t         d   | j                  t         d   | j                  t         d   | j                  t         d   | j                  t         d   | j
                  t         d   | j                  t         d   | j                  t         d   | j                  t         d	   | j                  i	S )
z
        Return a mapping from basic encodings (DW_EH_encoding_flags) the
        corresponding field constructors (for instance
        entry_structs.Dwarf_uint32).
        r   DW_EH_PE_uleb128DW_EH_PE_udata2DW_EH_PE_udata4DW_EH_PE_udata8DW_EH_PE_sleb128DW_EH_PE_sdata2DW_EH_PE_sdata4DW_EH_PE_sdata8)
r   rc   r]   rf   r8   Dwarf_uint64rr   Dwarf_int16Dwarf_int32Dwarf_int64)rK   s    r   r   z#CallFrameInfo._eh_encoding_to_field  s     !!23// !34++ !23** !23** !23** !34++ !23)) !23)) !23))'
 	
r   N)F)__name__
__module____qualname____doc__r   r!   r   r$   rG   r@   r?   rA   rC   r=   staticmethodr    r   r   r   r      sX    8 $)$^)@@D4$7%r:>,\ 
 
r   r   c                 B    | t         z  }|dk(  r	t        |    S t        |   S )z3 Given an opcode, return the instruction name.
    r   )rY   _OPCODE_NAME_MAP)rV   r|   s     r   instruction_namer     s+     }$G!|''((r   c                       e Zd ZdZd Zd Zy)r{   a   An instruction in the CFI section. opcode is the instruction
        opcode, numeric - as it appears in the section. args is a list of
        arguments (including arguments embedded in the low bits of some
        instructions, when applicable), decoded from the stream.
    c                      || _         || _        y r   rU   )r   rV   rW   s      r   r   zCallFrameInstruction.__init__  s    	r   c                 `    dt        | j                        | j                  | j                  fz  S )Nz%s (0x%x): %s)r   rV   rW   r    s    r   __repr__zCallFrameInstruction.__repr__  s/    T[[)4;;		"C C 	Cr   Nr   r   r   r   r   r   r   r   r   r{   r{     s    
Cr   r{   c                   ,    e Zd ZdZ	 ddZd Zd Zd Zy)CFIEntryaX   A common base class for CFI entries.
        Contains a header and a list of instructions (CallFrameInstruction).
        offset: the offset of this entry from the beginning of the section
        cie: for FDEs, a CIE pointer is required
        augmentation_dict: Augmentation data as a parsed struct (dict): see
            CallFrameInfo._parse_cie_augmentation and
            http://www.airs.com/blog/archives/460.
        augmentation_bytes: Augmentation data as a chain of bytes: see
            CallFrameInfo._parse_cie_augmentation and
            http://www.airs.com/blog/archives/460.
    Nc                 |    || _         || _        || _        || _        || _        d | _        |r|ni | _        || _        y r   )r1   r5   r2   r&   r6   _decoded_tabler3   r4   )r   r1   r5   r2   r&   r3   r4   r6   s           r   r   zCFIEntry.__init__  sC    ("6G!2R"4r   c                 \    | j                   | j                         | _         | j                   S )z Decode the CFI contained in this entry and return a
            DecodedCallFrameTable object representing it. See the documentation
            of that class to understand how to interpret the decoded table.
        )r   _decode_CFI_tabler    s    r   get_decodedzCFIEntry.get_decoded  s-    
 &"&"8"8":D"""r   c                      | j                   |   S )z6 Implement dict-like access to header entries
        )r1   )r   names     r   __getitem__zCFIEntry.__getitem__  s     {{4  r   c                    t        | t              r| }t        dt        dd            }g n| j                  }|j                         }t        |j                        dkD  r8t        j                  |j                  d         }t        j                  |      }nt        t        dd            }| d   |d<   t        j                  |j                        g }g }fd	}| j                  D ]  }t        |j                        }	|	d
k(  r7|j                  t        j                  |             |j                  d   |d<   U|	dv rE|j                  t        j                  |             |dxx   |j                  d   |d   z  z  cc<   |	dk(  r+t        |j                  d   |j                  d         |d<   |	dk(  r2t        |j                  d   |j                  d   |d   z        |d<   |	dk(  r,t        |j                  d   |d   j                        |d<   6|	dk(  r,t        |d   j                   |j                  d         |d<   g|	dk(  rt        |j                  d         |d<   |	dk(  r@ ||j                  d          t#        t"        j$                        ||j                  d   <   |	dk(  r@ ||j                  d          t#        t"        j&                        ||j                  d   <   |	dv rT ||j                  d          t#        t"        j(                  |j                  d   |d   z        ||j                  d   <   l|	dv rT ||j                  d          t#        t"        j*                  |j                  d   |d   z        ||j                  d   <   |	dk(  rN ||j                  d          t#        t"        j,                  |j                  d         ||j                  d   <   |	dk(  rN ||j                  d          t#        t"        j.                  |j                  d         ||j                  d   <   j|	dk(  rN ||j                  d          t#        t"        j0                  |j                  d         ||j                  d   <   |	dv r ||j                  d          t3        t        | t4              d|	z         |j                  d   v r$||j                  d      ||j                  d   <   (|j7                  |j                  d   d       I|	dk(  r&|j                  t        j8                  |             t|	d k(  s{|d   }
|j7                         }|
|d<    |d   j                   t        |      d!kD  r|j                  |       t;        |"      S )#zr Decode the instructions contained in the given CFI entry and return
            a DecodedCallFrameTable.
        r   N)regr&   )pccfa)r   r   r   c                 2    | vrj                  |        y y r   )r#   )regnum	reg_orders    r   _add_to_orderz1CFIEntry._decode_CFI_table.<locals>._add_to_order  s      Y&  ( 'r   rb   )rd   re   rg   r[   code_alignment_factorrj   r   r   rx   ro   rp   rs   )exprrm   rn   )r\   rh   rw   data_alignment_factor)rk   ry   ri   ru   rv   )r^   rl   z%s instruction must be in a FDEr`   ra   r   )tabler   )
isinstancerH   dictCFARuler6   r   rD   r   copyr   r2   r   rV   r#   rW   r&   r   RegisterRule	UNDEFINED
SAME_VALUEOFFSET
VAL_OFFSETREGISTER
EXPRESSIONVAL_EXPRESSIONr   rI   popdeepcopyDecodedCallFrameTable)r   r6   cur_linecie_decoded_tablelast_line_in_CIEr   
line_stackr   instrr   r   r   s              @r   r   zCFIEntry._decode_CFI_table  s0    dC Cqg$q&ABHI
 ((C # 1$**+a/#'99->-D-DR-H#I 99%56GQ$?@!"45HTN		"3"="=>I 
	) && N	$E
 $ELL1D''TYYx01!&A I ITYYx01%**Q-#6M2N"NN))")

1 ::a=#* ,,")

1 ::a=3/F+GG#I 22")

1#E?11#3 00") ++ ::a=#* 44")uzz!}"=++ejjm,*6|7M7M*NA',,ejjm,*6|7N7N*OA' 9 9ejjm,*6 ''JJqMC(?$@@+BA' FFejjm,*6 ++JJqMC(?$@@+BA' **ejjm,*6 ))JJqM+#A' ,,ejjm,*6 ++JJqM+#A' 00ejjm,*6 //JJqM+#A' FFejjm,tS)5<> ::a=$44.>uzz!}.MHUZZ]+LLA500!!$--"9://d^%>>+!#]N	$d E?*c(ma.?LL"$5IFFr   )Nr   N)r   r   r   r   r   r   r   r   r   r   r   r   r     s$    
 AE	5#!
xGr   r   c                       e Zd Zy)rH   N)r   r   r   r   r   r   rH   rH   y  s    r   rH   c                         e Zd Zd fd	Z xZS )rI   c                 F    t         t        |   ||||||       || _        y )N)r4   r6   )superrI   r   r7   )	r   r1   r5   r2   r&   r4   r6   r7   	__class__s	           r   r   zFDE.__init__~  s)    c4!&'<\ntw!x(r   NNN)r   r   r   r   __classcell__)r  s   @r   rI   rI   }  s    ) )r   rI   c                       e Zd ZdZd Zy)r9   z End marker for the sequence of CIE/FDE.

    This is specific to `.eh_frame` sections: this kind of entry does not exist
    in pure DWARF. `readelf` displays these as "ZERO terminator", hence the
    class name.
    c                     || _         y r   )r&   )r   r&   s     r   r   zZERO.__init__  s	    r   N)r   r   r   r   r   r   r   r   r9   r9     s    r   r9   c                   >    e Zd ZdZdZdZdZdZdZdZ	dZ
d	ZddZd Zy
)r   z Register rules are used to find registers in call frames. Each rule
        consists of a type (enumeration following DWARFv3 section 6.4.1)
        and an optional argument to augment the type.
    r   r   r   r   r   r   r   ARCHITECTURALNc                      || _         || _        y r   typearg)r   r  r  s      r   r   zRegisterRule.__init__  s    	r   c                 <    d| j                   d| j                  dS )NzRegisterRule(z, )r  r    s    r   r   zRegisterRule.__repr__  s    )-DHH==r   r   )r   r   r   r   r   r   r   r   r   r   r   r  r   r   r   r   r   r   r     s;     IJFJHJ%N#M>r   r   c                       e Zd ZdZddZd Zy)r   z A CFA rule is used to compute the CFA for each location. It either
        consists of a register+offset, or a DWARF expression.
    Nc                 .    || _         || _        || _        y r   r   r&   r   )r   r   r&   r   s       r   r   zCFARule.__init__  s    	r   c                 V    d| j                   d| j                  d| j                  dS )NzCFARule(reg=z	, offset=z, expr=r  r  r    s    r   r   zCFARule.__repr__  s    HHdkk499. 	.r   r  r   r   r   r   r   r     s    
.r   r   r   ztable reg_order   ?   DW_CFA)#r   collectionsr   common.utilsr   r   r   r   	constructr	   r
   enumsr   r5   r   	constantsobjectr   r   r{   r   rH   rI   r9   r   r   r   rY   rZ   r   listglobalskeysr   r   r   r   r   <module>r$     s     "@ @ & ' ! e
F e
P)C6 C]Gv ]GJ	( 	)( )6 >6 >,.f .B #.0   
  !" 1Dx ,04)1r   