Skip to content

Commit b5b4bf9

Browse files
metametamoonmisonijnikocelaiwo
authored
feat: Add bidirectional mode (#204)
* ci: updated dependencies in ci build and tests * feat: various adt constructions * feat: symbolicSizeConstantAddress memory support * feat: bidirectional execution * feat: lemmas deduction and persistance in bidirectional mode * feat: memory constraints in solvers are supported * feat: added FreezeLower pass --------- Co-authored-by: Aleksandr Misonizhnik <misonijnik@gmail.com> Co-authored-by: Aleksei Babushkin <ocelaiwo@gmail.com>
1 parent 8098ea8 commit b5b4bf9

91 files changed

Lines changed: 6536 additions & 795 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cirrus.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ task:
99
build_script:
1010
- mkdir build
1111
- cd build
12-
- cmake -DLLVM_DIR=/usr/local/llvm13 -DMAKE_BINARY=/usr/local/bin/gmake -DJSON_SRC_DIR=/usr/local -DIMMER_SRC_DIR=/usr/local -DENABLE_TCMALLOC:BOOL=true -DENABLE_POSIX_RUNTIME:BOOL=ON -DENABLE_SOLVER_Z3:BOOL=true -DENABLE_SYSTEM_TESTS:BOOL=ON -DENABLE_WARNINGS_AS_ERRORS=1 -DENABLE_FP_RUNTIME=1 ..
12+
- cmake -DLLVM_DIR=/usr/local/llvm13 -DMAKE_BINARY=/usr/local/bin/gmake -DJSON_SRC_DIR=/usr/local -DIMMER_SRC_DIR=/usr/local -DENABLE_TCMALLOC:BOOL=true -DENABLE_POSIX_RUNTIME:BOOL=ON -DENABLE_SOLVER_Z3:BOOL=true -DENABLE_SYSTEM_TESTS:BOOL=ON -DWARNINGS_AS_ERRORS:BOOL=OFF ..
1313
- gmake
1414
test_script:
1515
- sed -i.bak -e 's/lit\./lit13\./' test/lit.cfg

.github/workflows/build.yaml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ jobs:
156156
env: ${{ matrix.env }}
157157
run: scripts/build/run-tests.sh --run-docker --debug
158158

159+
159160
macOS:
160161
runs-on: macos-latest
161162
env:
@@ -173,11 +174,11 @@ jobs:
173174
- name: Checkout KLEE source code
174175
uses: actions/checkout@v4
175176
- name: Create virtualenv for Python3 (PEP 668)
176-
run: python3 -m venv .venv
177+
run: python3 -m venv .venv
177178
- name: Build KLEE
178-
run: source .venv/bin/activate && echo "$(which tabulate)" && scripts/build/build.sh klee --debug --install-system-deps
179+
run: source .venv/bin/activate && echo "$(which tabulate)" && scripts/build/build.sh klee --debug --install-system-deps
179180
- name: Run tests
180-
run: source .venv/bin/activate && scripts/build/run-tests.sh /tmp/klee_build* --debug
181+
run: source .venv/bin/activate && scripts/build/run-tests.sh /tmp/klee_build* --debug
181182

182183
Docker:
183184
runs-on: ubuntu-latest
@@ -230,8 +231,8 @@ jobs:
230231
clang-format:
231232
runs-on: ubuntu-latest
232233
steps:
233-
- uses: actions/checkout@v3
234-
- uses: actions/setup-python@v4
235-
with:
236-
python-version: 3.x
237-
- uses: pre-commit/action@v3.0.1
234+
- uses: actions/checkout@v3
235+
- uses: actions/setup-python@v4
236+
with:
237+
python-version: 3.x
238+
- uses: pre-commit/action@v3.0.1

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ ENABLE_WARNINGS_AS_ERRORS=0
3939
SOLVERS=BITWUZLA:Z3:STP
4040

4141
## Google Test Required options
42-
GTEST_VERSION=1.11.0
42+
GTEST_VERSION=1.16.0
4343

4444
## json options
4545
JSON_VERSION=v3.11.3

include/klee/ADT/ImmutableList.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ template <typename T> class ImmutableList {
3838
prev = nullptr;
3939
}
4040
}
41+
42+
ImmutableListNode(std::shared_ptr<ImmutableListNode> prev, size_t prev_len,
43+
std::vector<T> values)
44+
: prev(prev), prev_len(prev_len), values(std::move(values)) {}
4145
};
4246

4347
std::shared_ptr<ImmutableListNode> node;
@@ -97,6 +101,26 @@ template <typename T> class ImmutableList {
97101
node->values.push_back(value);
98102
}
99103

104+
void pop_back() {
105+
while (node && node->values.empty()) {
106+
node = node->prev;
107+
}
108+
if (!node) {
109+
return;
110+
}
111+
node = std::make_shared<ImmutableListNode>(node->prev, node->prev_len,
112+
node->values);
113+
node->values.pop_back();
114+
}
115+
116+
T at(size_t index) const {
117+
auto cur = node;
118+
while (cur && cur->prev_len > index) {
119+
cur = cur->prev;
120+
}
121+
return cur->values[index - cur->prev_len];
122+
}
123+
100124
bool empty() const { return size() == 0; }
101125

102126
const T &back() const {
@@ -106,6 +130,55 @@ template <typename T> class ImmutableList {
106130
return *it;
107131
}
108132

133+
const T &front() const { return at(0); }
134+
135+
friend bool operator==(const ImmutableList<T> &lhs,
136+
const ImmutableList<T> &rhs) {
137+
if (lhs.size() != rhs.size()) {
138+
return false;
139+
}
140+
141+
auto li = lhs.begin();
142+
auto ri = rhs.begin();
143+
while (li != lhs.end() && ri != rhs.end()) {
144+
if (*li != *ri) {
145+
return false;
146+
}
147+
++li;
148+
++ri;
149+
}
150+
151+
return true;
152+
}
153+
154+
friend bool operator!=(const ImmutableList<T> &lhs,
155+
const ImmutableList<T> &rhs) {
156+
return !(lhs == rhs);
157+
}
158+
159+
friend bool operator<(const ImmutableList<T> &lhs,
160+
const ImmutableList<T> &rhs) {
161+
if (lhs.size() < rhs.size()) {
162+
return true;
163+
} else if (lhs.size() > rhs.size()) {
164+
return false;
165+
}
166+
167+
auto li = lhs.begin();
168+
auto ri = rhs.begin();
169+
while (li != lhs.end() && ri != rhs.end()) {
170+
if (*li < *ri) {
171+
return true;
172+
} else if (*ri < *li) {
173+
return false;
174+
}
175+
++li;
176+
++ri;
177+
}
178+
179+
return false;
180+
}
181+
109182
ImmutableList() : node(){};
110183
ImmutableList(const ImmutableList<T> &il)
111184
: node(std::make_shared<ImmutableListNode>(il)) {}

include/klee/ADT/Ticker.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// -*- C++ -*-
2+
#ifndef KLEE_TICKER_H
3+
#define KLEE_TICKER_H
4+
5+
#include "klee/Support/ErrorHandling.h"
6+
7+
#include <cassert>
8+
#include <vector>
9+
10+
class Ticker {
11+
std::vector<unsigned> ticks;
12+
unsigned index = 0;
13+
unsigned counter = 0;
14+
15+
public:
16+
Ticker(std::vector<unsigned> ticks) : ticks(ticks) {
17+
bool atLeastOneNonZero = false;
18+
for (auto i : ticks) {
19+
if (i > 0) {
20+
atLeastOneNonZero = true;
21+
}
22+
}
23+
if (!atLeastOneNonZero) {
24+
klee::klee_warning("All ticker entries are 0, using 1 for every entry");
25+
ticks = std::vector<unsigned>(ticks.size(), 1);
26+
}
27+
while (ticks[index] == 0) {
28+
index += 1;
29+
}
30+
}
31+
32+
unsigned getCurrent() {
33+
unsigned current = index;
34+
counter += 1;
35+
if (counter == ticks[index]) {
36+
moveToNext();
37+
}
38+
return current;
39+
}
40+
41+
void moveToNext() {
42+
assert(ticks[index] != 0);
43+
44+
if (counter != 0) {
45+
index = (index + 1) % ticks.size();
46+
counter = 0;
47+
}
48+
49+
while (ticks[index] == 0) {
50+
index = (index + 1) % ticks.size();
51+
}
52+
}
53+
54+
const std::vector<unsigned> &getTicks() { return ticks; }
55+
};
56+
57+
#endif

include/klee/Core/Interpreter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ enum class MockMutableGlobalsPolicy {
8585
All, // Mock globals on module build stage and generate bc module for it
8686
};
8787

88+
enum class ExecutionKind { Forward, Bidirectional };
89+
8890
class Interpreter {
8991
public:
9092
enum class GuidanceKind {

include/klee/Core/TerminationTypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ enum Reason {
9797
MaxForks,
9898
CovCheck,
9999
NoMoreStates,
100+
UnreachedTarget,
100101
ReachedTarget,
101102
ErrorOnWhichShouldExit,
102103
Interrupt,

include/klee/Expr/Constraints.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,23 +117,34 @@ class PathConstraints {
117117
using ordered_constraints_ty =
118118
PersistentMap<Path::PathIndex, constraints_ty, Path::PathIndexCompare>;
119119

120-
void advancePath(KInstruction *ki);
120+
void advancePath(KInstruction *prevPC, KInstruction *pc);
121+
void retractPath();
121122
void advancePath(const Path &path);
122123

124+
ExprHashSet addConstraint(ref<Expr> e, Path::PathIndex currIndex);
123125
ExprHashSet addConstraint(ref<Expr> e);
124126
bool isSymcretized(ref<Expr> expr) const;
125127
void addSymcrete(ref<Symcrete> s);
126128
void rewriteConcretization(const Assignment &a);
127129

130+
const constraints_ty &original() const;
131+
const ExprHashMap<ExprHashSet> &simplificationMap() const;
128132
const ConstraintSet &cs() const;
133+
const ConstraintSet &withAssumptions(const ExprHashSet &assumptions) const;
129134
const Path &path() const;
130135

131-
static PathConstraints concat(const PathConstraints &l,
132-
const PathConstraints &r);
136+
const ordered_constraints_ty &orderedCS() const;
137+
PathConstraints() = default;
138+
PathConstraints(KInstruction *initpc) : _path(initpc) {}
133139

134140
private:
135141
Path _path;
142+
constraints_ty _original;
136143
ConstraintSet constraints;
144+
mutable ConstraintSet tmpConstraints;
145+
ExprHashMap<Path::PathIndex> pathIndexes;
146+
ordered_constraints_ty orderedConstraints;
147+
ExprHashMap<ExprHashSet> _simplificationMap;
137148
unsigned long addingCounter = 0UL;
138149
};
139150

include/klee/Expr/ExprPPrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define KLEE_EXPRPPRINTER_H
1212

1313
#include "klee/Expr/Expr.h"
14+
#include "klee/Expr/Lemma.h"
1415

1516
namespace llvm {
1617
class raw_ostream;
@@ -74,6 +75,8 @@ class ExprPPrinter {
7475
const Array *const *evalArraysBegin = 0,
7576
const Array *const *evalArraysEnd = 0,
7677
bool printArrayDecls = true);
78+
79+
static void printLemma(llvm::raw_ostream &os, const Lemma &l);
7780
};
7881

7982
} // namespace klee

include/klee/Expr/Lemma.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// -*- C++ -*-
2+
#ifndef KLEE_LEMMA_H
3+
#define KLEE_LEMMA_H
4+
5+
#include "klee/Core/Interpreter.h"
6+
#include "klee/Expr/ExprHashMap.h"
7+
#include "klee/Expr/Path.h"
8+
9+
#include <fstream>
10+
#include <memory>
11+
#include <string>
12+
13+
namespace klee {
14+
class KModule;
15+
16+
struct Lemma {
17+
/// @brief Required by klee::ref-managed objects
18+
class ReferenceCounter _refCount;
19+
20+
Path path;
21+
ExprOrderedSet constraints;
22+
23+
Lemma(Path path, ExprOrderedSet constraints)
24+
: path(path), constraints(constraints) {}
25+
26+
bool operator==(const Lemma &other) {
27+
return this->path == other.path && this->constraints == other.constraints;
28+
}
29+
30+
bool operator!=(const Lemma &other) { return !(*this == other); }
31+
32+
ref<Expr> asExpr();
33+
34+
int compare(const Lemma &b) const {
35+
if (path == b.path && constraints == b.constraints) {
36+
return 0;
37+
}
38+
return (path < b.path || (path == b.path && constraints < b.constraints))
39+
? -1
40+
: 1;
41+
}
42+
};
43+
44+
class Summary {
45+
public:
46+
void addLemma(ref<Lemma> lemma);
47+
void dumpToFile(KModule *km);
48+
void readFromFile(KModule *km);
49+
50+
Summary(InterpreterHandler *ih) : ih(ih) {}
51+
52+
private:
53+
std::set<ref<Lemma>> lemmas;
54+
std::set<ref<Lemma>> dumped;
55+
56+
std::string getFilename();
57+
58+
InterpreterHandler *ih;
59+
};
60+
61+
}; // namespace klee
62+
63+
#endif

0 commit comments

Comments
 (0)