def get_stack_sp(p, tag): """get stack and stack-pointer variables""" entry = p.get_entry(tag) renames = p.entry_exit_renames(tags=[tag]) r = renames[tag + '_IN'] sp = syntax.rename_expr(mk_var('r13', syntax.word32T), r) stack = syntax.rename_expr(mk_var('stack', syntax.builtinTs['Mem']), r) return (stack, sp)
def get_stack_sp (p, tag): """get stack and stack-pointer variables""" entry = p.get_entry (tag) renames = p.entry_exit_renames (tags = [tag]) r = renames[tag + '_IN'] sp = syntax.rename_expr (mk_var ('r13', syntax.word32T), r) stack = syntax.rename_expr (mk_var ('stack', syntax.builtinTs['Mem']), r) return (stack, sp)
def get_loop_virtual_stack_analysis (p, tag): """computes variable liveness etc analyses with stack slots treated as virtual variables.""" cache_key = ('loop_stack_analysis', tag) if cache_key in p.cached_analysis: return p.cached_analysis[cache_key] (ent, fname, _) = p.get_entry_details (tag) (_, sp) = get_stack_sp (p, tag) cc = get_asm_calling_convention (fname) rets = list (set ([ptr for arg in cc['rets'] for (ptr, _) in stack_virtualise_expr (arg, None)[0]])) rets = [adjust_ret_ptr (ret) for ret in rets] renames = p.entry_exit_renames (tags = [tag]) r = renames[tag + '_OUT'] rets = [syntax.rename_expr (ret, r) for ret in rets] ns = [n for n in p.nodes if p.node_tags[n][0] == tag] ptrs = list (set ([(n, ptr) for n in ns for ptr in (stack_virtualise_node (p.nodes[n], None))[0]])) ptrs += [(n, (sp, 'StackPointer')) for n in ns if p.loop_id (n)] offs = get_ptr_offsets (p, [(n, ptr) for (n, (ptr, _)) in ptrs], [(ent, sp, 'stack')] + [(ent, ptr, 'indirect_ret') for ptr in rets[:1]]) ptr_offs = {} rep_offs = {} upd_offsets = {} for ((n, ptr), off, k) in offs: ptr_offs.setdefault (n, {}) rep_offs.setdefault (n, {}) ptr_offs[n][ptr] = (k, off) rep_offs[n][k] = (ptr, - off) for (n, (ptr, kind)) in ptrs: if kind == 'MemUpdate' and p.loop_id (n): loop = p.loop_id (n) (k, off) = ptr_offs[n][ptr] upd_offsets.setdefault (loop, set ()) upd_offsets[loop].add ((k, off)) loc_offs = mk_get_local_offs (p, tag, rep_offs) adj_nodes = {} for n in ns: (_, node) = stack_virtualise_node (p.nodes[n], ptr_offs.get (n, {})) adj_nodes[n] = node # finally do analysis on this collection of nodes preds = dict (p.preds) preds['Ret'] = [n for n in preds['Ret'] if p.node_tags[n][0] == tag] preds['Err'] = [n for n in preds['Err'] if p.node_tags[n][0] == tag] vds = logic.compute_var_deps (adj_nodes, adjusted_var_dep_outputs (p), preds) result = (vds, adj_nodes, loc_offs, upd_offsets) p.cached_analysis[cache_key] = result return result
def get_loop_virtual_stack_analysis(p, tag): """computes variable liveness etc analyses with stack slots treated as virtual variables.""" cache_key = ('loop_stack_analysis', tag) if cache_key in p.cached_analysis: return p.cached_analysis[cache_key] (ent, fname, _) = p.get_entry_details(tag) (_, sp) = get_stack_sp(p, tag) cc = get_asm_calling_convention(fname) rets = list( set([ ptr for arg in cc['rets'] for (ptr, _) in stack_virtualise_expr(arg, None)[0] ])) rets = [adjust_ret_ptr(ret) for ret in rets] renames = p.entry_exit_renames(tags=[tag]) r = renames[tag + '_OUT'] rets = [syntax.rename_expr(ret, r) for ret in rets] ns = [n for n in p.nodes if p.node_tags[n][0] == tag] loop_ns = logic.minimal_loop_node_set(p) ptrs = list( set([(n, ptr) for n in ns for ptr in (stack_virtualise_node(p.nodes[n], None))[0]])) ptrs += [(n, (sp, 'StackPointer')) for n in ns if n in loop_ns] offs = get_ptr_offsets(p, [(n, ptr) for (n, (ptr, _)) in ptrs], [(ent, sp, 'stack')] + [(ent, ptr, 'indirect_ret') for ptr in rets[:1]]) ptr_offs = {} rep_offs = {} upd_offsets = {} for ((n, ptr), off, k) in offs: off = norm_int(off, 32) ptr_offs.setdefault(n, {}) rep_offs.setdefault(n, {}) ptr_offs[n][ptr] = (k, off) rep_offs[n][k] = (ptr, -off) for (n, (ptr, kind)) in ptrs: if kind == 'MemUpdate' and n in loop_ns: loop = p.loop_id(n) (k, off) = ptr_offs[n][ptr] upd_offsets.setdefault(loop, set()) upd_offsets[loop].add((k, off)) loc_offs = mk_get_local_offs(p, tag, rep_offs) adj_nodes = {} for n in ns: try: (_, node) = stack_virtualise_node(p.nodes[n], ptr_offs.get(n, {})) except StackOffsMissing, e: printout("Stack analysis issue at (%d, %s)." % (n, p.node_tags[n])) node = p.nodes[n] adj_nodes[n] = node
def ident_callables (fname, callees, idents): from solver import to_smt_expr, smt_expr from syntax import mk_not, mk_and, true_term auto_callables = dict ([((ident, f, true_term), True) for ident in idents.get (fname, [true_term]) for f in callees if f not in idents]) if not [f for f in callees if f in idents]: return auto_callables fun = functions[fname] p = fun.as_problem (problem.Problem, name = 'Target') check_ns = [(n, ident, cond) for n in p.nodes if p.nodes[n].kind == 'Call' if p.nodes[n].fname in idents for (ident, cond) in ident_conds (p.nodes[n].fname, idents)] p.do_analysis () assert check_ns rep = rep_graph.mk_graph_slice (p, fast = True) err_hyp = rep_graph.pc_false_hyp ((default_n_vc (p, 'Err'), 'Target')) callables = auto_callables nhyps = mk_not_callable_hyps (p) for (ident, cond) in ident_conds (fname, idents): renames = p.entry_exit_renames (tags = ['Target']) cond = syntax.rename_expr (cond, renames['Target_IN']) entry = p.get_entry ('Target') e_vis = ((entry, ()), 'Target') hyps = [err_hyp, rep_graph.eq_hyp ((cond, e_vis), (true_term, e_vis))] for (n, ident2, cond2) in check_ns: k = (ident, p.nodes[n].fname, ident2) (inp_env, _, _) = rep.get_func (default_n_vc (p, n)) pc = rep.get_pc (default_n_vc (p, n)) cond2 = to_smt_expr (cond2, inp_env, rep.solv) if rep.test_hyp_whyps (mk_not (mk_and (pc, cond2)), hyps + nhyps): callables[k] = False else: callables[k] = True return callables
def inst_eqs(p, restrs, eqs, tag_map={}): addr_map = {} if not tag_map: tag_map = dict([(tag, tag) for tag in p.tags()]) for (pair_tag, p_tag) in tag_map.iteritems(): addr_map[pair_tag + '_IN'] = ((p.get_entry(p_tag), ()), p_tag) addr_map[pair_tag + '_OUT'] = (('Ret', restrs), p_tag) renames = p.entry_exit_renames(tag_map.values()) for (pair_tag, p_tag) in tag_map.iteritems(): renames[pair_tag + '_IN'] = renames[p_tag + '_IN'] renames[pair_tag + '_OUT'] = renames[p_tag + '_OUT'] hyps = [] for (lhs, rhs) in eqs: vals = [(rename_expr(x, renames[x_addr]), addr_map[x_addr]) for (x, x_addr) in (lhs, rhs)] hyps.append(eq_hyp(vals[0], vals[1])) return hyps
def inst_eqs (p, restrs, eqs, tag_map = {}): addr_map = {} if not tag_map: tag_map = dict ([(tag, tag) for tag in p.tags ()]) for (pair_tag, p_tag) in tag_map.iteritems (): addr_map[pair_tag + '_IN'] = ((p.get_entry (p_tag), ()), p_tag) addr_map[pair_tag + '_OUT'] = (('Ret', restrs), p_tag) renames = p.entry_exit_renames (tag_map.values ()) for (pair_tag, p_tag) in tag_map.iteritems (): renames[pair_tag + '_IN'] = renames[p_tag + '_IN'] renames[pair_tag + '_OUT'] = renames[p_tag + '_OUT'] hyps = [] for (lhs, rhs) in eqs: vals = [(rename_expr (x, renames[x_addr]), addr_map[x_addr]) for (x, x_addr) in (lhs, rhs)] hyps.append (eq_hyp (vals[0], vals[1])) return hyps
def ident_callables(fname, callees, idents): from solver import to_smt_expr, smt_expr from syntax import mk_not, mk_and, true_term auto_callables = dict([((ident, f, true_term), True) for ident in idents.get(fname, [true_term]) for f in callees if f not in idents]) if not [f for f in callees if f in idents]: return auto_callables fun = functions[fname] p = fun.as_problem(problem.Problem, name='Target') check_ns = [(n, ident, cond) for n in p.nodes if p.nodes[n].kind == 'Call' if p.nodes[n].fname in idents for (ident, cond) in ident_conds(p.nodes[n].fname, idents)] p.do_analysis() assert check_ns rep = rep_graph.mk_graph_slice(p, fast=True) err_hyp = rep_graph.pc_false_hyp((default_n_vc(p, 'Err'), 'Target')) callables = auto_callables nhyps = mk_not_callable_hyps(p) for (ident, cond) in ident_conds(fname, idents): renames = p.entry_exit_renames(tags=['Target']) cond = syntax.rename_expr(cond, renames['Target_IN']) entry = p.get_entry('Target') e_vis = ((entry, ()), 'Target') hyps = [err_hyp, rep_graph.eq_hyp((cond, e_vis), (true_term, e_vis))] for (n, ident2, cond2) in check_ns: k = (ident, p.nodes[n].fname, ident2) (inp_env, _, _) = rep.get_func(default_n_vc(p, n)) pc = rep.get_pc(default_n_vc(p, n)) cond2 = to_smt_expr(cond2, inp_env, rep.solv) if rep.test_hyp_whyps(mk_not(mk_and(pc, cond2)), hyps + nhyps): callables[k] = False else: callables[k] = True return callables