def guess_pv(p, n, addr_expr): vs = syntax.get_expr_var_set(addr_expr) [pred] = p.preds[n] pvs = [] def vis(expr): if expr.is_op(["PValid", "PArrayValid"]): pvs.append(expr) p.nodes[pred].cond.visit(vis) match_pvs = [pv for pv in pvs if set.union(*[syntax.get_expr_var_set(v) for v in pv.vals[2:]]) == vs] if len(match_pvs) > 1: match_pvs = [pv for pv in match_pvs if pv.is_op("PArrayValid")] pv = match_pvs[0] return pv
def node_const_rets(node): if "instruction'" in node.fname: return inst_const_rets(node) if node.fname in pre_pairings: if pre_pairings[node.fname]['ASM'] != node.fname: return None cc = get_asm_calling_convention_at_node(node) input_set = set( [v for arg in node.args for v in syntax.get_expr_var_set(arg)]) callee_saved_set = set(cc['callee_saved']) return [ mk_var(nm, typ) for (nm, typ) in node.rets if mk_var(nm, typ) in callee_saved_set if (nm, typ) in input_set ] elif preserves_sp(node.fname): if node.fname not in get_functions_with_tag('ASM'): return None f_outs = functions[node.fname].outputs return [ mk_var(nm, typ) for ((nm, typ), (nm2, _)) in azip(node.rets, f_outs) if nm2 == 'r13' ] else: return None
def compute_var_flows (nodes, outputs, preds, override_lvals_rvals = {}): # compute a graph of reverse var flows to pass to tarjan's algorithm graph = {} entries = ['Ret'] for (n, node) in nodes.iteritems (): if node.kind == 'Basic': for (lv, rv) in node.upds: graph[(n, 'Post', lv)] = [(n, 'Pre', v) for v in syntax.get_expr_var_set (rv)] elif node.is_noop (): pass else: if n in override_lvals_rvals: (lvals, rvals) = override_lvals_rvals[n] else: rvals = syntax.get_node_rvals (node) rvals = set (rvals.iteritems ()) lvals = set (node.get_lvals ()) if node.kind != 'Basic': lvals = list (lvals) + ['PC'] entries.append ((n, 'Post', 'PC')) for lv in lvals: graph[(n, 'Post', lv)] = [(n, 'Pre', rv) for rv in rvals] graph['Ret'] = [(n, 'Post', v) for n in preds['Ret'] for v in outputs (n)] vs = set ([v for k in graph for (_, _, v) in graph[k]]) for v in vs: for n in nodes: graph.setdefault ((n, 'Post', v), [(n, 'Pre', v)]) graph[(n, 'Pre', v)] = [(n2, 'Post', v) for n2 in preds[n]] comps = tarjan (graph, entries) return (graph, comps)
def guess_pv(p, n, addr_expr): vs = syntax.get_expr_var_set(addr_expr) [pred] = p.preds[n] pvs = [] def vis(expr): if expr.is_op(['PValid', 'PArrayValid']): pvs.append(expr) p.nodes[pred].cond.visit(vis) match_pvs = [ pv for pv in pvs if set.union(*[syntax.get_expr_var_set(v) for v in pv.vals[2:]]) == vs ] if len(match_pvs) > 1: match_pvs = [pv for pv in match_pvs if pv.is_op('PArrayValid')] pv = match_pvs[0] return pv
def adjusted_var_dep_outputs_for_tag(p, tag): (ent, fname, _) = p.get_entry_details(tag) fun = functions[fname] cc = get_asm_calling_convention(fname) callee_saved_set = set(cc['callee_saved']) ret_set = set([(nm, typ) for ret in cc['rets'] for (nm, typ) in syntax.get_expr_var_set(ret)]) rets = [(nm2, typ) for ((nm, typ), (nm2, _)) in azip(fun.outputs, p.outputs[tag]) if (nm, typ) in ret_set or mk_var(nm, typ) in callee_saved_set] return rets
def adjusted_var_dep_outputs_for_tag (p, tag): (ent, fname, _) = p.get_entry_details (tag) fun = functions[fname] cc = get_asm_calling_convention (fname) callee_saved_set = set (cc['callee_saved']) ret_set = set ([(nm, typ) for ret in cc['rets'] for (nm, typ) in syntax.get_expr_var_set (ret)]) rets = [(nm2, typ) for ((nm, typ), (nm2, _)) in azip (fun.outputs, p.outputs[tag]) if (nm, typ) in ret_set or mk_var (nm, typ) in callee_saved_set] return rets
def pseudo_node_lvals_rvals(node): assert node.kind == 'Call' cc = get_asm_calling_convention_at_node(node) if not cc: return None arg_vars = set( [var for arg in cc['args'] for var in syntax.get_expr_var_set(arg)]) callee_saved_set = set(cc['callee_saved']) rets = [(nm, typ) for (nm, typ) in node.rets if mk_var(nm, typ) not in callee_saved_set] return (rets, arg_vars)
def pseudo_node_lvals_rvals (node): assert node.kind == 'Call' cc = get_asm_calling_convention_at_node (node) if not cc: return None arg_vars = set ([var for arg in cc['args'] for var in syntax.get_expr_var_set (arg)]) callee_saved_set = set (cc['callee_saved']) rets = [(nm, typ) for (nm, typ) in node.rets if mk_var (nm, typ) not in callee_saved_set] return (rets, arg_vars)
def node_const_rets (node): if "instruction'" in node.fname: return inst_const_rets (node) if node.fname not in pre_pairings: return None if pre_pairings[node.fname]['ASM'] != node.fname: return None cc = get_asm_calling_convention_at_node (node) input_set = set ([v for arg in node.args for v in syntax.get_expr_var_set (arg)]) callee_saved_set = set (cc['callee_saved']) return [mk_var (nm, typ) for (nm, typ) in node.rets if mk_var (nm, typ) in callee_saved_set if (nm, typ) in input_set]
def inst_const_rets (node): assert "instruction'" in node.fname bits = set ([s.lower () for s in node.fname.split ('_')]) fun = functions[node.fname] def is_const (nm, typ): if typ in [builtinTs['Mem'], builtinTs['Dom']]: return True if typ != word32T: return False return not (nm in bits or [al for al in reg_aliases.get (nm, []) if al in bits]) is_consts = [is_const (nm, typ) for (nm, typ) in fun.outputs] input_set = set ([v for arg in node.args for v in syntax.get_expr_var_set (arg)]) return [mk_var (nm, typ) for ((nm, typ), const) in azip (node.rets, is_consts) if const and (nm, typ) in input_set]
def inst_const_rets(node): assert "instruction'" in node.fname bits = set([s.lower() for s in node.fname.split('_')]) fun = functions[node.fname] def is_const(nm, typ): if typ in [builtinTs['Mem'], builtinTs['Dom']]: return True if typ != word32T: return False return not (nm in bits or [al for al in reg_aliases.get(nm, []) if al in bits]) is_consts = [is_const(nm, typ) for (nm, typ) in fun.outputs] input_set = set( [v for arg in node.args for v in syntax.get_expr_var_set(arg)]) return [ mk_var(nm, typ) for ((nm, typ), const) in azip(node.rets, is_consts) if const and (nm, typ) in input_set ]
def trace_var(rep, tag, m, v): p = rep.p ns = walk_model(rep, tag, m) vds = rep.p.compute_var_dependencies() trace = [] vs = syntax.get_expr_var_set(v) def fetch((n, vc)): if n in vds and [(nm, typ) for (nm, typ) in vs if (nm, typ) not in vds[n]]: return None try: (_, env) = rep.get_node_pc_env((n, vc), tag) s = solver.smt_expr(v, env, rep.solv) s_x = solver.parse_s_expression(s) ev = search.eval_model(m, s_x) return (s, solver.smt_expr(ev, {}, None)) except solver.EnvMiss, e: return None except AssertionError, e: return None
def contextual_conds (nodes, preds): """computes a collection of conditions that can be assumed true at any point in the node graph.""" pre_conds = {} arc_conds = {} visit = [n for n in nodes if not (preds[n])] while visit: n = visit.pop () if n not in nodes: continue in_arc_conds = [arc_conds.get ((pre, n), set ()) for pre in preds[n]] if not in_arc_conds: conds = set () else: conds = set.intersection (* in_arc_conds) if pre_conds.get (n) == conds: continue pre_conds[n] = conds if n not in nodes: continue if nodes[n].kind == 'Cond' and nodes[n].left == nodes[n].right: c_conds = [conds, conds] elif nodes[n].kind == 'Cond': c_conds = [nodes[n].cond, mk_not_red (nodes[n].cond)] c_conds = [set.union (set ([c]), conds) for c in c_conds] else: upds = set (nodes[n].get_lvals ()) c_conds = [set ([c for c in conds if not set.intersection (upds, syntax.get_expr_var_set (c))])] for (cont, conds) in zip (nodes[n].get_conts (), c_conds): arc_conds[(n, cont)] = conds visit.append (cont) return (arc_conds, pre_conds)