|
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 | 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