Skip to content

Commit c0f0f96

Browse files
0possivg
andauthored
adds the flatten pass (#1332)
* Added flatten/unroll pass. * Update plugins/flatten/flatten_main.ml Co-authored-by: Ivan Gotovchits <[email protected]> * Update plugins/flatten/flatten_main.ml Co-authored-by: Ivan Gotovchits <[email protected]> * Update plugins/flatten/flatten_main.ml Co-authored-by: Ivan Gotovchits <[email protected]> * Update plugins/flatten/flatten_main.ml Co-authored-by: Ivan Gotovchits <[email protected]> * applies `make indent` * adds the missing core_kernel dependency Co-authored-by: Ivan Gotovchits <[email protected]>
1 parent 650c35c commit c0f0f96

File tree

3 files changed

+164
-0
lines changed

3 files changed

+164
-0
lines changed

oasis/flatten

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Flag flatten
2+
Description: Build the flatten plugin
3+
Default: false
4+
5+
Library flatten_plugin
6+
Build$: flag(everything) || flag(flatten)
7+
XMETADescription: flattens (unrolls) BIR expressions into a trivial form
8+
Path: plugins/flatten
9+
FindlibName: bap-plugin-flatten
10+
CompiledObject: best
11+
BuildDepends: bap, core_kernel
12+
InternalModules: Flatten_main
13+
XMETAExtraLines: tags="pass,analysis,flatten,tac,3ac,unroll"

plugins/flatten/.merlin

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
PKG core_kernel
2+
PKG bap
3+
PKG ocamlgraph
4+
5+
B _build
6+
FLG -short-paths
7+
FLG -w -4-33-40-41-42-43-34-44

plugins/flatten/flatten_main.ml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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

Comments
 (0)