def mk_num (x, typ): import logic if logic.is_int (typ): typ = Type ('Word', typ) assert typ.kind == 'Word', typ assert logic.is_int (x), x return Expr ('Num', typ, val = x)
def mk_word32_maybe(x): import logic if logic.is_int (x): return mk_word32 (x) else: assert x.typ == word32T return x
def assembly_point(p, n): (_, hints) = p.node_tags[n] if type(hints) != tuple or not logic.is_int(hints[1]): return None while p.node_tags[n][1][1] % 4 != 0: [n] = p.preds[n] return p.node_tags[n][1][1]
def graph_name(nodes, node_tags, n, prev=None): if type(n) == str: return 't_%s_%d' % (n, prev) if n not in nodes: return 'unknown_%d' % n if n not in node_tags: ident = '%d' % n else: (tag, details) = node_tags[n] if len(details) > 1 and logic.is_int(details[1]): ident = '%d_%s_%s_0x%x' % (n, tag, details[0], details[1]) elif type(details) != str: details = '_'.join(map(str, details)) ident = '%d_%s_%s' % (n, tag, details) else: ident = '%d_%s_%s' % (n, tag, details) ident = sanitise_str(ident) node = nodes[n] if node.kind == 'Call': return 'fcall_%s' % ident if node.kind == 'Cond': return ident if node.kind == 'Basic': return 'ass_%s' % ident assert not 'node kind understood'
def mk_acc (idx, expr, replaces): if logic.is_int (idx): assert expr.typ.kind == 'Array' return compile_array_acc (idx, expr, replaces) else: assert expr.typ.kind == 'Struct' return compile_field_acc (idx, expr, replaces)
def mk_acc(idx, expr, replaces): if logic.is_int(idx): assert expr.typ.kind == 'Array' return compile_array_acc(idx, expr, replaces) else: assert expr.typ.kind == 'Struct' return compile_field_acc(idx, expr, replaces)
def graph_name(nodes, node_tags, n, prev=None): if type(n) == str: return "t_%s_%d" % (n, prev) if n not in nodes: return "unknown_%d" % n if n not in node_tags: ident = "%d" % n else: (tag, details) = node_tags[n] if len(details) > 1 and logic.is_int(details[1]): ident = "%d_%s_%s_0x%x" % (n, tag, details[0], details[1]) elif type(details) != str: details = "_".join(map(str, details)) ident = "%d_%s_%s" % (n, tag, details) else: ident = "%d_%s_%s" % (n, tag, details) ident = sanitise_str(ident) node = nodes[n] if node.kind == "Call": return "fcall_%s" % ident if node.kind == "Cond": return ident if node.kind == "Basic": return "ass_%s" % ident assert not "node kind understood"
def compile_array_acc (i, expr, replaces, must = True): '''pseudo-compile access to array element i of expr''' if not logic.is_int (i) and i.kind == 'Num': assert i.typ == word32T i = i.val if expr.kind == 'Array': if logic.is_int (i): return expr.vals[i] else: expr2 = expr.vals[-1] for (j, v) in enumerate (expr.vals[:-1]): expr2 = mk_if (mk_eq (i, mk_word32 (j)), v, expr2) return expr2 elif expr.is_op ('ArrayUpdate'): [arr, j, v] = expr.vals if j.kind == 'Num' and logic.is_int (i): if i == j.val: return v else: return compile_array_acc (i, arr, replaces) else: return mk_if (mk_eq (j, mk_word32_maybe (i)), v, compile_array_acc (i, arr, replaces)) elif expr.is_op ('MemAcc'): [m, p] = expr.vals return mk_memacc (m, mk_arroffs (p, expr.typ, i), expr.typ.el_typ) elif expr.is_op ('IfThenElse'): [cond, left, right] = expr.vals return mk_if (cond, compile_array_acc (i, left, replaces), compile_array_acc (i, right, replaces)) elif expr.kind == 'Var': assert expr.name in replaces if logic.is_int (i): (_, v_nm, typ) = replaces[expr.name][i] return mk_var (v_nm, typ) else: vs = [(mk_word32 (j), mk_var (v_nm, typ)) for (j, v_nm, typ) in replaces[expr.name]] expr2 = vs[0][1] for (j, v) in vs[1:]: expr2 = mk_if (mk_eq (i, j), v, expr2) return expr2 else: if not must: return None return mk_arr_index (expr, mk_word32_maybe (i))
def compile_array_acc(i, expr, replaces, must=True): '''pseudo-compile access to array element i of expr''' if not logic.is_int(i) and i.kind == 'Num': assert i.typ == word32T i = i.val if expr.kind == 'Array': if logic.is_int(i): return expr.vals[i] else: expr2 = expr.vals[-1] for (j, v) in enumerate(expr.vals[:-1]): expr2 = mk_if(mk_eq(i, mk_word32(j)), v, expr2) return expr2 elif expr.is_op('ArrayUpdate'): [arr, j, v] = expr.vals if j.kind == 'Num' and logic.is_int(i): if i == j.val: return v else: return compile_array_acc(i, arr, replaces) else: return mk_if(mk_eq(j, mk_word32_maybe(i)), v, compile_array_acc(i, arr, replaces)) elif expr.is_op('MemAcc'): [m, p] = expr.vals return mk_memacc(m, mk_arroffs(p, expr.typ, i), expr.typ.el_typ) elif expr.is_op('IfThenElse'): [cond, left, right] = expr.vals return mk_if(cond, compile_array_acc(i, left, replaces), compile_array_acc(i, right, replaces)) elif expr.kind == 'Var': assert expr.name in replaces if logic.is_int(i): (_, v_nm, typ) = replaces[expr.name][i] return mk_var(v_nm, typ) else: vs = [(mk_word32(j), mk_var(v_nm, typ)) for (j, v_nm, typ) in replaces[expr.name]] expr2 = vs[0][1] for (j, v) in vs[1:]: expr2 = mk_if(mk_eq(i, j), v, expr2) return expr2 else: if not must: return None return mk_arr_index(expr, mk_word32_maybe(i))
def serialise_bound(addr, bound_info): if bound_info == None: return [hex(addr), "None", "None"] else: (bound, kind) = bound_info assert logic.is_int(bound) assert str(kind) == kind return [hex(addr), str(bound), kind]
def mk_arroffs(p, typ, i): assert typ.kind == 'Array' import logic if logic.is_int (i): assert i < typ.num offs = i * typ.el_typ.size() assert offs == i or offs % 4 == 0 return mk_plus (p, mk_word32 (offs)) else: sz = typ.el_typ.size() return mk_plus (p, mk_times (i, mk_word32 (sz)))
def build_compound_problem (fnames): """mirrors build_problem from check for multiple functions""" printout ('Building compound problem for %s' % fnames) last_compound_problem_req[0] = list (fnames) p = problem.Problem (None, name = ', '.join(fnames)) fun_tag_pairs = [] all_tags = {} for (i, fn) in enumerate (fnames): i = len (fnames) - i [pair] = pairings[fn] next_tags = {} scripts = get_problem_inline_scripts (pair) for (pair_tag, fname) in pair.funs.items (): tag = '%s_%d_%s' % (fname, i, pair_tag) tag = syntax.fresh_name (tag, all_tags) next_tags[pair_tag] = tag p.add_entry_function (functions[fname], tag) p.hook_tag_hints[tag] = pair_tag p.replay_inline_script (tag, scripts[pair_tag]) fun_tag_pairs.append ((next_tags, pair)) p.pad_merge_points () p.do_analysis () free_hyps = [] for (tags, pair) in fun_tag_pairs: (inp_eqs, _) = pair.eqs free_hyps += check.inst_eqs (p, (), inp_eqs, tags) err_vis_opts = rep_graph.vc_options ([0, 1, 2], [1]) err_vis_vc = tuple ([(n, err_vis_opts) for n in p.loop_heads () if p.node_tags[n][0] == tags['C']]) err_vis = (('Err', err_vis_vc), tags['C']) free_hyps.append (rep_graph.pc_false_hyp (err_vis)) addr_map = {} for n in p.nodes: if not p.node_tags[n][0].endswith ('_ASM'): continue if type (p.node_tags[n][1]) == tuple: (fname, data) = p.node_tags[n][1] if (logic.is_int (data) and is_addr (data) and not fname.startswith ("instruction'")): assert data not in addr_map, data addr_map[data] = n return (p, free_hyps, addr_map, fun_tag_pairs)
def build_compound_problem(fnames): """mirrors build_problem from check for multiple functions""" printout('Building compound problem for %s' % fnames) last_compound_problem_req[0] = list(fnames) p = problem.Problem(None, name=', '.join(fnames)) fun_tag_pairs = [] all_tags = {} for (i, fn) in enumerate(fnames): i = len(fnames) - i [pair] = pairings[fn] next_tags = {} scripts = get_problem_inline_scripts(pair) for (pair_tag, fname) in pair.funs.items(): tag = '%s_%d_%s' % (fname, i, pair_tag) tag = syntax.fresh_name(tag, all_tags) next_tags[pair_tag] = tag p.add_entry_function(functions[fname], tag) p.hook_tag_hints[tag] = pair_tag p.replay_inline_script(tag, scripts[pair_tag]) fun_tag_pairs.append((next_tags, pair)) p.pad_merge_points() p.do_analysis() free_hyps = [] for (tags, pair) in fun_tag_pairs: (inp_eqs, _) = pair.eqs free_hyps += check.inst_eqs(p, (), inp_eqs, tags) err_vis_opts = rep_graph.vc_options([0, 1, 2], [1]) err_vis_vc = tuple([(n, err_vis_opts) for n in p.loop_heads() if p.node_tags[n][0] == tags['C']]) err_vis = (('Err', err_vis_vc), tags['C']) free_hyps.append(rep_graph.pc_false_hyp(err_vis)) addr_map = {} for n in p.nodes: if not p.node_tags[n][0].endswith('_ASM'): continue if type(p.node_tags[n][1]) == tuple: (fname, data) = p.node_tags[n][1] if (logic.is_int(data) and is_addr(data) and not fname.startswith("instruction'")): assert data not in addr_map, data addr_map[data] = n return (p, free_hyps, addr_map, fun_tag_pairs)
def get_extra_sp_defs (rep, tag): """all functions will keep the stack pointer equal, whether they have pairing partners or not. add these extra defs/equalities for the purposes of stack depth analysis.""" # FIXME how to parametrise this? sp = mk_var ('r13', syntax.word32T) defs = {} items = [(n_vc, x) for (n_vc, x) in rep.funcs.iteritems () if logic.is_int (n_vc[0])] for ((n, vc), (inputs, outputs, _)) in items: if rep.p.node_tags[n][0] == tag: inp_sp = solver.smt_expr (sp, inputs, rep.solv) inp_sp = solver.parse_s_expression (inp_sp) out_sp = solver.smt_expr (sp, outputs, rep.solv) out_sp = solver.parse_s_expression (out_sp) if inp_sp != out_sp: defs[out_sp] = inp_sp return defs
def graph_name (nodes, node_tags, n, prev=None): if type (n) == str: return 't_%s_%d' % (n, prev) if n not in nodes: return 'unknown_%d' % n if n not in node_tags: ident = '%d' % n else: (tag, details) = node_tags[n] if len (details) > 1 and logic.is_int (details[1]): ident = '%d_%s_%s_0x%x' % (n, tag, details[0], details[1]) else: ident = '%d_%s_%s' % (n, tag, details) node = nodes[n] if node.kind == 'Call': return 'fcall_%s' % ident if node.kind == 'Cond': return ident if node.kind == 'Basic': return 'ass_%s' % ident assert not 'node kind understood'
def get_extra_sp_defs(rep, tag): """add extra defs/equalities about stack pointer for the purposes of stack depth analysis.""" # FIXME how to parametrise this? sp = mk_var('r13', syntax.word32T) defs = {} fcalls = [ n_vc for n_vc in rep.funcs if logic.is_int(n_vc[0]) if rep.p.node_tags[n_vc[0]][0] == tag if preserves_sp(rep.p.nodes[n_vc[0]].fname) ] for (n, vc) in fcalls: (inputs, outputs, _) = rep.funcs[(n, vc)] if (sp.name, sp.typ) not in outputs: continue inp_sp = solver.smt_expr(sp, inputs, rep.solv) inp_sp = solver.parse_s_expression(inp_sp) out_sp = solver.smt_expr(sp, outputs, rep.solv) out_sp = solver.parse_s_expression(out_sp) if inp_sp != out_sp: defs[out_sp] = inp_sp return defs