Skip to content

Commit 8999685

Browse files
Lana243ladisgin
authored andcommitted
Add mocks:
- Generation in two modes: naive and determinitic - Mocks are reproducible - Special mocks for allocators: malloc, calloc, realloc
1 parent 479d04f commit 8999685

33 files changed

+961
-48
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ jobs:
139139
runs-on: macos-latest
140140
env:
141141
BASE: /tmp
142+
LLVM_VERSION: 11
142143
SOLVERS: STP
143144
UCLIBC_VERSION: 0
144145
USE_TCMALLOC: 0

include/klee/Core/Interpreter.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class BasicBlock;
3232
class Function;
3333
class LLVMContext;
3434
class Module;
35+
class Type;
3536
class raw_ostream;
3637
class raw_fd_ostream;
3738
} // namespace llvm
@@ -61,6 +62,13 @@ class InterpreterHandler {
6162
const char *suffix, bool isError = false) = 0;
6263
};
6364

65+
enum class MockStrategy {
66+
None, // No mocks are generated
67+
Naive, // For each function call new symbolic value is generated
68+
Deterministic, // Each function is treated as uninterpreted function in SMT.
69+
// Compatible with Z3 solver only
70+
};
71+
6472
class Interpreter {
6573
public:
6674
enum class GuidanceKind {
@@ -77,6 +85,8 @@ class Interpreter {
7785
std::string LibraryDir;
7886
std::string EntryPoint;
7987
std::string OptSuffix;
88+
std::string MainCurrentName;
89+
std::string MainNameAfterMock;
8090
bool Optimize;
8191
bool Simplify;
8292
bool CheckDivZero;
@@ -86,13 +96,16 @@ class Interpreter {
8696

8797
ModuleOptions(const std::string &_LibraryDir,
8898
const std::string &_EntryPoint, const std::string &_OptSuffix,
89-
bool _Optimize, bool _Simplify, bool _CheckDivZero,
90-
bool _CheckOvershift, bool _WithFPRuntime,
91-
bool _WithPOSIXRuntime)
99+
const std::string &_MainCurrentName,
100+
const std::string &_MainNameAfterMock, bool _Optimize,
101+
bool _Simplify, bool _CheckDivZero, bool _CheckOvershift,
102+
bool _WithFPRuntime, bool _WithPOSIXRuntime)
92103
: LibraryDir(_LibraryDir), EntryPoint(_EntryPoint),
93-
OptSuffix(_OptSuffix), Optimize(_Optimize), Simplify(_Simplify),
94-
CheckDivZero(_CheckDivZero), CheckOvershift(_CheckOvershift),
95-
WithFPRuntime(_WithFPRuntime), WithPOSIXRuntime(_WithPOSIXRuntime) {}
104+
OptSuffix(_OptSuffix), MainCurrentName(_MainCurrentName),
105+
MainNameAfterMock(_MainNameAfterMock), Optimize(_Optimize),
106+
Simplify(_Simplify), CheckDivZero(_CheckDivZero),
107+
CheckOvershift(_CheckOvershift), WithFPRuntime(_WithFPRuntime),
108+
WithPOSIXRuntime(_WithPOSIXRuntime) {}
96109
};
97110

98111
enum LogType {
@@ -110,10 +123,11 @@ class Interpreter {
110123
unsigned MakeConcreteSymbolic;
111124
GuidanceKind Guidance;
112125
nonstd::optional<SarifReport> Paths;
126+
enum MockStrategy MockStrategy;
113127

114128
InterpreterOptions(nonstd::optional<SarifReport> Paths)
115129
: MakeConcreteSymbolic(false), Guidance(GuidanceKind::NoGuidance),
116-
Paths(std::move(Paths)) {}
130+
Paths(std::move(Paths)), MockStrategy(MockStrategy::None) {}
117131
};
118132

119133
protected:
@@ -142,7 +156,11 @@ class Interpreter {
142156
const ModuleOptions &opts,
143157
const std::unordered_set<std::string> &mainModuleFunctions,
144158
const std::unordered_set<std::string> &mainModuleGlobals,
145-
std::unique_ptr<InstructionInfoTable> origInfos) = 0;
159+
std::unique_ptr<InstructionInfoTable> origInfos,
160+
const std::set<std::string> &ignoredExternals) = 0;
161+
162+
virtual std::map<std::string, llvm::Type *>
163+
getAllExternals(const std::set<std::string> &ignoredExternals) = 0;
146164

147165
// supply a tree stream writer which the interpreter will use
148166
// to record the concrete path (as a stream of '0' and '1' bytes).

include/klee/Core/MockBuilder.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef KLEE_MOCKBUILDER_H
2+
#define KLEE_MOCKBUILDER_H
3+
4+
#include "llvm/IR/IRBuilder.h"
5+
#include "llvm/IR/Module.h"
6+
7+
#include <set>
8+
#include <string>
9+
10+
namespace klee {
11+
12+
class MockBuilder {
13+
private:
14+
const llvm::Module *userModule;
15+
std::unique_ptr<llvm::Module> mockModule;
16+
std::unique_ptr<llvm::IRBuilder<>> builder;
17+
std::map<std::string, llvm::Type *> externals;
18+
19+
const std::string mockEntrypoint, userEntrypoint;
20+
21+
void initMockModule();
22+
void buildMockMain();
23+
void buildExternalGlobalsDefinitions();
24+
void buildExternalFunctionsDefinitions();
25+
void buildCallKleeMakeSymbol(const std::string &klee_function_name,
26+
llvm::Value *source, llvm::Type *type,
27+
const std::string &symbol_name);
28+
29+
public:
30+
MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint,
31+
std::string userEntrypoint,
32+
std::map<std::string, llvm::Type *> externals);
33+
34+
std::unique_ptr<llvm::Module> build();
35+
};
36+
37+
} // namespace klee
38+
39+
#endif // KLEE_MOCKBUILDER_H

include/klee/Expr/IndependentSet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class IndependentElementSet {
8686
constraints_ty exprs; // All expressions (constraints) that are associated
8787
// with this factor
8888
SymcreteOrderedSet symcretes; // All symcretes associated with this factor
89+
std::set<std::string> uninterpretedFunctions;
8990

9091
IndependentElementSet();
9192
IndependentElementSet(ref<Expr> e);

include/klee/Expr/SourceBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "klee/Expr/SymbolicSource.h"
66
#include "klee/Module/KModule.h"
77

8+
#include "llvm/IR/Function.h"
9+
810
namespace klee {
911

1012
class SourceBuilder {
@@ -28,6 +30,12 @@ class SourceBuilder {
2830
static ref<SymbolicSource> value(const llvm::Value &_allocSite, int _index,
2931
KModule *km);
3032
static ref<SymbolicSource> irreproducible(const std::string &name);
33+
static ref<SymbolicSource> mockNaive(const KModule *kModule,
34+
const llvm::Function &kFunction,
35+
unsigned version);
36+
static ref<SymbolicSource>
37+
mockDeterministic(const KModule *kModule, const llvm::Function &kFunction,
38+
const std::vector<ref<Expr>> &args);
3139
};
3240

3341
}; // namespace klee

include/klee/Expr/SymbolicSource.h

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ DISABLE_WARNING_POP
1717

1818
namespace klee {
1919

20+
class Expr;
2021
class Array;
2122
class Expr;
2223
class ConstantExpr;
2324
class KModule;
25+
struct KFunction;
2426

2527
class SymbolicSource {
2628
protected:
@@ -41,7 +43,9 @@ class SymbolicSource {
4143
LazyInitializationSize,
4244
Instruction,
4345
Argument,
44-
Irreproducible
46+
Irreproducible,
47+
MockNaive,
48+
MockDeterministic
4549
};
4650

4751
public:
@@ -361,6 +365,58 @@ class IrreproducibleSource : public SymbolicSource {
361365
}
362366
};
363367

368+
class MockSource : public SymbolicSource {
369+
public:
370+
const KModule *km;
371+
const llvm::Function &function;
372+
MockSource(const KModule *_km, const llvm::Function &_function)
373+
: km(_km), function(_function) {}
374+
375+
static bool classof(const SymbolicSource *S) {
376+
return S->getKind() == Kind::MockNaive ||
377+
S->getKind() == Kind::MockDeterministic;
378+
}
379+
};
380+
381+
class MockNaiveSource : public MockSource {
382+
public:
383+
const unsigned version;
384+
385+
MockNaiveSource(const KModule *km, const llvm::Function &function,
386+
unsigned _version)
387+
: MockSource(km, function), version(_version) {}
388+
389+
Kind getKind() const override { return Kind::MockNaive; }
390+
std::string getName() const override { return "mockNaive"; }
391+
392+
static bool classof(const SymbolicSource *S) {
393+
return S->getKind() == Kind::MockNaive;
394+
}
395+
396+
unsigned computeHash() override;
397+
398+
int internalCompare(const SymbolicSource &b) const override;
399+
};
400+
401+
class MockDeterministicSource : public MockSource {
402+
public:
403+
const std::vector<ref<Expr>> args;
404+
405+
MockDeterministicSource(const KModule *_km, const llvm::Function &_function,
406+
const std::vector<ref<Expr>> &_args);
407+
408+
Kind getKind() const override { return Kind::MockDeterministic; }
409+
std::string getName() const override { return "mockDeterministic"; }
410+
411+
static bool classof(const SymbolicSource *S) {
412+
return S->getKind() == Kind::MockDeterministic;
413+
}
414+
415+
unsigned computeHash() override;
416+
417+
int internalCompare(const SymbolicSource &b) const override;
418+
};
419+
364420
} // namespace klee
365421

366422
#endif /* KLEE_SYMBOLICSOURCE_H */

include/klee/klee.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,5 +201,6 @@ long double klee_rintl(long double d);
201201
// stdin/stdout
202202
void klee_init_env(int *argcPtr, char ***argvPtr);
203203
void check_stdin_read();
204+
void *__klee_wrapped_malloc(size_t size);
204205

205206
#endif /* KLEE_H */

lib/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ add_library(kleeCore
2222
Memory.cpp
2323
MemoryManager.cpp
2424
PForest.cpp
25+
MockBuilder.cpp
2526
PTree.cpp
2627
Searcher.cpp
2728
SeedInfo.cpp

lib/Core/ExecutionState.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS
2626
#include "llvm/IR/Function.h"
2727
#include "llvm/Support/CommandLine.h"
2828
#include "llvm/Support/raw_ostream.h"
29+
#include "klee/Support/ErrorHandling.h"
2930
DISABLE_WARNING_POP
3031

3132
#include <cassert>

0 commit comments

Comments
 (0)