@@ -12,20 +12,24 @@ Author: Daniel Kroening, kroening@kroening.com
12
12
#include " bmc.h"
13
13
14
14
#include < chrono>
15
+ #include < exception>
15
16
#include < fstream>
16
17
#include < iostream>
17
18
#include < memory>
18
19
20
+ #include < util/exit_codes.h>
19
21
#include < util/string2int.h>
20
22
#include < util/source_location.h>
21
23
#include < util/string_utils.h>
24
+ #include < util/memory_info.h>
22
25
#include < util/message.h>
23
26
#include < util/json.h>
24
27
#include < util/cprover_prefix.h>
25
28
26
29
#include < langapi/mode.h>
27
30
#include < langapi/language_util.h>
28
31
32
+ #include < goto-programs/goto_model.h>
29
33
#include < goto-programs/xml_goto_trace.h>
30
34
#include < goto-programs/json_goto_trace.h>
31
35
#include < goto-programs/graphml_witness.h>
@@ -37,6 +41,7 @@ Author: Daniel Kroening, kroening@kroening.com
37
41
#include < goto-symex/memory_model_tso.h>
38
42
#include < goto-symex/memory_model_pso.h>
39
43
44
+ #include " cbmc_solvers.h"
40
45
#include " counterexample_beautification.h"
41
46
#include " fault_localization.h"
42
47
@@ -359,8 +364,7 @@ safety_checkert::resultt bmct::execute(const goto_functionst &goto_functions)
359
364
{
360
365
try
361
366
{
362
- // perform symbolic execution
363
- symex.symex_from_entry_point_of (goto_functions);
367
+ perform_symbolic_execution (goto_functions);
364
368
365
369
// add a partial ordering, if required
366
370
if (equation.has_threads ())
@@ -595,3 +599,118 @@ void bmct::setup_unwind()
595
599
if (options.get_option (" unwind" )!=" " )
596
600
symex.set_unwind_limit (options.get_unsigned_int_option (" unwind" ));
597
601
}
602
+
603
+ int bmct::do_language_agnostic_bmc (
604
+ const optionst &opts,
605
+ const goto_modelt &goto_model,
606
+ const ui_message_handlert::uit &ui,
607
+ messaget &message,
608
+ std::function<void (bmct &, const goto_modelt &)> frontend_configure_bmc)
609
+ {
610
+ message_handlert &mh = message.get_message_handler ();
611
+ safety_checkert::resultt result;
612
+ goto_symext::branch_worklistt worklist;
613
+ try
614
+ {
615
+ {
616
+ cbmc_solverst solvers (
617
+ opts, goto_model.symbol_table , message.get_message_handler ());
618
+ solvers.set_ui (ui);
619
+ std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
620
+ cbmc_solver = solvers.get_solver ();
621
+ prop_convt &pc = cbmc_solver->prop_conv ();
622
+ bmct bmc (opts, goto_model.symbol_table , mh, pc, worklist);
623
+ bmc.set_ui (ui);
624
+ frontend_configure_bmc (bmc, goto_model);
625
+ result = bmc.run (goto_model.goto_functions );
626
+ }
627
+ INVARIANT (
628
+ opts.get_bool_option (" paths" ) || worklist.empty (),
629
+ " the worklist should be empty after doing full-program "
630
+ " model checking, but the worklist contains " +
631
+ std::to_string (worklist.size ()) + " unexplored branches." );
632
+
633
+ // When model checking, the bmc.run() above will already have explored
634
+ // the entire program, and result contains the verification result. The
635
+ // worklist (containing paths that have not yet been explored) is thus
636
+ // empty, and we don't enter this loop.
637
+ //
638
+ // When doing path exploration, there will be some saved paths left to
639
+ // explore in the worklist. We thus need to run the above code again,
640
+ // once for each saved path in the worklist, to continue symbolically
641
+ // execute the program. Note that the code in the loop is similar to
642
+ // the code above except that we construct a path_explorert rather than
643
+ // a bmct, which allows us to execute from a saved state rather than
644
+ // from the entry point. See the path_explorert documentation, and the
645
+ // difference between the implementations of perform_symbolic_exection()
646
+ // in bmct and path_explorert, for more information.
647
+
648
+ while (!worklist.empty ())
649
+ {
650
+ message.status () << " ___________________________\n "
651
+ << " Starting new path (" << worklist.size ()
652
+ << " to go)\n "
653
+ << message.eom ;
654
+ cbmc_solverst solvers (
655
+ opts, goto_model.symbol_table , message.get_message_handler ());
656
+ solvers.set_ui (ui);
657
+ std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
658
+ cbmc_solver = solvers.get_solver ();
659
+ prop_convt &pc = cbmc_solver->prop_conv ();
660
+ goto_symext::branch_pointt &resume = worklist.front ();
661
+ path_explorert pe (
662
+ opts,
663
+ goto_model.symbol_table ,
664
+ mh,
665
+ pc,
666
+ resume.equation ,
667
+ resume.state ,
668
+ worklist);
669
+ frontend_configure_bmc (pe, goto_model);
670
+ result &= pe.run (goto_model.goto_functions );
671
+ worklist.pop_front ();
672
+ }
673
+ }
674
+ catch (const char *error_msg)
675
+ {
676
+ message.error () << error_msg << message.eom ;
677
+ return CPROVER_EXIT_EXCEPTION;
678
+ }
679
+ catch (const std::string &error_msg)
680
+ {
681
+ message.error () << error_msg << message.eom ;
682
+ return CPROVER_EXIT_EXCEPTION;
683
+ }
684
+ catch (...)
685
+ {
686
+ message.error () << " unable to get solver" << message.eom ;
687
+ throw std::current_exception ();
688
+ }
689
+
690
+ switch (result)
691
+ {
692
+ case safety_checkert::resultt::SAFE:
693
+ return CPROVER_EXIT_VERIFICATION_SAFE;
694
+ case safety_checkert::resultt::UNSAFE:
695
+ return CPROVER_EXIT_VERIFICATION_UNSAFE;
696
+ case safety_checkert::resultt::ERROR:
697
+ return CPROVER_EXIT_INTERNAL_ERROR;
698
+ }
699
+ UNREACHABLE;
700
+ }
701
+
702
+ void bmct::perform_symbolic_execution (const goto_functionst &goto_functions)
703
+ {
704
+ symex.symex_from_entry_point_of (goto_functions, symex_symbol_table);
705
+ INVARIANT (
706
+ options.get_bool_option (" paths" ) || branch_worklist.empty (),
707
+ " Branch points were saved even though we should have been "
708
+ " executing the entire program and merging paths" );
709
+ }
710
+
711
+ void path_explorert::perform_symbolic_execution (
712
+ const goto_functionst &goto_functions)
713
+ {
714
+ symex.resume_symex_from_saved_state (
715
+ goto_functions, saved_state, &equation, symex_symbol_table);
716
+ }
0 commit comments