Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds the flatten pass #1332

Merged
merged 7 commits into from
Jul 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions oasis/flatten
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Flag flatten
Description: Build the flatten plugin
Default: false

Library flatten_plugin
Build$: flag(everything) || flag(flatten)
XMETADescription: flattens (unrolls) BIR expressions into a trivial form
Path: plugins/flatten
FindlibName: bap-plugin-flatten
CompiledObject: best
BuildDepends: bap, core_kernel
InternalModules: Flatten_main
XMETAExtraLines: tags="pass,analysis,flatten,tac,3ac,unroll"
7 changes: 7 additions & 0 deletions plugins/flatten/.merlin
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
PKG core_kernel
PKG bap
PKG ocamlgraph

B _build
FLG -short-paths
FLG -w -4-33-40-41-42-43-34-44
144 changes: 144 additions & 0 deletions plugins/flatten/flatten_main.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
open Bap.Std
open Core_kernel
include Self()


let get_direct_typ (e : exp) : Type.t = match e with
| Bil.Var v -> Var.typ v
| Bil.Unknown (_,t) -> t
| Bil.Int w -> Type.Imm (Word.bitwidth w)
| _ -> failwith "the expression is not flattened"

let flatten_exp (exp : exp) (blk : blk term) (before : tid) : exp * blk term =
let is_virtual = true in
let fresh = true in
let rec aux (exp : exp) (blk : blk term) = match exp with
| Bil.Load (x, y, endian, s) ->
let x, blk = aux x blk in
let y, blk = aux y blk in
let vtype = Type.Imm (Size.in_bits s) in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Load (x, y, endian, s) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.Store (x, y, z, endian, s) ->
let x, blk = aux x blk in
let y, blk = aux y blk in
let z, blk = aux z blk in
let vtype = Type.Imm (Size.in_bits s) in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Store (x, y, z, endian, s) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.BinOp (b, x, y) ->
let x, blk = aux x blk in
let y, blk = aux y blk in
let vtype = get_direct_typ x in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.BinOp(b, x, y) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.UnOp (u, x) ->
let x, blk = aux x blk in
let vtype = get_direct_typ x in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.UnOp(u, x) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.Var _
| Bil.Int _ -> exp, blk
| Bil.Cast (c, n, x) ->
let x, blk = aux x blk in
let vtype = Type.Imm n in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Cast (c, n, x) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.Let (v, x, y) ->
let x, blk = aux x blk in
let y, blk = aux y blk in
let vtype = Var.typ v in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Let (v, x, y) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.Unknown (_, _) -> exp, blk
| Bil.Ite (x, y, z) ->
let x, blk = aux x blk in
let y, blk = aux y blk in
let z, blk = aux z blk in
let vtype = get_direct_typ y in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Ite (x, y, z) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.Extract (n, p, x) ->
let x, blk = aux x blk in
let vtype = get_direct_typ x in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Extract (n, p, x) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def
| Bil.Concat (x, y) ->
let x, blk = aux x blk in
let y, blk = aux y blk in
let vtype = get_direct_typ x in
let var = Var.create ~is_virtual ~fresh "flt" vtype in
let e = Bil.Concat (x, y) in
let def = Def.create var e in
Bil.Var var,
Term.prepend def_t ~before blk def in
aux exp blk

let flatten_blk original_blk =
let rec flatten_elts (elts : Blk.elt seq) (blk : blk term) =
let rec flatten_jmp (jmp : Jmp.t) (expseq : exp seq) (blk : blk term) =
match Seq.next expseq with
| Some(hd, tl) ->
let exp, blk = flatten_exp hd blk (Term.tid jmp) in
Jmp.substitute jmp hd exp |> Term.update jmp_t blk |>
flatten_jmp jmp tl
| None -> blk in

match Seq.next elts with
| Some (hd, tl) -> (match hd with
| `Def def ->
let exp, blk = flatten_exp (Def.rhs def) blk (Term.tid def) in
Def.with_rhs def exp |> Term.update def_t blk |>
flatten_elts tl
| `Jmp jmp -> flatten_jmp jmp (Jmp.exps jmp) blk
| `Phi phi -> flatten_elts tl blk)
| None -> blk in

flatten_elts (Blk.elts original_blk) original_blk

let flatten_sub =
Term.map blk_t ~f:flatten_blk

let main = Project.map_program ~f:(Term.map sub_t ~f:flatten_sub)

;;
Config.manpage [
`S "DESCRIPTION";
`P "Flatten all AST in the program.";
`S "EXAMPLE";
`Pre {|
;; input
#10 := 11 * (#9 + 13) - 17
;; output
#11 := #9 + 13
#12 := 11 * #11
#10 := #12 - 17
|}

]

let () = Config.when_ready (fun _ -> Project.register_pass main);;