Skip to content

Commit d23288e

Browse files
committed
wip
1 parent ea95a1e commit d23288e

File tree

10 files changed

+586
-226
lines changed

10 files changed

+586
-226
lines changed

src/cmd/cmd_sym.ml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ let link_state =
1717
Link.extern_module' Link.empty_state ~name:"symbolic" ~func_typ
1818
Symbolic_wasm_ffi.symbolic_extern_module
1919
in
20-
Link.extern_module' link_state ~name:"summaries" ~func_typ
21-
Symbolic_wasm_ffi.summaries_extern_module )
20+
let link_state =
21+
Link.extern_module' link_state ~name:"summaries" ~func_typ
22+
Symbolic_wasm_ffi.summaries_extern_module
23+
in
24+
Link.extern_module' link_state ~name:"debug" ~func_typ
25+
Symbolic_wasm_ffi.debug_extern_module )
2226

2327
let run_binary_modul ~unsafe ~optimize (pc : unit Result.t Choice.t)
2428
(m : Binary.modul) =
@@ -81,9 +85,9 @@ let cmd profiling debug unsafe optimize workers no_stop_at_failure no_values
8185
Format.pp_std "Assert failure: %a@\n" Expr.pp assertion;
8286
Format.pp_std "Model:@\n @[<v>%a@]@." (Smtml.Model.pp ~no_values) model
8387
in
84-
let rec print_and_count_failures count_acc results =
88+
let rec print_and_count_failures (failures_acc, paths_acc) results =
8589
match results () with
86-
| Seq.Nil -> Ok count_acc
90+
| Seq.Nil -> Ok (failures_acc, paths_acc)
8791
| Seq.Cons ((result, _thread), tl) ->
8892
let* model =
8993
let open Symbolic_choice in
@@ -98,7 +102,8 @@ let cmd profiling debug unsafe optimize workers no_stop_at_failure no_values
98102
failwith "unreachable: callback should have filtered eval ok out."
99103
| EVal (Error e) -> Error e
100104
in
101-
let count_acc = succ count_acc in
105+
let paths_acc = succ paths_acc in
106+
let failures_acc = succ failures_acc in
102107
let* () =
103108
if not no_values then
104109
let testcase =
@@ -107,8 +112,9 @@ let cmd profiling debug unsafe optimize workers no_stop_at_failure no_values
107112
Cmd_utils.write_testcase ~dir:workspace testcase
108113
else Ok ()
109114
in
110-
if no_stop_at_failure then print_and_count_failures count_acc tl
111-
else Ok count_acc
115+
if no_stop_at_failure then
116+
print_and_count_failures (failures_acc, paths_acc) tl
117+
else Ok (failures_acc, paths_acc)
112118
in
113119
let results =
114120
if deterministic_result_order then
@@ -121,8 +127,9 @@ let cmd profiling debug unsafe optimize workers no_stop_at_failure no_values
121127
|> List.to_seq |> Seq.map fst
122128
else results
123129
in
124-
let* count = print_and_count_failures 0 results in
125-
if count > 0 then Error (`Found_bug count)
130+
let* failures, paths = print_and_count_failures (0, 0) results in
131+
Format.pp_std "Completed paths: %d@." paths;
132+
if failures > 0 then Error (`Found_bug failures)
126133
else begin
127134
Format.pp_std "All OK";
128135
Ok ()

src/concolic/concolic_wasm_ffi.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,7 @@ let summaries_extern_module =
184184
]
185185
in
186186
{ Link.functions }
187+
188+
let debug_extern_module =
189+
let functions = [] in
190+
{ Link.functions }

src/intf/wasm_ffi_intf.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ module type S = sig
4646
val symbolic_extern_module : extern_func Link.extern_module
4747

4848
val summaries_extern_module : extern_func Link.extern_module
49+
50+
val debug_extern_module : extern_func Link.extern_module
4951
end

src/symbolic/symbolic.ml

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -57,58 +57,25 @@ struct
5757
module Memory = struct
5858
include Symbolic_memory
5959

60-
let concretise (a : Smtml.Expr.t) : Smtml.Expr.t Choice.t =
61-
let open Choice in
62-
let open Smtml in
63-
match Expr.view a with
64-
(* Avoid unecessary re-hashconsing and allocation when the value
65-
is already concrete. *)
66-
| Val _ | Ptr { offset = { node = Val _; _ }; _ } -> return a
67-
| Ptr { base; offset } ->
68-
let+ offset = select_i32 offset in
69-
Expr.ptr base (Symbolic_value.const_i32 offset)
70-
| _ ->
71-
let+ v = select_i32 a in
72-
Symbolic_value.const_i32 v
73-
74-
let check_within_bounds m a =
75-
match check_within_bounds m a with
76-
| Error t -> Choice.trap t
77-
| Ok (cond, ptr) ->
78-
let open Choice in
79-
let* out_of_bounds = select cond in
80-
if out_of_bounds then trap Trap.Memory_heap_buffer_overflow
81-
else return ptr
82-
83-
let with_concrete (m : t) a f : 'a Choice.t =
84-
let open Choice in
85-
let* addr = concretise a in
86-
let+ ptr = check_within_bounds m addr in
87-
f m ptr
88-
89-
let load_8_s m a = with_concrete m a load_8_s
60+
let load_8_s m a = Choice.return @@ load_8_s m a
9061

91-
let load_8_u m a = with_concrete m a load_8_u
62+
let load_8_u m a = Choice.return @@ load_8_u m a
9263

93-
let load_16_s m a = with_concrete m a load_16_s
64+
let load_16_s m a = Choice.return @@ load_16_s m a
9465

95-
let load_16_u m a = with_concrete m a load_16_u
66+
let load_16_u m a = Choice.return @@ load_16_u m a
9667

97-
let load_32 m a = with_concrete m a load_32
68+
let load_32 m a = Choice.return @@ load_32 m a
9869

99-
let load_64 m a = with_concrete m a load_64
70+
let load_64 m a = Choice.return @@ load_64 m a
10071

101-
let store_8 m ~addr v =
102-
with_concrete m addr (fun m addr -> store_8 m ~addr v)
72+
let store_8 m ~addr v = Choice.return @@ store_8 m ~addr v
10373

104-
let store_16 m ~addr v =
105-
with_concrete m addr (fun m addr -> store_16 m ~addr v)
74+
let store_16 m ~addr v = Choice.return @@ store_16 m ~addr v
10675

107-
let store_32 m ~addr v =
108-
with_concrete m addr (fun m addr -> store_32 m ~addr v)
76+
let store_32 m ~addr v = Choice.return @@ store_32 m ~addr v
10977

110-
let store_64 m ~addr v =
111-
with_concrete m addr (fun m addr -> store_64 m ~addr v)
78+
let store_64 m ~addr v = Choice.return @@ store_64 m ~addr v
11279
end
11380

11481
module Data = struct

src/symbolic/symbolic.old.ml

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
(* SPDX-License-Identifier: AGPL-3.0-or-later *)
2+
(* Copyright © 2021-2024 OCamlPro *)
3+
(* Written by the Owi programmers *)
4+
5+
module type Thread = sig
6+
type t
7+
8+
val memories : t -> Symbolic_memory.collection
9+
10+
val tables : t -> Symbolic_table.collection
11+
12+
val globals : t -> Symbolic_global.collection
13+
14+
val pc : t -> Symbolic_value.vbool list
15+
end
16+
17+
module MakeP
18+
(Thread : Thread)
19+
(Choice : Choice_intf.Complete
20+
with module V := Symbolic_value
21+
and type thread := Thread.t) =
22+
struct
23+
module Value = Symbolic_value
24+
module Choice = Choice
25+
module Extern_func = Concrete_value.Make_extern_func (Value) (Choice)
26+
module Global = Symbolic_global
27+
module Table = Symbolic_table
28+
29+
type thread = Thread.t
30+
31+
let select (c : Value.vbool) ~(if_true : Value.t) ~(if_false : Value.t) :
32+
Value.t Choice.t =
33+
match (if_true, if_false) with
34+
| I32 if_true, I32 if_false ->
35+
Choice.return (Value.I32 (Value.Bool.select_expr c ~if_true ~if_false))
36+
| I64 if_true, I64 if_false ->
37+
Choice.return (Value.I64 (Value.Bool.select_expr c ~if_true ~if_false))
38+
| F32 if_true, F32 if_false ->
39+
Choice.return (Value.F32 (Value.Bool.select_expr c ~if_true ~if_false))
40+
| F64 if_true, F64 if_false ->
41+
Choice.return (Value.F64 (Value.Bool.select_expr c ~if_true ~if_false))
42+
| Ref _, Ref _ ->
43+
let open Choice in
44+
let+ b = select c in
45+
if b then if_true else if_false
46+
| _, _ -> assert false
47+
48+
module Elem = struct
49+
type t = Link_env.elem
50+
51+
let get (elem : t) i : Value.ref_value =
52+
match elem.value.(i) with Funcref f -> Funcref f | _ -> assert false
53+
54+
let size (elem : t) = Array.length elem.value
55+
end
56+
57+
module Memory = struct
58+
include Symbolic_memory
59+
60+
let concretise (a : Smtml.Expr.t) : Smtml.Expr.t Choice.t =
61+
let open Choice in
62+
let open Smtml in
63+
match Expr.view a with
64+
(* Avoid unecessary re-hashconsing and allocation when the value
65+
is already concrete. *)
66+
| Val _ | Ptr { offset = { node = Val _; _ }; _ } -> return a
67+
| Ptr { base; offset } ->
68+
let+ offset = select_i32 offset in
69+
Expr.ptr base (Symbolic_value.const_i32 offset)
70+
| _ ->
71+
let+ v = select_i32 a in
72+
Symbolic_value.const_i32 v
73+
74+
let check_within_bounds m a =
75+
match is_out_of_bounds m a with
76+
| Error t -> Choice.trap t
77+
| Ok (cond, ptr) ->
78+
let open Choice in
79+
let* out_of_bounds = select cond in
80+
if out_of_bounds then trap Trap.Memory_heap_buffer_overflow
81+
else return ptr
82+
83+
let with_concrete (m : t) a f : 'a Choice.t =
84+
let open Choice in
85+
let* addr = concretise a in
86+
let+ ptr = check_within_bounds m addr in
87+
f m ptr
88+
89+
let load_8_s m a = with_concrete m a load_8_s
90+
91+
let load_8_u m a = with_concrete m a load_8_u
92+
93+
let load_16_s m a = with_concrete m a load_16_s
94+
95+
let load_16_u m a = with_concrete m a load_16_u
96+
97+
let load_32 m a = with_concrete m a load_32
98+
99+
let load_64 m a = with_concrete m a load_64
100+
101+
let store_8 m ~addr v =
102+
with_concrete m addr (fun m addr -> store_8 m ~addr v)
103+
104+
let store_16 m ~addr v =
105+
with_concrete m addr (fun m addr -> store_16 m ~addr v)
106+
107+
let store_32 m ~addr v =
108+
with_concrete m addr (fun m addr -> store_32 m ~addr v)
109+
110+
let store_64 m ~addr v =
111+
with_concrete m addr (fun m addr -> store_64 m ~addr v)
112+
end
113+
114+
module Data = struct
115+
type t = Link_env.data
116+
117+
let value data = data.Link_env.value
118+
end
119+
120+
module Env = struct
121+
type t = Extern_func.extern_func Link_env.t
122+
123+
type t' = Env_id.t
124+
125+
let get_memory env id =
126+
let orig_mem = Link_env.get_memory env id in
127+
let f (t : thread) =
128+
let memories = Thread.memories t in
129+
Symbolic_memory.get_memory (Link_env.id env) orig_mem memories id
130+
in
131+
Choice.with_thread f
132+
133+
let get_func = Link_env.get_func
134+
135+
let get_extern_func = Link_env.get_extern_func
136+
137+
let get_table (env : t) i : Table.t Choice.t =
138+
let orig_table = Link_env.get_table env i in
139+
let f (t : thread) =
140+
let tables = Thread.tables t in
141+
Symbolic_table.get_table (Link_env.id env) orig_table tables i
142+
in
143+
Choice.with_thread f
144+
145+
let get_elem env i = Link_env.get_elem env i
146+
147+
let get_data env n =
148+
let data = Link_env.get_data env n in
149+
Choice.return data
150+
151+
let get_global (env : t) i : Global.t Choice.t =
152+
let orig_global = Link_env.get_global env i in
153+
let f (t : thread) =
154+
let globals = Thread.globals t in
155+
Symbolic_global.get_global (Link_env.id env) orig_global globals i
156+
in
157+
Choice.with_thread f
158+
159+
let drop_elem _ =
160+
(* TODO *)
161+
()
162+
163+
let drop_data = Link_env.drop_data
164+
end
165+
166+
module Module_to_run = struct
167+
(** runnable module *)
168+
type t =
169+
{ modul : Binary.modul
170+
; env : Env.t
171+
; to_run : Types.binary Types.expr list
172+
}
173+
174+
let env (t : t) = t.env
175+
176+
let modul (t : t) = t.modul
177+
178+
let to_run (t : t) = t.to_run
179+
end
180+
end
181+
182+
module P = MakeP [@inlined hint] (Thread) (Symbolic_choice)
183+
module M = MakeP [@inlined hint] (Thread) (Symbolic_choice_minimalist)
184+
185+
let convert_module_to_run (m : 'f Link.module_to_run) =
186+
P.Module_to_run.{ modul = m.modul; env = m.env; to_run = m.to_run }
187+
188+
let convert_module_to_run_minimalist (m : 'f Link.module_to_run) =
189+
M.Module_to_run.{ modul = m.modul; env = m.env; to_run = m.to_run }

0 commit comments

Comments
 (0)