|
| 1 | +open Bap.Std |
| 2 | +open Core_kernel |
| 3 | +include Self() |
| 4 | + |
| 5 | + |
| 6 | +let get_direct_typ (e : exp) : Type.t = match e with |
| 7 | + | Bil.Var v -> Var.typ v |
| 8 | + | Bil.Unknown (_,t) -> t |
| 9 | + | Bil.Int w -> Type.Imm (Word.bitwidth w) |
| 10 | + | _ -> failwith "the expression is not flattened" |
| 11 | + |
| 12 | +let flatten_exp (exp : exp) (blk : blk term) (before : tid) : exp * blk term = |
| 13 | + let is_virtual = true in |
| 14 | + let fresh = true in |
| 15 | + let rec aux (exp : exp) (blk : blk term) = match exp with |
| 16 | + | Bil.Load (x, y, endian, s) -> |
| 17 | + let x, blk = aux x blk in |
| 18 | + let y, blk = aux y blk in |
| 19 | + let vtype = Type.Imm (Size.in_bits s) in |
| 20 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 21 | + let e = Bil.Load (x, y, endian, s) in |
| 22 | + let def = Def.create var e in |
| 23 | + Bil.Var var, |
| 24 | + Term.prepend def_t ~before blk def |
| 25 | + | Bil.Store (x, y, z, endian, s) -> |
| 26 | + let x, blk = aux x blk in |
| 27 | + let y, blk = aux y blk in |
| 28 | + let z, blk = aux z blk in |
| 29 | + let vtype = Type.Imm (Size.in_bits s) in |
| 30 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 31 | + let e = Bil.Store (x, y, z, endian, s) in |
| 32 | + let def = Def.create var e in |
| 33 | + Bil.Var var, |
| 34 | + Term.prepend def_t ~before blk def |
| 35 | + | Bil.BinOp (b, x, y) -> |
| 36 | + let x, blk = aux x blk in |
| 37 | + let y, blk = aux y blk in |
| 38 | + let vtype = get_direct_typ x in |
| 39 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 40 | + let e = Bil.BinOp(b, x, y) in |
| 41 | + let def = Def.create var e in |
| 42 | + Bil.Var var, |
| 43 | + Term.prepend def_t ~before blk def |
| 44 | + | Bil.UnOp (u, x) -> |
| 45 | + let x, blk = aux x blk in |
| 46 | + let vtype = get_direct_typ x in |
| 47 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 48 | + let e = Bil.UnOp(u, x) in |
| 49 | + let def = Def.create var e in |
| 50 | + Bil.Var var, |
| 51 | + Term.prepend def_t ~before blk def |
| 52 | + | Bil.Var _ |
| 53 | + | Bil.Int _ -> exp, blk |
| 54 | + | Bil.Cast (c, n, x) -> |
| 55 | + let x, blk = aux x blk in |
| 56 | + let vtype = Type.Imm n in |
| 57 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 58 | + let e = Bil.Cast (c, n, x) in |
| 59 | + let def = Def.create var e in |
| 60 | + Bil.Var var, |
| 61 | + Term.prepend def_t ~before blk def |
| 62 | + | Bil.Let (v, x, y) -> |
| 63 | + let x, blk = aux x blk in |
| 64 | + let y, blk = aux y blk in |
| 65 | + let vtype = Var.typ v in |
| 66 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 67 | + let e = Bil.Let (v, x, y) in |
| 68 | + let def = Def.create var e in |
| 69 | + Bil.Var var, |
| 70 | + Term.prepend def_t ~before blk def |
| 71 | + | Bil.Unknown (_, _) -> exp, blk |
| 72 | + | Bil.Ite (x, y, z) -> |
| 73 | + let x, blk = aux x blk in |
| 74 | + let y, blk = aux y blk in |
| 75 | + let z, blk = aux z blk in |
| 76 | + let vtype = get_direct_typ y in |
| 77 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 78 | + let e = Bil.Ite (x, y, z) in |
| 79 | + let def = Def.create var e in |
| 80 | + Bil.Var var, |
| 81 | + Term.prepend def_t ~before blk def |
| 82 | + | Bil.Extract (n, p, x) -> |
| 83 | + let x, blk = aux x blk in |
| 84 | + let vtype = get_direct_typ x in |
| 85 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 86 | + let e = Bil.Extract (n, p, x) in |
| 87 | + let def = Def.create var e in |
| 88 | + Bil.Var var, |
| 89 | + Term.prepend def_t ~before blk def |
| 90 | + | Bil.Concat (x, y) -> |
| 91 | + let x, blk = aux x blk in |
| 92 | + let y, blk = aux y blk in |
| 93 | + let vtype = get_direct_typ x in |
| 94 | + let var = Var.create ~is_virtual ~fresh "flt" vtype in |
| 95 | + let e = Bil.Concat (x, y) in |
| 96 | + let def = Def.create var e in |
| 97 | + Bil.Var var, |
| 98 | + Term.prepend def_t ~before blk def in |
| 99 | + aux exp blk |
| 100 | + |
| 101 | +let flatten_blk original_blk = |
| 102 | + let rec flatten_elts (elts : Blk.elt seq) (blk : blk term) = |
| 103 | + let rec flatten_jmp (jmp : Jmp.t) (expseq : exp seq) (blk : blk term) = |
| 104 | + match Seq.next expseq with |
| 105 | + | Some(hd, tl) -> |
| 106 | + let exp, blk = flatten_exp hd blk (Term.tid jmp) in |
| 107 | + Jmp.substitute jmp hd exp |> Term.update jmp_t blk |> |
| 108 | + flatten_jmp jmp tl |
| 109 | + | None -> blk in |
| 110 | + |
| 111 | + match Seq.next elts with |
| 112 | + | Some (hd, tl) -> (match hd with |
| 113 | + | `Def def -> |
| 114 | + let exp, blk = flatten_exp (Def.rhs def) blk (Term.tid def) in |
| 115 | + Def.with_rhs def exp |> Term.update def_t blk |> |
| 116 | + flatten_elts tl |
| 117 | + | `Jmp jmp -> flatten_jmp jmp (Jmp.exps jmp) blk |
| 118 | + | `Phi phi -> flatten_elts tl blk) |
| 119 | + | None -> blk in |
| 120 | + |
| 121 | + flatten_elts (Blk.elts original_blk) original_blk |
| 122 | + |
| 123 | +let flatten_sub = |
| 124 | + Term.map blk_t ~f:flatten_blk |
| 125 | + |
| 126 | +let main = Project.map_program ~f:(Term.map sub_t ~f:flatten_sub) |
| 127 | + |
| 128 | +;; |
| 129 | +Config.manpage [ |
| 130 | + `S "DESCRIPTION"; |
| 131 | + `P "Flatten all AST in the program."; |
| 132 | + `S "EXAMPLE"; |
| 133 | + `Pre {| |
| 134 | + ;; input |
| 135 | + #10 := 11 * (#9 + 13) - 17 |
| 136 | + ;; output |
| 137 | + #11 := #9 + 13 |
| 138 | + #12 := 11 * #11 |
| 139 | + #10 := #12 - 17 |
| 140 | + |} |
| 141 | + |
| 142 | +] |
| 143 | + |
| 144 | +let () = Config.when_ready (fun _ -> Project.register_pass main);; |
0 commit comments