
    jH                         d dl mZ d dlmZ d dlmZmZmZ d dlm	Z	  G d d          Z
d Zd Zd	 Zd
 Z G d d          Zd Zd ZdS )    )defaultdict)logger)	CondBlockStatementBlockbuild_node_from_block)Variablec                       e Zd ZdZd Zd Zd Zd Zd 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d Zd Zd ZdS )Graphz
    Stores a CFG (Control Flow Graph), which is a directed graph.

    The CFG defines an entry node :py:attr:`entry`, a single exit node :py:attr:`exit`, a list of nodes
    :py:attr:`nodes` and a list of edges :py:attr:`edges`.
    c                 :   d | _         d | _        t                      | _        t	          t                    | _        g | _        t	          t                    | _        t	          t                    | _        t	          t                    | _	        d | _
        d | _        d S N)entryexitlistnodesr   edgesrpocatch_edgesreverse_edgesreverse_catch_edges
loc_to_insloc_to_nodeselfs    b/home/ubuntu/.hermes/hermes-agent/venv/lib/python3.11/site-packages/androguard/decompiler/graph.py__init__zGraph.__init__&   sv    
	VV
 &&
&t,,(..#.t#4#4     c                 8    | j                             |g           S r   )r   getr   nodes     r   sucsz
Graph.sucs3   s    z~~dB'''r   c                 p    | j                             |g           | j                            |g           z   S r   )r   r   r   r   s     r   all_sucszGraph.all_sucs6   s0    z~~dB''$*:*>*>tR*H*HHHr   c                 L    d | j                             |g           D             S )Nc                      g | ]}|j         	|S  in_catch.0ns     r   
<listcomp>zGraph.preds.<locals>.<listcomp>:   s    NNNa1:NNNNr   )r   r   r   s     r   predszGraph.preds9   s)    NN4-11$;;NNNNr   c                 p    | j                             |g           | j                            |g           z   S r   )r   r   r   r   s     r   	all_predszGraph.all_preds<   s<    !%%dB//$2J2N2N"3
 3
 
 	
r   c                 :    | j                             |           dS )z
        Adds the given node to the graph, without connecting it to anyhting else.

        :param androguard.decompiler.node.Node node: node to add
        N)r   appendr   s     r   add_nodezGraph.add_nodeA   s      	
$r   c                     | j         |         }||vr|                    |           | j        |         }||vr|                    |           d S d S r   )r   r1   r   )r   e1e2lsucslpredss        r   add_edgezGraph.add_edgeI   s`    
2U??LL#B'VMM" r   c                    |j         p|j         }|                    |           |                    |           | j        |         }||vr|                    |           | j        |         }||vr|                    |           d S d S r   )
catch_typeset_catch_typer   r1   r   )r   r4   r5   active_typer6   r7   s         r   add_catch_edgezGraph.add_catch_edgeQ   s    m4r}
+&&&
+&&& $U??LL)"-VMM" r   c                    | j                             |g           }|D ]"}| j        |                             |           #| j                            |g           }|D ]"}| j         |                             |           #| j                            |g           }|D ]"}| j        |                             |           #| j                            |g           }|D ]"}| j        |                             |           #| j                            |           || j        v r| j                            |           ~dS )z
        Remove the node from the graph, removes also all connections.

        :param androguard.decompiler.node.Node node: the node to remove
        N)	r   r   r   remover   popr   r   r   )r   r    r-   predsuccssuc	exc_preds	exc_succss           r   remove_nodezGraph.remove_node]   sV    "&&tR00 	* 	*DJt##D))))
tR(( 	1 	1Cs#**40000,00r::	 	0 	0DT"))$////$((r22	 	7 	7C$S)006666
$48HOOD!!!DDr   c                     i | _         i | _        d}| j        D ]V}|}|                    |          }|dz
  }| j                             |                                           || j        ||f<   Wd S )Nr      )r   r   r   
number_insupdateget_loc_with_ins)r   numr    
start_nodeend_nodes        r   rI   zGraph.number_insx   s    H 	: 	:DJ//#&&CQwHO""4#8#8#:#:;;;59DZ122	: 	:r   c                 6    | j                             |          S r   )r   r   )r   locs     r   get_ins_from_loczGraph.get_ins_from_loc   s    ""3'''r   c                 r    | j                                         D ]\  \  }}}||cxk    r|k    rn |c S d S r   )r   items)r   rP   startendr    s        r   get_node_from_loczGraph.get_node_from_loc   sc    "&"2"8"8":": 	 	LUC$""""s""""" #	 	r   c                     |                      |          }|                     |                              ||           | j                            |           d S r   )rQ   rV   
remove_insr   r@   )r   rP   inss      r   rX   zGraph.remove_ins   sU    ##C((s##..sC888C     r   c                     t          | j                  dz   }|                                 D ]}||j        z
  |_        t          | j        d           | _        dS )z
        Number the nodes in reverse post order.
        An RPO traversal visit as many predecessors of a node as possible
        before visiting the node itself.
        rH   c                     | j         S r   rL   )r+   s    r   <lambda>z#Graph.compute_rpo.<locals>.<lambda>   s    AE r   keyN)lenr   
post_orderporL   sortedr   )r   nbr    s      r   compute_rpozGraph.compute_rpo   sZ     __q OO%% 	$ 	$DDG|DHH$*//:::r   c              #   p    K    fdt                        j        d          D ]	\  }}|V  
dS )z
        Yields the :class`~androguard.decompiler.node.Node`s of the graph in post-order i.e we visit all the
        children of a node before visiting the node itself.
        c              3      K                        |                                |           D ]}|vr ||          D ]\  }}||fV  || _        |dz   | fV  d S )NrH   )addr#   rb   )r+   cntrC   s_visitr   visiteds       r   rk   z Graph.post_order.<locals>._visit   s      KKNNN}}Q'' % %g%%"(&c"2"2 % %Q!1fAD'1*r   rH   N)setr   )r   _r    rk   rl   s   `  @@r   ra   zGraph.post_order   sm      	 	 	 	 	 	 	 %%vdj!,, 	 	GAtJJJJ	 	r   Tc           
      |   ddl }ddlm}m}  |            }|                    ddddd	           t          | j        d
           D ]?}|r|j        j        r|	                     |t          |          t          |j                  d                     |	                     |t          |          t          |j                  d                     nS|                     |          D ]=}	|	                     |t          |          t          |	          d                     >| j                            |g           D ]>}
|	                     |t          |          t          |
          dd                     ?A|                    |j                            |d|z            d           dS )z
        Writes the current graph as a PNG file

        :param str name: filename (without .png)
        :param str dname: directory of the output png
        :param draw_branches:
        :return:
        r   N)DotEdge	lightgrayfilledboxCourier10)colorstyleshapefontnamefontsizec                     | j         S r   r\   )xs    r   r]   zGraph.draw.<locals>.<lambda>   s    QU r   r^   green)rw   redblueblackdashed)rw   rx   z%s.pngpng)format)ospydotrp   rq   set_node_defaultsrc   r   typeis_condr8   strtruefalser!   r   r   writepathjoin)r   namednamedraw_branchesr   rp   rq   gr    rC   except_nodes              r   drawz
Graph.draw   s    				########CEE	 	 	
 	
 	
 4:??;;; 	 	D H!2 H

44D		3ty>>IIIJJJ

44D		3tz??%HHHIIII99T?? H HCJJttCIIs3xxvFFFGGGG#/33D"==  

DD		K((%&	      	
UHtO44UCCCCCr   c                      t          |           S r   )dom_ltr   s    r   immediate_dominatorszGraph.immediate_dominators   s    d||r   c                 *    t          | j                  S r   )r`   r   r   s    r   __len__zGraph.__len__       4:r   c                 *    t          | j                  S r   )r   r   r   s    r   __repr__zGraph.__repr__   r   r   c              #   &   K   | j         D ]}|V  d S r   )r   r   s     r   __iter__zGraph.__iter__   s,      J 	 	DJJJJ	 	r   N)T)__name__
__module____qualname____doc__r   r!   r#   r-   r/   r2   r8   r=   rF   rI   rQ   rV   rX   re   ra   r   r   r   r   r   r&   r   r   r
   r
      sZ             ( ( (I I IO O O
 
 

       
 
 
  6	: 	: 	:( ( (  
! ! !
	; 	; 	;  &&D &D &D &DP          r   r
   c                    d | D             }t                      }| j        dd         D ]}|j        j        rt	          |                                          dk    rv|                                dd         }|                                d         }t          d|j        z  |          }t          d|j        z  |g          }|||<   |||<   |||<   |	                    |           |	                    |           |j
        D ]}|                    |           d|j        _        |j        |_        |j        |_        |                     |          D ]}	||	         }
||                     |	          vr|                     |
|           8|	|u r|}
|	j        j        r |	j        |u r||
_        |	j        |u r||
_        |                     |
|           |                     |          D ]}|                     |||                    | j                            |g           D ]}|                     |||                    || j        u r|| _        |                     |           |                     |           |                     ||           |                    |           |                    |           |                     |           |                    |           |D ]}|                    |           dS )z
    Split IfNodes in two nodes, the first node is the header node, the
    second one is only composed of the jump condition.
    c                     i | ]}||S r&   r&   r)   s     r   
<dictcomp>z"split_if_nodes.<locals>.<dictcomp>   s    $$$1$$$r   NrH   z%s-prez%s-condT)rm   r   r   r   r`   get_insr   r   r   	copy_fromvar_to_declareadd_variable_declarationis_stmtr   r   r/   r!   r=   r8   r   r   r   r2   update_attribute_withrF   rh   )graphnode_map	to_updater    pre_inslast_inspre_node	cond_nodevarrA   	pred_noderC   s               r   split_if_nodesr      s6   
 %$e$$$HIAAA 3  3 9 2	 4<<>>""Q&&,,.."-<<>>"-)(TY*>HH%i$)&;hZHH	!)%-"&/#""4(((##D))). ; ;C55c::::(,%!%	"&*	!OOD11 8 8D (I5::d#3#333,,YAAA t||$-	y( 79,,-5IN:--.6IONN9h7777 ::d++ = =CNN9hsm<<<< !,00r:: B BC((8C=AAAA5;&&"*EKx(((y)))x333..x888//999!!$'''MM$ - -""8,,,,- -r   c                 X   d}|rd}i }t                      }| j        dd         D ]b}|j        j        r=|| v r8|                     |          }t          |          dk    r>|d         }t          |                                          dk    rt          d |                     |          D                       r||u r|||<   |                     |          D ][}|	                    |           || 
                    |          vr|                     ||           E|                     ||           \d}|| j        u r|| _        |                     |           <|j        j        rt          |                     |                    dk    r|| j        vr||u s|| j        u s|                                }|                    |           |j        D ]}	|                    |	           | 
                    |          d         }
|
r|                     ||
           | j                            |g           D ]}|                     ||           d}|                     |           M|                    |           d|D ]}|	                    |           |dS dS )aP  
    Simplify the CFG by merging/deleting statement nodes when possible:
    If statement B follows statement A and if B has no other predecessor
    besides A, then we can merge A and B into a new statement node.
    We also remove nodes which do nothing except redirecting the control
    flow (nodes which only contains a goto).
    TFNrH   r   c              3   .   K   | ]}|j         j        V  d S r   )r   	is_switchr*   rA   s     r   	<genexpr>zsimplify.<locals>.<genexpr>7  s8        04	+     r   )rm   r   r   r   r#   r`   r   anyr/   r   r!   r=   r8   r   rF   r   add_insr   r   r   rh   )r   redor   r   r    r!   rC   rA   ins_to_merger   new_sucexception_sucs               r   simplifyr   #  s    D
 11EE	KN +	$ +	$Dy  *$TU]]~~d++t99>>1gt||~~&&!++  8=8M8M     ! !s{{ %(HTN % 5 5 2 2228<<<uzz$'7'777!00s;;;$tS1111Du{**&)%%d++++H$+EOOC0011Q66 E$555"ckksek/A/A#&;;==LLL..."1 ; ;55c::::#jjooa0G 6tW555).):)>)>sB)G)G B B,,T=AAAAD%%c***d#### 	1 	1D&&x0000c  11 11 11 11 11r   c                 8     fdfdfd}fd}i i i ci i c}t          t                    t          t                    c}d  j        D               j        d          }t	          |dd          D ]}|         }|         D ].} ||          }	t          |         |	                   x}
|<   /||
                                      |           |         } |||           ||         }|r:|                                } ||          }	|	         |         k     r|	n|||<   |:t	          d	|dz             D ]/}|         }||         }||                  k    r||         ||<   0d
| j        <   |S )z(Dominator algorithm from Lengauer-Tarjanc                     |dz   x	| <   }| x
|<   | <   d| <                        |           D ]6}	|         s| |<    ||          }|                             |            7|S )NrH   r   )r#   rh   )vr+   w_dfsancestorr   labelparentrA   semivertexs      r   r   zdom_lt.<locals>._dfsc  s    !eQ!  q	E!H"" 	 	A7 q	DAJJGKKNNNNr   c                     |          }|         rA |           |                  |                   k     r|         | <   |         | <   d S d S r   r&   )r   u	_compressr   r   r   s     r   r   zdom_lt.<locals>._compressn  sh    QKA; 	&IaLLLE!H~U1X.. 8a"1+HQKKK		& 	&r   c                 >    |          r |            |          S | S r   r&   )r   r   r   r   s    r   _evalzdom_lt.<locals>._evalv  s*    A; 	IaLLL8Or   c                     | |<   d S r   r&   )r   r   r   s     r   _linkzdom_lt.<locals>._link|  s    r   c                     i | ]}|d S )r   r&   )r*   r   s     r   r   zdom_lt.<locals>.<dictcomp>  s    &&&QAq&&&r   r   rH   r      N)r   rm   r   r   rangeminrh   r@   )r   r   r   dombucketr+   ir   r   r   ypwbpwdwr   r   r   r   r   rA   r   r   s   `             @@@@@@@@r   r   r   `  s\   	 	 	 	 	 	 	 	 	 	 	 	& & & & & & & &            "2rFHfRJE3s##[%5%5LD& '&%+&&&DU[!A1a__ 4 41Ia 	0 	0AaAd1gtAw///AQvaya   AYb!Rj 	4		AaAq'DG++QQCF  	4
 1a!e__  1IVQ  WCFCJr   c              #   \  K   | g}| h}|r|                     d          }|V  |j        rA|j        j        D ]4\  }}}||vr*|                    |           |                    |           5|j        D ]4\  }}}||vr*|                    |           |                    |           5|dS dS )zp
    Breadth first search

    Yields all nodes found from the starting point

    :param start: start node
    r   N)r@   exception_analysis
exceptionsr1   rh   childs)rT   to_visitrl   r    rn   	exceptionchilds          r   bfsr     s       wHgG
 #||A


" 	+#'#:#E + +1iG++OOI...KK	***; 	# 	#KAq%G##&&&E"""  # # # # #r   c                   &    e Zd Zd Zd Zd Zd ZdS )GenInvokeRetNamec                 "    d| _         d | _        d S )Nr   )rL   retr   s    r   r   zGenInvokeRetName.__init__  s    r   c                 h    | xj         dz  c_         t          d| j         z            | _        | j        S )NrH   ztmp%d)rL   r   r   r   s    r   newzGenInvokeRetName.new  s.    AGdh.//xr   c                     || _         d S r   r   )r   r   s     r   set_tozGenInvokeRetName.set_to  s    r   c                     | j         S r   r   r   s    r   lastzGenInvokeRetName.last  s	    xr   N)r   r   r   r   r   r   r   r&   r   r   r   r     sP            
      r   r   c                 0   |                     |          }|t          |||          }|||<   |j        r|j        j        D ]{\  }}}|                     |          }	|	t          ||||          }	d|	_        |	||<   |                    |           |	                    |           |                     ||	           ||j        D ]\  }}}
|                     |
          }|t          |
||          }|||
<   |                     ||           |j	        j
        r|                    |           |j	        j        r<|j        dz  |j        dz  z
  |j        z   }|
j        dz  }||k    r||_        ||_        |j	        j        r|j        |j        |_        |S )NTr   )r   r   r   r   r(   r;   r=   r   r8   r   r   add_caser   rU   last_lengthoff_last_insrT   r   r   )r   blockblock_to_nodevmapgen_retr    _typern   exception_targetexception_nodechild_block
child_node	if_target
child_addrs                 r   	make_noder    s   U##D|$UD'::#e 7*/*B*M 
	7 
	7&E1&*../?@@N%!6$dGU" " +/'2@./&&&))%000  ~6666"\ ( (1k"&&{33
.{D'JJJ)3M+&tZ(((9 	&MM*%%%9 	(aE$5$:;d>OO  %*a/JJ&&&		'
 y TZ/Y
Kr   c                    t          |           }t                      }t                      }i }g }|D ]%}|j        D ]\  }	}	}
|                    |
           &|D ]*}
t          ||
|||          |                               +||          |_        ~~|                                 |	                                 |j
        D ]Efd|                              D             }|r t          d |D                       rd_        Fd |D             }t          |          dk    r't          j        d           |j
        d         |_        n5t          |          dk     rt          j        d           n|d	         |_        |S )
z
    Constructs a CFG

    :param androguard.core.analysis.analysis.DEXBasicBlock start_block: The startpoint
    :param vmap: variable mapping
    :param exceptions: list of androguard.core.analysis.analysis.ExceptionAnalysis

    :rtype: Graph
    c                 4    g | ]}|j         j         k     |S r&   r\   )r*   rA   r    s     r   r,   zconstruct.<locals>.<listcomp>  s'    OOO$48dh;N;N;N;N;Nr   c              3   $   K   | ]}|j         V  d S r   r'   r   s     r   r   zconstruct.<locals>.<genexpr>  s$      994999999r   Tc                 *    g | ]}|j         j        |S r&   )r   	is_return)r*   r    s     r   r,   zconstruct.<locals>.<listcomp>#  s"    AAADTY-@A4AAAr   rH   zMultiple exit nodes found !r   zNo exit node found !r   )r   r
   r   r   r1   r  r2   r   re   rI   r   r/   allr(   r`   r   errorr   debug)start_blockr   r   
bfs_blocksr   r   r   exceptions_start_blockr   rn   r   r-   lexit_nodesr    s                @r   	constructr    s    [!!JGGE  G M 1 1	$/ 	1 	1KAq%"))%0000	1   }dGDDt,EKz			 ! !OOOO%//$"7"7OOO 	!S99599999 	! DM BAEAAAK
;!2333Yr]

	[		A		 	+,,,, ^
Lr   N)collectionsr   logurur   "androguard.decompiler.basic_blocksr   r   r   !androguard.decompiler.instructionr   r
   r   r   r   r   r   r  r  r&   r   r   <module>r     s2  " $ # # # # #               
 7 6 6 6 6 6C C C C C C C CL<- <- <-~:1 :1 :1z< < <~# # #0       "+ + +\: : : : :r   