1+ #ifndef CONCOLIC_DRIVER_HPP
2+ #define CONCOLIC_DRIVER_HPP
3+
4+ #include " smt_solver.hpp"
5+ #include " symbolic_rt.hpp"
6+ #include < functional>
7+ #include < ostream>
8+ #include < string>
9+
10+ class ConcolicDriver {
11+ friend class ManagedConcolicCleanup ;
12+
13+ public:
14+ ConcolicDriver (std::function<void ()> entrypoint, std::string tree_file)
15+ : entrypoint(entrypoint), tree_file(tree_file) {}
16+ ConcolicDriver (std::function<void ()> entrypoint)
17+ : entrypoint(entrypoint), tree_file(std::nullopt ) {}
18+ void run ();
19+
20+ private:
21+ Solver solver;
22+ std::function<void ()> entrypoint;
23+ std::optional<std::string> tree_file;
24+ };
25+
26+ class ManagedConcolicCleanup {
27+ const ConcolicDriver &driver;
28+
29+ public:
30+ ManagedConcolicCleanup (const ConcolicDriver &driver) : driver(driver) {}
31+ ~ManagedConcolicCleanup () {
32+ if (driver.tree_file .has_value ())
33+ ExploreTree.dump_graphviz (driver.tree_file .value ());
34+ }
35+ };
36+
37+ inline void ConcolicDriver::run () {
38+ ManagedConcolicCleanup cleanup{*this };
39+ while (true ) {
40+ auto cond = ExploreTree.get_unexplored_conditions ();
41+ ExploreTree.reset_cursor ();
42+
43+ if (!cond.has_value ()) {
44+ std::cout << " No unexplored conditions found, exiting..." << std::endl;
45+ return ;
46+ }
47+ auto new_env = solver.solve (cond.value ());
48+ if (!new_env.has_value ()) {
49+ std::cout << " All unexplored paths are unreachable, exiting..."
50+ << std::endl;
51+ return ;
52+ }
53+ SymEnv.update (std::move (new_env.value ()));
54+ try {
55+ entrypoint ();
56+ std::cout << " Execution finished successfully with symbolic environment:"
57+ << std::endl;
58+ std::cout << SymEnv.to_string () << std::endl;
59+ } catch (...) {
60+ ExploreTree.fillFailedNode ();
61+ std::cout << " Caught runtime error with symbolic environment:"
62+ << std::endl;
63+ std::cout << SymEnv.to_string () << std::endl;
64+ return ;
65+ }
66+ }
67+ }
68+
69+ static std::monostate reset_stacks () {
70+ Stack.reset ();
71+ Frames.reset ();
72+ SymStack.reset ();
73+ SymFrames.reset ();
74+ initRand ();
75+ Memory = Memory_t (1 );
76+ return std::monostate{};
77+ }
78+
79+ static void start_concolic_execution_with (
80+ std::function<std::monostate(std::monostate)> entrypoint,
81+ std::string tree_file) {
82+ ConcolicDriver driver ([=]() { entrypoint (std::monostate{}); }, tree_file);
83+ driver.run ();
84+ }
85+
86+ static void start_concolic_execution_with (
87+ std::function<std::monostate(std::monostate)> entrypoint) {
88+
89+ const char *env_tree_file = std::getenv (" TREE_FILE" );
90+
91+ ConcolicDriver driver =
92+ env_tree_file ? ConcolicDriver ([=]() { entrypoint (std::monostate{}); },
93+ env_tree_file)
94+ : ConcolicDriver ([=]() { entrypoint (std::monostate{}); });
95+ driver.run ();
96+ }
97+
98+ #endif // CONCOLIC_DRIVER_HPP
0 commit comments