Skip to content

Commit 978ca5b

Browse files
committed
Add callback after symex to bmct
This permits frontend programs to intervene after symex executes, either in addition to or instead of running bmc. Its current use case is to implement show-goto-functions and similar debug output options when symex-driven lazy loading means that function bodies are not populated until symex has run. When --paths is in use, the callback will be made every time symex finishes a path.
1 parent 8df9350 commit 978ca5b

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

src/cbmc/bmc.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,15 @@ safety_checkert::resultt bmct::execute(
377377
const goto_functionst &goto_functions =
378378
goto_model.get_goto_functions();
379379

380+
// This provides the driver program the opportunity to do things like a
381+
// symbol-table or goto-functions dump instead of actually running the
382+
// checker, like show-vcc except driver-program specific.
383+
// In particular clients that use symex-driven program loading need to print
384+
// GOTO functions after symex, as function bodies are not produced until
385+
// symex first requests them.
386+
if(driver_callback_after_symex && driver_callback_after_symex())
387+
return safety_checkert::resultt::SAFE; // to indicate non-error
388+
380389
// add a partial ordering, if required
381390
if(equation.has_threads())
382391
{
@@ -616,14 +625,15 @@ void bmct::setup_unwind()
616625
// creating those function bodies on demand.
617626
/// \param ui: user-interface mode (plain text, XML output, JSON output, ...)
618627
/// \param message: used for logging
619-
/// \param frontend_configure_bmc: function provided by the frontend program,
620-
/// which applies frontend-specific configuration to a bmct before running.
628+
/// \param driver_configure_bmc: function provided by the driver program,
629+
/// which applies driver-specific configuration to a bmct before running.
621630
int bmct::do_language_agnostic_bmc(
622631
const optionst &opts,
623632
abstract_goto_modelt &model,
624633
const ui_message_handlert::uit &ui,
625634
messaget &message,
626-
std::function<void(bmct &, const symbol_tablet &)> frontend_configure_bmc)
635+
std::function<void(bmct &, const symbol_tablet &)> driver_configure_bmc,
636+
std::function<bool(void)> callback_after_symex)
627637
{
628638
const symbol_tablet &symbol_table = model.get_symbol_table();
629639
message_handlert &mh = message.get_message_handler();
@@ -637,9 +647,10 @@ int bmct::do_language_agnostic_bmc(
637647
std::unique_ptr<cbmc_solverst::solvert> cbmc_solver;
638648
cbmc_solver = solvers.get_solver();
639649
prop_convt &pc = cbmc_solver->prop_conv();
640-
bmct bmc(opts, symbol_table, mh, pc, worklist);
650+
bmct bmc(opts, symbol_table, mh, pc, worklist, callback_after_symex);
641651
bmc.set_ui(ui);
642-
frontend_configure_bmc(bmc, symbol_table);
652+
if(driver_configure_bmc)
653+
driver_configure_bmc(bmc, symbol_table);
643654
result = bmc.run(model);
644655
}
645656
INVARIANT(
@@ -682,8 +693,10 @@ int bmct::do_language_agnostic_bmc(
682693
pc,
683694
resume.equation,
684695
resume.state,
685-
worklist);
686-
frontend_configure_bmc(pe, symbol_table);
696+
worklist,
697+
callback_after_symex);
698+
if(driver_configure_bmc)
699+
driver_configure_bmc(pe, symbol_table);
687700
result &= pe.run(model);
688701
worklist.pop_front();
689702
}

src/cbmc/bmc.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ class bmct:public safety_checkert
7474
const symbol_tablet &outer_symbol_table,
7575
message_handlert &_message_handler,
7676
prop_convt &_prop_conv,
77-
goto_symext::branch_worklistt &_branch_worklist)
77+
goto_symext::branch_worklistt &_branch_worklist,
78+
std::function<bool(void)> callback_after_symex)
7879
: safety_checkert(ns, _message_handler),
7980
options(_options),
8081
outer_symbol_table(outer_symbol_table),
@@ -83,7 +84,8 @@ class bmct:public safety_checkert
8384
branch_worklist(_branch_worklist),
8485
symex(_message_handler, outer_symbol_table, equation, branch_worklist),
8586
prop_conv(_prop_conv),
86-
ui(ui_message_handlert::uit::PLAIN)
87+
ui(ui_message_handlert::uit::PLAIN),
88+
driver_callback_after_symex(callback_after_symex)
8789
{
8890
symex.constant_propagation=options.get_bool_option("propagation");
8991
symex.record_coverage=
@@ -128,10 +130,9 @@ class bmct:public safety_checkert
128130
abstract_goto_modelt &goto_model,
129131
const ui_message_handlert::uit &ui,
130132
messaget &message,
131-
std::function<void(bmct &, const symbol_tablet &)> frontend_configure_bmc =
132-
[](bmct &_bmc, const symbol_tablet &) { // NOLINT (*)
133-
// Empty default implementation
134-
});
133+
std::function<void(bmct &, const symbol_tablet &)>
134+
driver_configure_bmc = nullptr,
135+
std::function<bool(void)> callback_after_symex = nullptr);
135136

136137
protected:
137138
/// \brief Constructor for path exploration from saved state
@@ -147,7 +148,8 @@ class bmct:public safety_checkert
147148
message_handlert &_message_handler,
148149
prop_convt &_prop_conv,
149150
symex_target_equationt &_equation,
150-
goto_symext::branch_worklistt &_branch_worklist)
151+
goto_symext::branch_worklistt &_branch_worklist,
152+
std::function<bool(void)> callback_after_symex)
151153
: safety_checkert(ns, _message_handler),
152154
options(_options),
153155
outer_symbol_table(outer_symbol_table),
@@ -156,7 +158,8 @@ class bmct:public safety_checkert
156158
branch_worklist(_branch_worklist),
157159
symex(_message_handler, outer_symbol_table, equation, branch_worklist),
158160
prop_conv(_prop_conv),
159-
ui(ui_message_handlert::uit::PLAIN)
161+
ui(ui_message_handlert::uit::PLAIN),
162+
driver_callback_after_symex(callback_after_symex)
160163
{
161164
symex.constant_propagation = options.get_bool_option("propagation");
162165
symex.record_coverage =
@@ -238,6 +241,12 @@ class bmct:public safety_checkert
238241
/// full-program model-checking from the entry point of the program.
239242
virtual void perform_symbolic_execution(
240243
goto_symext::get_goto_functiont get_goto_function);
244+
245+
/// Optional callback, to be run after symex but before handing the resulting
246+
/// equation to the solver. If it returns true then we will skip the solver
247+
/// stage and return "safe" (no assertions violated / coverage goals reached),
248+
/// similar to the behaviour when 'show-vcc' or 'program-only' are specified.
249+
std::function<bool(void)> driver_callback_after_symex;
241250
};
242251

243252
/// \brief Symbolic execution from a saved branch point
@@ -260,14 +269,16 @@ class path_explorert : public bmct
260269
prop_convt &_prop_conv,
261270
symex_target_equationt &saved_equation,
262271
const goto_symex_statet &saved_state,
263-
goto_symext::branch_worklistt &branch_worklist)
272+
goto_symext::branch_worklistt &branch_worklist,
273+
std::function<bool(void)> callback_after_symex)
264274
: bmct(
265275
_options,
266276
outer_symbol_table,
267277
_message_handler,
268278
_prop_conv,
269279
saved_equation,
270-
branch_worklist),
280+
branch_worklist,
281+
callback_after_symex),
271282
saved_state(saved_state)
272283
{
273284
}

0 commit comments

Comments
 (0)