<s> from . explorer import Explorer <EOL> import simuvex , claripy <EOL> class Callable ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , project , addr , concrete_only = False , prototype = None , base_state = None , toc = None ) : <EOL> """<STR_LIT>""" <EOL> if prototype is not None and not isinstance ( prototype , simuvex . s_type . SimTypeFunction ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> self . _project = project <EOL> self . _ty = prototype <EOL> self . _addr = addr <EOL> self . _concrete_only = concrete_only <EOL> self . _base_state = base_state <EOL> self . _toc = toc <EOL> self . _caller = None <EOL> self . _deadend_addr = project . _extern_obj . get_pseudo_addr ( '<STR_LIT>' ) <EOL> def set_base_state ( self , state ) : <EOL> """<STR_LIT>""" <EOL> self . _base_state = state <EOL> def call_get_return_val ( self , * args ) : <EOL> return self . get_call_results ( * args ) [ <NUM_LIT:0> ] <EOL> __call__ = call_get_return_val <EOL> def call_get_res_state ( self , * args ) : <EOL> return self . get_call_results ( * args ) [ <NUM_LIT:1> ] <EOL> def get_call_results ( self , * args ) : <EOL> cc = simuvex . DefaultCC [ self . _project . arch . name ] ( self . _project . arch ) <EOL> if self . _ty is not None : <EOL> wantlen = len ( self . _ty . args ) <EOL> if len ( args ) != wantlen : <EOL> raise TypeError ( "<STR_LIT>" . format ( self . _addr , wantlen , '<STR_LIT>' if wantlen == <NUM_LIT:1> else '<STR_LIT:s>' , len ( args ) ) ) <EOL> state = self . _base_state . copy ( ) if self . _base_state is not None else self . _project . factory . blank_state ( ) <EOL> if state . arch . name == '<STR_LIT>' and self . _toc is not None : <EOL> state . regs . r2 = self . _toc <EOL> if self . _ty is not None : <EOL> pointed_args = [ self . _standardize_value ( arg , ty , state ) for arg , ty in zip ( args , self . _ty . args ) ] <EOL> else : <EOL> pointed_args = [ self . _standardize_value ( arg , None , state ) for arg in args ] <EOL> def step_func ( pg ) : <EOL> pg2 = pg . prune ( ) <EOL> if len ( pg2 . active ) > <NUM_LIT:1> : <EOL> raise AngrCallableMultistateError ( "<STR_LIT>" ) <EOL> return pg2 <EOL> caller = PathGroup . call ( self . _project , self . _addr , pointed_args , start = self . _project . factory . path ( state ) ) <EOL> caller_end_unpruned = caller . step ( until = lambda pg : len ( pg . active ) == <NUM_LIT:0> , step_func = step_func if self . _concrete_only else None ) . unstash ( from_stash = '<STR_LIT>' ) <EOL> caller_end_unmerged = caller_end_unpruned . prune ( filter_func = lambda pt : pt . addr == self . _deadend_addr ) <EOL> if len ( caller_end_unmerged . active ) == <NUM_LIT:0> : <EOL> raise AngrCallableError ( "<STR_LIT>" ) <EOL> caller_end = caller_end_unmerged . merge ( ) <EOL> out_state = caller_end . active [ <NUM_LIT:0> ] . state <EOL> out_val = out_state . se . simplify ( cc . get_return_expr ( out_state ) ) <EOL> return out_val , out_state <EOL> def _standardize_value ( self , arg , ty , state ) : <EOL> check = ty is not None <EOL> if isinstance ( arg , Callable . PointerWrapper ) : <EOL> if check and not isinstance ( ty , simuvex . s_type . SimTypePointer ) : <EOL> raise TypeError ( "<STR_LIT>" . format ( ty ) ) <EOL> real_value = self . _standardize_value ( arg . value , ty . pts_to if check else None , state ) <EOL> return self . _push_value ( real_value , state ) <EOL> elif isinstance ( arg , str ) : <EOL> if check and ( not isinstance ( ty , simuvex . s_type . SimTypePointer ) or not isinstance ( ty . pts_to , simuvex . s_type . SimTypeChar ) ) : <EOL> raise TypeError ( "<STR_LIT>" . format ( ty ) ) <EOL> return self . _standardize_value ( map ( ord , arg + '<STR_LIT>' ) , simuvex . s_type . SimTypePointer ( state . arch , simuvex . s_type . SimTypeChar ( ) ) , state ) <EOL> elif isinstance ( arg , list ) : <EOL> if check and not isinstance ( ty , simuvex . s_type . SimTypePointer ) : <EOL> raise TypeError ( "<STR_LIT>" . format ( ty ) ) <EOL> types = map ( type , arg ) <EOL> if types [ <NUM_LIT:1> : ] != types [ : - <NUM_LIT:1> ] : <EOL> raise TypeError ( "<STR_LIT>" ) <EOL> pointed_args = [ self . _standardize_value ( sarg , ty . pts_to if check else None , state ) for sarg in arg ] <EOL> for sarg in reversed ( pointed_args ) : <EOL> out = self . _push_value ( sarg , state ) <EOL> return out <EOL> elif isinstance ( arg , ( int , long ) ) : <EOL> return state . se . BVV ( arg , ty . size if check else state . arch . bits ) <EOL> elif isinstance ( arg , claripy . ast . Base ) : <EOL> return arg <EOL> @ staticmethod <EOL> def _push_value ( val , state ) : <EOL> sp = state . regs . sp - val . size ( ) / <NUM_LIT:8> <EOL> state . regs . sp = sp <EOL> state . memory . store ( sp , val , endness = state . arch . memory_endness ) <EOL> return sp <EOL> class PointerWrapper ( object ) : <EOL> def __init__ ( self , value ) : <EOL> self . value = value <EOL> class Caller ( Explorer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , project , addr , args = ( ) , start = None , num_find = None , concrete_only = False , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> self . _fake_return_addr = project . entry <EOL> self . _cc = simuvex . DefaultCC [ project . arch . name ] ( project . arch ) <EOL> self . _concrete_only = concrete_only <EOL> start_paths = [ ] <EOL> if start is None : <EOL> start_paths . append ( project . factory . path ( project . factory . blank_state ( addr = addr ) ) ) <EOL> elif isinstance ( start , ( tuple , list , set ) ) : <EOL> start_paths . extend ( start ) <EOL> else : <EOL> start_paths . append ( start ) <EOL> self . symbolic_args = [ start_paths [ <NUM_LIT:0> ] . state . se . Unconstrained ( '<STR_LIT>' % i , project . arch . bits ) if arg is None else arg for i , arg in enumerate ( args ) ] <EOL> self . _ret_addr = start_paths [ <NUM_LIT:0> ] . state . se . BVV ( self . _fake_return_addr , project . arch . bits ) <EOL> for p in start_paths : <EOL> p . state . ip = addr <EOL> self . _cc . setup_callsite ( p . state , self . _ret_addr , self . symbolic_args ) <EOL> super ( Caller , self ) . __init__ ( project , find = self . _fake_return_addr , start = start_paths , num_find = num_find , ** kwargs ) <EOL> def post_tick ( self ) : <EOL> if not self . _concrete_only : return <EOL> if len ( self . active ) > <NUM_LIT:1> : <EOL> toomany = self . active <EOL> self . active = [ ] <EOL> for path in toomany : <EOL> if path . state . satisfiable ( ) : <EOL> self . active . append ( path ) <EOL> else : <EOL> self . errored . append ( path ) <EOL> if len ( self . active ) > <NUM_LIT:1> : <EOL> raise AngrCallableMultistateError ( "<STR_LIT>" ) <EOL> def map_se ( self , func , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> runs = kwargs . pop ( '<STR_LIT>' , None ) <EOL> solution = kwargs . pop ( '<STR_LIT>' , None ) <EOL> extra_constraints = kwargs . pop ( '<STR_LIT>' , ( ) ) <EOL> sort = kwargs . pop ( '<STR_LIT>' , True ) <EOL> for r , p in self . iter_returns ( runs = runs , solution = solution ) : <EOL> v = getattr ( p . state . se , func ) ( * args , extra_constraints = extra_constraints + ( r == solution , ) , ** kwargs ) <EOL> yield r , sorted ( v ) if sort else v <EOL> def map_func ( self , func , runs = None , solution = None ) : <EOL> """<STR_LIT>""" <EOL> for r , p in self . iter_returns ( runs = runs , solution = solution ) : <EOL> yield func ( r , self . symbolic_args , p ) <EOL> def iter_returns ( self , runs = None , solution = None ) : <EOL> """<STR_LIT>""" <EOL> for p in self . iter_found ( runs = runs ) : <EOL> r = p . state . se . simplify ( self . _cc . get_return_expr ( p . state ) ) <EOL> if solution is not None and not p . state . se . solution ( r , solution ) : <EOL> continue <EOL> yield ( r , p ) <EOL> __iter__ = iter_returns <EOL> from . . path_group import PathGroup <EOL> from . . errors import AngrCallableError , AngrCallableMultistateError <EOL> from . import all_surveyors <EOL> all_surveyors [ '<STR_LIT>' ] = Caller </s>
