forked from rems-project/asl-interpreter
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #55 from UQ-PAC/taint
Offline Partial Eval
- Loading branch information
Showing
30 changed files
with
3,615 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
open LibASL | ||
open Testing | ||
open Asl_ast | ||
open Value | ||
|
||
let () = Printexc.register_printer | ||
(function | ||
| Value.EvalError (loc, e) -> | ||
Some ("EvalError at " ^ pp_loc loc ^ ": " ^ e) | ||
| _ -> None) | ||
|
||
let op_dis (op: int): stmt list opresult = | ||
let bv = Primops.prim_cvt_int_bits (Z.of_int 32) (Z.of_int op) in | ||
try | ||
let stmts = OfflineASL.Offline.run bv in | ||
Result.Ok stmts | ||
with | ||
| e -> Result.Error (Op_DisFail e) | ||
|
||
let op_test_opcode (env: Env.t) (iset: string) (op: int): Env.t opresult = | ||
let op' = Value.VBits (Primops.prim_cvt_int_bits (Z.of_int 32) (Z.of_int op)) in | ||
|
||
let initenv = Env.copy env in | ||
Random.self_init (); | ||
let vals = (List.init 64 (fun _ -> Z.of_int64 (Random.int64 Int64.max_int))) in | ||
Eval.initializeRegistersAndMemory initenv vals; | ||
Eval.initializeGlobals initenv; | ||
|
||
let initenv = Env.freeze initenv in | ||
|
||
let (let*) = Result.bind in | ||
let* evalenv = op_eval initenv iset op' in | ||
let* disstmts = op_dis op in | ||
let* disevalenv = op_diseval initenv disstmts in | ||
op_compare (evalenv, disevalenv) | ||
|
||
let run opt_verbose instr env = | ||
let iset = "A64" in | ||
let encodings = get_opcodes opt_verbose iset instr env in | ||
List.iter (fun (enc, fields, opt_opcodes) -> | ||
Printf.printf "\nENCODING: %s\n" enc; | ||
match opt_opcodes with | ||
| None -> Printf.printf "(encoding unused)\n"; | ||
| Some opcodes -> | ||
List.iter (fun (op, valid) -> | ||
let fs = fields_of_opcode fields op in | ||
Printf.printf "%s: %s --> " (hex_of_int op) (pp_enc_fields fs); | ||
flush stdout; | ||
if valid then | ||
let result = op_test_opcode env iset op in | ||
Printf.printf "%s\n" (pp_opresult (fun _ -> "OK") result) | ||
else Printf.printf "(invalid)\n"; | ||
) opcodes | ||
) encodings | ||
|
||
let opt_instr = ref [] | ||
let options = Arg.align ([]) | ||
let usage_msg = "" | ||
|
||
let _ = | ||
Arg.parse options | ||
(fun s -> opt_instr := (!opt_instr) @ [s]) | ||
usage_msg | ||
|
||
let rec process_command tcenv env cmd = | ||
match String.split_on_char ' ' cmd with | ||
| (":set" :: "impdef" :: rest) -> | ||
let cmd = String.concat " " rest in | ||
let (x, e) = LoadASL.read_impdef tcenv Unknown cmd in | ||
let v = Eval.eval_expr Unknown env e in | ||
Eval.Env.setImpdef env x v | ||
| [":project"; prj] -> | ||
let inchan = open_in prj in | ||
(try | ||
while true do | ||
process_command tcenv env (input_line inchan) | ||
done | ||
with | ||
| End_of_file -> | ||
close_in inchan | ||
) | ||
| [""] -> () | ||
| _ -> Printf.printf "Ignoring: %s\n" cmd | ||
|
||
let main () = | ||
let opt_verbose = ref false in | ||
let env = match Eval.aarch64_evaluation_environment ~verbose:!opt_verbose () with | ||
| Some e -> e | ||
| _ -> failwith "Unable to build evaluation environment." in | ||
let filenames = Option.get Eval.aarch64_asl_files in | ||
let prj_files = List.filter (fun f -> Utils.endswith f ".prj") (snd filenames) in | ||
let tcenv = Tcheck.Env.mkEnv Tcheck.env0 in | ||
List.iter (fun f -> process_command tcenv env (":project " ^ f)) prj_files; | ||
List.map (fun instr -> run opt_verbose instr env) !opt_instr | ||
|
||
let _ = ignore (main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
open LibASL | ||
open Asl_ast | ||
open Asl_utils | ||
|
||
let run (opcode: string) = | ||
let op = Z.of_string opcode in | ||
let bv = Primops.prim_cvt_int_bits (Z.of_int 32) op in | ||
let stmts = OfflineASL.Offline.run bv in | ||
List.iter (fun s -> Printf.printf "%s\n" (pp_stmt s)) stmts | ||
|
||
let opt_instr = ref [] | ||
let options = Arg.align ([]) | ||
let usage_msg = "" | ||
|
||
let _ = | ||
Arg.parse options | ||
(fun s -> opt_instr := (!opt_instr) @ [s]) | ||
usage_msg | ||
|
||
let main () = | ||
List.map (fun instr -> run instr) !opt_instr | ||
|
||
let _ = main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
open Asl_ast | ||
open Asl_utils | ||
open Asl_visitor | ||
open Utils | ||
|
||
type state = { | ||
mutable callers : IdentSet.t Bindings.t; | ||
mutable seen : IdentSet.t; | ||
mutable worklist : IdentSet.t; | ||
} | ||
|
||
class call_visitor(fn : ident -> unit) = object (self) | ||
inherit Asl_visitor.nopAslVisitor | ||
method! vlexpr e = | ||
(match e with | ||
| LExpr_Write (f, _, _) -> fn f | ||
| LExpr_ReadWrite (g, s, _, _) -> fn g; fn s | ||
| _ -> ()); | ||
DoChildren | ||
method! vexpr e = | ||
(match e with | ||
| Expr_TApply (f, _, _) -> fn f | ||
| _ -> ()); | ||
DoChildren | ||
method! vstmt e = | ||
(match e with | ||
| Stmt_TCall (f, _, _, _) -> fn f | ||
| _ -> ()); | ||
DoChildren | ||
end | ||
|
||
let init_state i: state = | ||
{ callers = Bindings.empty; seen = i; worklist = i } | ||
|
||
let get_callers (st: state) id = | ||
match Bindings.find_opt id st.callers with | ||
| None -> IdentSet.empty | ||
| Some v -> v | ||
|
||
let callback (st: state) (caller: ident) (callee: ident) = | ||
(* Add caller edge *) | ||
let existing = get_callers st callee in | ||
st.callers <- Bindings.add callee (IdentSet.add caller existing) st.callers; | ||
(* Add to worklist if a new callee *) | ||
if not (IdentSet.mem callee st.seen) then st.worklist <- IdentSet.add callee st.worklist; | ||
(* Mark as seen *) | ||
st.seen <- IdentSet.add callee st.seen | ||
|
||
let get_body i env = | ||
match Eval.Env.getFunOpt Unknown env i with | ||
| Some fnsig -> fnsig_get_body fnsig | ||
| _ -> [] | ||
|
||
let run (init: IdentSet.t) frontier (env: Eval.Env.t): (IdentSet.t Bindings.t * IdentSet.t) = | ||
(* create mutable state with initial worklist, seen, empty edges *) | ||
let rec iter st = begin | ||
(* Get fns to visit, clear worklist *) | ||
let delta = st.worklist in | ||
st.worklist <- IdentSet.empty; | ||
|
||
(* Walk each function in delta *) | ||
IdentSet.iter (fun fn -> | ||
let walker = new call_visitor(callback st fn) in | ||
let body = get_body fn env in | ||
let _ = visit_stmts walker body in | ||
()) (IdentSet.diff delta frontier); | ||
|
||
(* If more fns to process, loop *) | ||
if IdentSet.cardinal st.worklist = 0 then () | ||
else iter st | ||
end in | ||
|
||
let st = init_state init in | ||
let _ = iter st in | ||
(* Filter seen to only include functions with implementations *) | ||
let seen = IdentSet.filter (fun v -> not (isNone (Eval.Env.getFunOpt Unknown env v))) st.seen in | ||
let seen = IdentSet.diff seen frontier in | ||
(st.callers, seen) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.