def get_targets(self,node,parent): pc = self.prog.cpu.PC() n = node mpc = pc while True: m = n.data.map.use((pc,n.data.address)) mpc = m(mpc) T = _target(mpc,node).expand() if len(T)>0: return T try: n = n.N(-1)[0] # get first parent node (parent arg is unused) except IndexError: break # we are at function entry node # create func nodes: xpc = [] if n.data.misc[code.tag.FUNC_START]: if node.data.misc[code.tag.FUNC_END]: n.data.misc[code.tag.FUNC_START] += 1 try: fsym = n.data.misc['callers'][0].data.misc['to'].ref except (IndexError,TypeError,AttributeError): fsym = 'f' func = code.func(n.c,name="%s:%s"%(fsym,n.name)) logger.verbose("function %s created"%func) if mpc._is_mem and len(mpc.mods)>0: pol = '(assume_no_aliasing)' if self.policy['frame-aliasing']==False else '' logger.verbose("pc is memory aliased in %s %s"%(str(func),pol)) if self.policy['frame-aliasing']==False: mpc.mods = [] func.map[pc] = mpc for cn in n.data.misc['callers']: cnpc = cn.data.map.use((pc,cn.data.address))(mpc) f = cfg.node(func) e = cn.c.add_edge(cfg.link(cn,f)) xpc.extend(_target(cnpc,e.v[1]).expand()) n.data.misc['func'] = func else: xpc.extend(_target(mpc,node).expand()) return xpc
def getcfg(self,loc=None): from collections import OrderedDict,defaultdict D = OrderedDict() C = defaultdict(lambda: []) for b in self.iterblocks(loc): n = cfg.node(b) D[n.data.address] = n # now we have collected an overapprox. of all blocks, # lets link those "super-blocks" together: while len(D)>0: k,n = D.popitem(last=False) # add node (does nothing if n is already in G) n = self.G.add_vertex(n) b = n.data # find its links: if b.misc['func_call']: aret = b.misc['retto']+0 nret = D.get(aret,None) or self.G.get_with_address(aret) if nret is not None: e = cfg.link(n,nret) self.G.add_edge(e) ato = b.misc['to'] if ato is not 0: C[ato+0].append((e,'func_call')) elif b.misc['func_goto'] and b.misc['to'] is not 0: ato = b.misc['to']+0 nto = D.get(ato,None) or self.G.get_with_address(ato) if nto is not None: e = cfg.link(n,nto) self.G.add_edge(e) else: C[ato].append((n,'to')) if b.misc['cond']: ato = n.data.support[1] nto = D.get(ato,None) or self.G.get_with_address(ato) if nto is not None: e = cfg.link(n,nto,data=b.misc['cond'][1]) self.G.add_edge(e) else: C[ato].append((n,b.misc['cond'])) # now all super-blocks have been processed, but some may need # to be cut, lets handle those missed targets: while len(C)>0: ato,L = C.popitem() n = cfg.node(next(self.iterblocks(ato))) n = self.G.add_vertex(n) for (p,why) in L: if why is 'func_call': if n.data.misc['callers']: n.data.misc['callers'].append(p) else: n.data.misc['callers']=[p] else: e = cfg.link(p,n) self.G.add_edge(e) # finally create func objects and insert nodes: for n in self.G.V(): if n.data.misc['callers']: n.data.misc['func'] = f = code.func(n.c) calls = [] for e in n.data.misc['callers']: fn = cfg.node(f) p = e.v[0] p.c.add_edge(cfg.link(p,fn)) p.c.add_edge(cfg.link(fn,e.v[1])) p.c.remove_edge(e) calls.append(p) n.data.misc['callers'] = calls return self.G
def get_targets(self,node,parent): pc = self.prog.cpu.PC() alf = code.mapper.assume_no_aliasing code.mapper.assume_no_aliasing = not self.policy['frame-aliasing'] # try fforward first: T = fforward.get_targets(self,node,parent) if len(T)>0: code.mapper.assume_no_aliasing = alf return T # create func object: f = code.func(node.c) m = f.backward(node) if m is None: logger.verbose('dead end at %s'%node.name) else: m = m.use((pc,f.address)) # get pc @ node: mpc = m(pc) T = _target(mpc,node).expand() # if a target is defined here, it means that func cfg is not completed # so we can return now : if len(T)>0: code.mapper.assume_no_aliasing = alf return T # otherwise if func cfg is complete compute pc out of function callers: xpc = [] # check if a leaf is still going to be explored for x in f.cfg.leaves(): if x in (s.parent for s in self.spool): code.mapper.assume_no_aliasing = alf return xpc # f is now fully explored so we can "return" to callers: logger.info('lbackward: function %s done'%f) # cleanup spool: for t in self.spool: if t.parent.c is f.cfg: t.dirty=True # if needed compute the full map: if f.misc['partial']: m = f.makemap() f.map = m self.prog.codehelper(func=f) mpc = f.map(pc) roots = filter(lambda n: n.data.misc[code.tag.FUNC_START],f.cfg.sV) if len(roots)<=0: code.mapper.assume_no_aliasing = alf return xpc if len(roots)>1: logger.verbose('lbackward: multiple entries into function %s ?!'%f) nroot = roots[0] nroot.data.misc['func'] = f try: fsym = nroot.data.misc['callers'][0].data.misc['to'].ref except (IndexError,TypeError,AttributeError): fsym = 'f' f.name = "%s:%s"%(fsym,nroot.name) for cn in nroot.data.misc['callers']: cnpc = cn.data.map.use((pc,cn.data.address))(mpc) fn = cfg.node(f) e = cn.c.add_edge(cfg.link(cn,fn)) xpc.extend(_target(cnpc,e.v[1]).expand()) code.mapper.assume_no_aliasing = alf return xpc