<s> import logging <EOL> from collections import defaultdict <EOL> from androguard . decompiler . dad . opcode_ins import INSTRUCTION_SET <EOL> from androguard . decompiler . dad . instruction import MoveExceptionExpression <EOL> from androguard . decompiler . dad . node import Node <EOL> from androguard . decompiler . dad . util import get_type <EOL> logger = logging . getLogger ( '<STR_LIT>' ) <EOL> class BasicBlock ( Node ) : <EOL> def __init__ ( self , name , block_ins ) : <EOL> super ( BasicBlock , self ) . __init__ ( name ) <EOL> self . ins = block_ins <EOL> self . ins_range = None <EOL> self . loc_ins = None <EOL> self . var_to_declare = set ( ) <EOL> self . catch_type = None <EOL> def get_ins ( self ) : <EOL> return self . ins <EOL> def get_loc_with_ins ( self ) : <EOL> if self . loc_ins is None : <EOL> self . loc_ins = zip ( range ( * self . ins_range ) , self . ins ) <EOL> return self . loc_ins <EOL> def remove_ins ( self , loc , ins ) : <EOL> self . ins . remove ( ins ) <EOL> self . loc_ins . remove ( ( loc , ins ) ) <EOL> def add_ins ( self , new_ins_list ) : <EOL> for new_ins in new_ins_list : <EOL> self . ins . append ( new_ins ) <EOL> def add_variable_declaration ( self , variable ) : <EOL> self . var_to_declare . add ( variable ) <EOL> def number_ins ( self , num ) : <EOL> last_ins_num = num + len ( self . ins ) <EOL> self . ins_range = [ num , last_ins_num ] <EOL> self . loc_ins = None <EOL> return last_ins_num <EOL> def set_catch_type ( self , _type ) : <EOL> self . catch_type = _type <EOL> class StatementBlock ( BasicBlock ) : <EOL> def __init__ ( self , name , block_ins ) : <EOL> super ( StatementBlock , self ) . __init__ ( name , block_ins ) <EOL> self . type . is_stmt = True <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_statement_node ( self ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . num , self . name ) <EOL> class ReturnBlock ( BasicBlock ) : <EOL> def __init__ ( self , name , block_ins ) : <EOL> super ( ReturnBlock , self ) . __init__ ( name , block_ins ) <EOL> self . type . is_return = True <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_return_node ( self ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . num , self . name ) <EOL> class ThrowBlock ( BasicBlock ) : <EOL> def __init__ ( self , name , block_ins ) : <EOL> super ( ThrowBlock , self ) . __init__ ( name , block_ins ) <EOL> self . type . is_throw = True <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_throw_node ( self ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . num , self . name ) <EOL> class SwitchBlock ( BasicBlock ) : <EOL> def __init__ ( self , name , switch , block_ins ) : <EOL> super ( SwitchBlock , self ) . __init__ ( name , block_ins ) <EOL> self . switch = switch <EOL> self . cases = [ ] <EOL> self . default = None <EOL> self . node_to_case = defaultdict ( list ) <EOL> self . type . is_switch = True <EOL> def add_case ( self , case ) : <EOL> self . cases . append ( case ) <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_switch_node ( self ) <EOL> def copy_from ( self , node ) : <EOL> super ( SwitchBlock , self ) . copy_from ( node ) <EOL> self . cases = node . cases [ : ] <EOL> self . switch = node . switch [ : ] <EOL> def update_attribute_with ( self , n_map ) : <EOL> super ( SwitchBlock , self ) . update_attribute_with ( n_map ) <EOL> self . cases = [ n_map . get ( n , n ) for n in self . cases ] <EOL> for node1 , node2 in n_map . iteritems ( ) : <EOL> if node1 in self . node_to_case : <EOL> self . node_to_case [ node2 ] = self . node_to_case . pop ( node1 ) <EOL> def order_cases ( self ) : <EOL> values = self . switch . get_values ( ) <EOL> if len ( values ) < len ( self . cases ) : <EOL> self . default = self . cases . pop ( <NUM_LIT:0> ) <EOL> for case , node in zip ( values , self . cases ) : <EOL> self . node_to_case [ node ] . append ( case ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . num , self . name ) <EOL> class CondBlock ( BasicBlock ) : <EOL> def __init__ ( self , name , block_ins ) : <EOL> super ( CondBlock , self ) . __init__ ( name , block_ins ) <EOL> self . true = None <EOL> self . false = None <EOL> self . type . is_cond = True <EOL> def update_attribute_with ( self , n_map ) : <EOL> super ( CondBlock , self ) . update_attribute_with ( n_map ) <EOL> self . true = n_map . get ( self . true , self . true ) <EOL> self . false = n_map . get ( self . false , self . false ) <EOL> def neg ( self ) : <EOL> if len ( self . ins ) != <NUM_LIT:1> : <EOL> raise RuntimeWarning ( '<STR_LIT>' ) <EOL> self . ins [ - <NUM_LIT:1> ] . neg ( ) <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_cond_node ( self ) <EOL> def visit_cond ( self , visitor ) : <EOL> if len ( self . ins ) != <NUM_LIT:1> : <EOL> raise RuntimeWarning ( '<STR_LIT>' ) <EOL> return visitor . visit_ins ( self . ins [ - <NUM_LIT:1> ] ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . num , self . name ) <EOL> class Condition ( object ) : <EOL> def __init__ ( self , cond1 , cond2 , isand , isnot ) : <EOL> self . cond1 = cond1 <EOL> self . cond2 = cond2 <EOL> self . isand = isand <EOL> self . isnot = isnot <EOL> def neg ( self ) : <EOL> self . isand = not self . isand <EOL> self . cond1 . neg ( ) <EOL> self . cond2 . neg ( ) <EOL> def get_ins ( self ) : <EOL> lins = [ ] <EOL> lins . extend ( self . cond1 . get_ins ( ) ) <EOL> lins . extend ( self . cond2 . get_ins ( ) ) <EOL> return lins <EOL> def get_loc_with_ins ( self ) : <EOL> loc_ins = [ ] <EOL> loc_ins . extend ( self . cond1 . get_loc_with_ins ( ) ) <EOL> loc_ins . extend ( self . cond2 . get_loc_with_ins ( ) ) <EOL> return loc_ins <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_short_circuit_condition ( self . isnot , self . isand , <EOL> self . cond1 , self . cond2 ) <EOL> def __str__ ( self ) : <EOL> if self . isnot : <EOL> ret = '<STR_LIT>' <EOL> else : <EOL> ret = '<STR_LIT>' <EOL> return ret % ( self . cond1 , [ '<STR_LIT>' , '<STR_LIT>' ] [ self . isand ] , self . cond2 ) <EOL> class ShortCircuitBlock ( CondBlock ) : <EOL> def __init__ ( self , name , cond ) : <EOL> super ( ShortCircuitBlock , self ) . __init__ ( name , None ) <EOL> self . cond = cond <EOL> def get_ins ( self ) : <EOL> return self . cond . get_ins ( ) <EOL> def get_loc_with_ins ( self ) : <EOL> return self . cond . get_loc_with_ins ( ) <EOL> def neg ( self ) : <EOL> self . cond . neg ( ) <EOL> def visit_cond ( self , visitor ) : <EOL> return self . cond . visit ( visitor ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . num , self . cond ) <EOL> class LoopBlock ( CondBlock ) : <EOL> def __init__ ( self , name , cond ) : <EOL> super ( LoopBlock , self ) . __init__ ( name , None ) <EOL> self . cond = cond <EOL> def get_ins ( self ) : <EOL> return self . cond . get_ins ( ) <EOL> def neg ( self ) : <EOL> self . cond . neg ( ) <EOL> def get_loc_with_ins ( self ) : <EOL> return self . cond . get_loc_with_ins ( ) <EOL> def visit ( self , visitor ) : <EOL> return visitor . visit_loop_node ( self ) <EOL> def visit_cond ( self , visitor ) : <EOL> return self . cond . visit_cond ( visitor ) <EOL> def update_attribute_with ( self , n_map ) : <EOL> super ( LoopBlock , self ) . update_attribute_with ( n_map ) <EOL> self . cond . update_attribute_with ( n_map ) <EOL> def __str__ ( self ) : <EOL> if self . looptype . is_pretest : <EOL> if self . false in self . loop_nodes : <EOL> return '<STR_LIT>' % ( self . num , self . name , self . cond ) <EOL> return '<STR_LIT>' % ( self . num , self . name , self . cond ) <EOL> elif self . looptype . is_posttest : <EOL> return '<STR_LIT>' % ( self . num , self . name , self . cond ) <EOL> elif self . looptype . is_endless : <EOL> return '<STR_LIT>' % ( self . num , self . name , self . cond ) <EOL> return '<STR_LIT>' % ( self . num , self . name ) <EOL> class TryBlock ( BasicBlock ) : <EOL> def __init__ ( self , node ) : <EOL> super ( TryBlock , self ) . __init__ ( '<STR_LIT>' % node . name , None ) <EOL> self . try_start = node <EOL> self . catch = [ ] <EOL> @ property <EOL> def num ( self ) : <EOL> return self . try_start . num <EOL> @ num . setter <EOL> def num ( self , value ) : <EOL> pass <EOL> def add_catch_node ( self , node ) : <EOL> self . catch . append ( node ) <EOL> def visit ( self , visitor ) : <EOL> visitor . visit_try_node ( self ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . name , self . catch ) <EOL> class CatchBlock ( BasicBlock ) : <EOL> def __init__ ( self , node ) : <EOL> first_ins = node . ins [ <NUM_LIT:0> ] <EOL> self . exception_ins = None <EOL> if isinstance ( first_ins , MoveExceptionExpression ) : <EOL> self . exception_ins = first_ins <EOL> node . ins . pop ( <NUM_LIT:0> ) <EOL> super ( CatchBlock , self ) . __init__ ( '<STR_LIT>' % node . name , node . ins ) <EOL> self . catch_start = node <EOL> self . catch_type = node . catch_type <EOL> def visit ( self , visitor ) : <EOL> visitor . visit_catch_node ( self ) <EOL> def visit_exception ( self , visitor ) : <EOL> if self . exception_ins : <EOL> visitor . visit_ins ( self . exception_ins ) <EOL> else : <EOL> visitor . write ( get_type ( self . catch_type ) ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % self . name <EOL> def build_node_from_block ( block , vmap , gen_ret , exception_type = None ) : <EOL> ins , lins = None , [ ] <EOL> idx = block . get_start ( ) <EOL> for ins in block . get_instructions ( ) : <EOL> opcode = ins . get_op_value ( ) <EOL> if opcode == - <NUM_LIT:1> : <EOL> idx += ins . get_length ( ) <EOL> continue <EOL> try : <EOL> _ins = INSTRUCTION_SET [ opcode ] <EOL> except IndexError : <EOL> logger . error ( '<STR_LIT>' , ins . get_name ( ) . lower ( ) ) <EOL> _ins = INSTRUCTION_SET [ <NUM_LIT:0> ] <EOL> if opcode == <NUM_LIT> : <EOL> fillarray = block . get_special_ins ( idx ) <EOL> lins . append ( _ins ( ins , vmap , fillarray ) ) <EOL> elif ( <NUM_LIT> <= opcode <= <NUM_LIT> or <NUM_LIT> <= opcode <= <NUM_LIT> ) : <EOL> lins . append ( _ins ( ins , vmap , gen_ret ) ) <EOL> elif <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> lins . append ( _ins ( ins , vmap , gen_ret . new ( ) ) ) <EOL> elif <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> lins . append ( _ins ( ins , vmap , gen_ret . last ( ) ) ) <EOL> elif opcode == <NUM_LIT> : <EOL> lins . append ( _ins ( ins , vmap , exception_type ) ) <EOL> elif <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> idx += ins . get_length ( ) <EOL> continue <EOL> else : <EOL> lins . append ( _ins ( ins , vmap ) ) <EOL> idx += ins . get_length ( ) <EOL> name = block . get_name ( ) <EOL> if <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> node = ReturnBlock ( name , lins ) <EOL> elif <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> idx -= ins . get_length ( ) <EOL> values = block . get_special_ins ( idx ) <EOL> node = SwitchBlock ( name , values , lins ) <EOL> elif <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> node = CondBlock ( name , lins ) <EOL> node . off_last_ins = ins . get_ref_off ( ) <EOL> elif opcode == <NUM_LIT> : <EOL> node = ThrowBlock ( name , lins ) <EOL> else : <EOL> if <NUM_LIT> <= opcode <= <NUM_LIT> : <EOL> lins . pop ( ) <EOL> node = StatementBlock ( name , lins ) <EOL> return node </s>
