Skip to content

Commit eafb105

Browse files
committed
Add --debug-asm-symex-first
This flag results in running symex on the asm side first, resulting in easier debugging when there is an error in symbolically executing the assembly at all.
1 parent efc121c commit eafb105

File tree

3 files changed

+63
-16
lines changed

3 files changed

+63
-16
lines changed

src/Assembly/Equivalence.v

+47-16
Original file line numberDiff line numberDiff line change
@@ -1452,30 +1452,61 @@ Section check_equivalence.
14521452
Local Notation map_err_None v := (ErrorT.map_error (fun e => (None, e)) v).
14531453
Local Notation map_err_Some label v := (ErrorT.map_error (fun e => (Some label, e)) v).
14541454

1455-
Definition check_equivalence : ErrorT (option (string (* fname *) * Lines (* asm lines *)) * EquivalenceCheckingError) unit :=
1455+
Definition map_symex_asm (inputs : list (idx + list idx)) (output_types : type_spec) (d : dag)
1456+
: ErrorT
1457+
(option (string (* fname *) * Lines (* asm lines *)) * EquivalenceCheckingError)
1458+
(list ((string (* fname *) * Lines (* asm lines *)) * (list (idx + list idx) * symbolic_state))) :=
14561459
let reg_available := assembly_calling_registers (* registers available for calling conventions *) in
1460+
(ls <-- (List.map
1461+
(fun '((fname, asm) as label)
1462+
=> (asm <- map_err_Some label (strip_ret asm);
1463+
let stack_size : nat := N.to_nat (assembly_stack_size asm) in
1464+
symevaled_asm <- map_err_Some label (symex_asm_func (dereference_output_scalars:=false) d assembly_callee_saved_registers output_types stack_size inputs reg_available asm);
1465+
Success (label, symevaled_asm)))
1466+
asm);
1467+
Success ls)%error.
1468+
1469+
Definition check_equivalence : ErrorT (option (string (* fname *) * Lines (* asm lines *)) * EquivalenceCheckingError) unit :=
14571470
let d := dag.empty in
14581471
input_types <- map_err_None (simplify_input_type t arg_bounds);
14591472
output_types <- map_err_None (simplify_base_type (type.final_codomain t) out_bounds);
1460-
let '(inputs, d) := build_inputs (descr:=Build_description "build_inputs" true ) input_types d in
1473+
let '(inputs, d) := build_inputs (descr:=Build_description "build_inputs" true) input_types d in
14611474

1462-
PHOAS_output <- map_err_None (symex_PHOAS expr inputs d);
1463-
let '(PHOAS_output, d) := PHOAS_output in
1475+
ls <- (
1476+
if negb debug_symex_asm_first then (
1477+
PHOAS_output <- map_err_None (symex_PHOAS expr inputs d);
1478+
let '(PHOAS_output, d) := PHOAS_output in
14641479

1465-
let first_new_idx_after_all_old_idxs : option idx := Some (dag.size d) in
1480+
let first_new_idx_after_all_old_idxs : option idx := Some (dag.size d) in
14661481

1467-
_ <-- (List.map
1468-
(fun '((fname, asm) as label)
1469-
=> (asm <- map_err_Some label (strip_ret asm);
1470-
let stack_size : nat := N.to_nat (assembly_stack_size asm) in
1471-
symevaled_asm <- map_err_Some label (symex_asm_func (dereference_output_scalars:=false) d assembly_callee_saved_registers output_types stack_size inputs reg_available asm);
1472-
let '(asm_output, s) := symevaled_asm in
1482+
asm_output <- map_symex_asm inputs output_types d;
1483+
1484+
let ls := List.map (fun '(lbl, (asm_output, s)) => (lbl, asm_output, PHOAS_output, s, first_new_idx_after_all_old_idxs)) asm_output in
1485+
Success ls
1486+
) else ( (* debug version, do asm first *)
1487+
asm_output <- map_symex_asm inputs output_types d;
1488+
1489+
ls <-- (List.map (fun '(lbl, (asm_output, s)) =>
1490+
let d := s.(dag_state) in
1491+
let first_new_idx_after_all_old_idxs : option idx := Some (dag.size d) in
1492+
1493+
PHOAS_output <- map_err_None (symex_PHOAS expr inputs d);
1494+
let '(PHOAS_output, d) := PHOAS_output in
1495+
1496+
let s := {| dag_state := d; symbolic_reg_state := s.(symbolic_reg_state); symbolic_flag_state := s.(symbolic_flag_state); symbolic_mem_state := s.(symbolic_mem_state) |} in
1497+
1498+
Success (lbl, asm_output, PHOAS_output, s, first_new_idx_after_all_old_idxs))
1499+
asm_output);
1500+
Success ls
1501+
));
1502+
1503+
_ <-- List.map (fun '(lbl, asm_output, PHOAS_output, s, first_new_idx_after_all_old_idxs) =>
1504+
if list_beq _ (sum_beq _ _ N.eqb (list_beq _ N.eqb)) asm_output PHOAS_output
1505+
then Success tt
1506+
else Error (Some lbl, Unable_to_unify asm_output PHOAS_output first_new_idx_after_all_old_idxs s))
1507+
ls;
1508+
Success tt.
14731509

1474-
if list_beq _ (sum_beq _ _ N.eqb (list_beq _ N.eqb)) asm_output PHOAS_output
1475-
then Success tt
1476-
else Error (Some label, Unable_to_unify asm_output PHOAS_output first_new_idx_after_all_old_idxs s)))
1477-
asm);
1478-
Success tt.
14791510

14801511
(** We don't actually generate assembly, we just check equivalence and pass assembly through unchanged *)
14811512
Definition generate_assembly_of_hinted_expr : ErrorT (option (string (* fname *) * Lines (* asm lines *)) * EquivalenceCheckingError) (list (string * Lines))

src/Assembly/Symbolic.v

+9
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,8 @@ Module Export Options.
401401
than every time, because it is (currently) quadratic to compute
402402
in the number of passes *)
403403
Class rewriting_passes_opt := rewriting_passes : list rewrite_pass.
404+
(** Should we symex the assembly first, even though this may be more inefficient? *)
405+
Class debug_symex_asm_first_opt := debug_symex_asm_first : bool.
404406
Definition default_rewriting_passes
405407
{rewriting_pipeline : rewriting_pipeline_opt}
406408
{rewriting_pass_filter : rewriting_pass_filter_opt}
@@ -410,17 +412,20 @@ Module Export Options.
410412
Class symbolic_options_opt :=
411413
{ asm_rewriting_pipeline : rewriting_pipeline_opt
412414
; asm_rewriting_pass_filter : rewriting_pass_filter_opt
415+
; asm_debug_symex_asm_first : debug_symex_asm_first_opt
413416
}.
414417

415418
(* This holds the list of computed options, which are passed around between methods *)
416419
Class symbolic_options_computed_opt :=
417420
{ asm_rewriting_passes : rewriting_passes_opt
421+
; asm_debug_symex_asm_first_computed : debug_symex_asm_first_opt
418422
}.
419423

420424
(* N.B. The default rewriting pass filter should not be changed here, but instead changed in CLI.v where it is derived from a default string *)
421425
Definition default_symbolic_options : symbolic_options_opt
422426
:= {| asm_rewriting_pipeline := default_rewrite_pass_order
423427
; asm_rewriting_pass_filter := fun _ => true
428+
; asm_debug_symex_asm_first := false
424429
|}.
425430
End Options.
426431
Module Export Hints.
@@ -431,13 +436,17 @@ Module Export Hints.
431436
asm_rewriting_pipeline
432437
asm_rewriting_pass_filter
433438
asm_rewriting_passes
439+
asm_debug_symex_asm_first
440+
asm_debug_symex_asm_first_computed
434441
.
435442
#[global]
436443
Hint Cut [
437444
( _ * )
438445
(asm_rewriting_pipeline
439446
| asm_rewriting_pass_filter
440447
| asm_rewriting_passes
448+
| asm_debug_symex_asm_first
449+
| asm_debug_symex_asm_first_computed
441450
) ( _ * )
442451
(Build_symbolic_options_opt
443452
| Build_symbolic_options_computed_opt

src/CLI.v

+7
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,10 @@ Module ForExtraction.
547547
:= ([Arg.long_key "asm-rewriting-passes"],
548548
Arg.String,
549549
["A comma-separated list of rewriting passes to enable. Prefix with - to disable a pass. This list only impacts passes listed in --asm-rewriting-pipeline. Default : " ++ (if default_asm_rewriting_passes =? "" then "(none)" else default_asm_rewriting_passes)]%string ++ describe_flag_options "rewriting pass" "Enable all rewriting passes" special_asm_rewriting_pass_flags known_asm_rewriting_pass_flags_with_spec)%list.
550+
Definition asm_debug_symex_asm_first_spec : named_argT
551+
:= ([Arg.long_key "debug-asm-symex-first"],
552+
Arg.Unit,
553+
["Debug option: If true, the assembly equivalence checker will symex the assembly first, even though this may be more inefficient. This may be useful for having a more concise description of errors in assembly symbolic execution."]).
550554
Definition doc_text_before_function_name_spec : named_argT
551555
:= ([Arg.long_key "doc-text-before-function-name"],
552556
Arg.String,
@@ -730,6 +734,7 @@ Module ForExtraction.
730734
; asm_error_on_unique_names_mismatch_spec
731735
; asm_rewriting_pipeline_spec
732736
; asm_rewriting_passes_spec
737+
; asm_debug_symex_asm_first_spec
733738
; doc_text_before_function_name_spec
734739
; doc_text_before_type_name_spec
735740
; doc_newline_before_package_declaration_spec
@@ -788,6 +793,7 @@ Module ForExtraction.
788793
, asm_error_on_unique_names_mismatchv
789794
, asm_rewriting_pipelinev
790795
, asm_rewriting_passesv
796+
, asm_debug_symex_asm_firstv
791797
, doc_text_before_function_namev
792798
, doc_text_before_type_namev
793799
, doc_newline_before_package_declarationv
@@ -875,6 +881,7 @@ Module ForExtraction.
875881
; symbolic_options_ :=
876882
{| asm_rewriting_pipeline := to_rewriting_pipeline_list asm_rewriting_pipelinev
877883
; asm_rewriting_pass_filter := fun p => asm_rewriting_pass_filterv (show_rewrite_pass p)
884+
; asm_debug_symex_asm_first := to_bool asm_debug_symex_asm_firstv
878885
|}
879886
|}
880887
; ignore_unique_asm_names := negb (to_bool asm_error_on_unique_names_mismatchv)

0 commit comments

Comments
 (0)