Skip to content

Commit 307eb86

Browse files
committed
refactor
1 parent 220a92f commit 307eb86

File tree

8 files changed

+161
-138
lines changed

8 files changed

+161
-138
lines changed

.github/workflows/build.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ jobs:
139139
runs-on: macos-latest
140140
env:
141141
BASE: /tmp
142-
LLVM_VERSION: 11
143142
SOLVERS: STP
144143
UCLIBC_VERSION: 0
145144
USE_TCMALLOC: 0

include/klee/Core/Interpreter.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class Interpreter {
9393
bool Simplify;
9494
bool CheckDivZero;
9595
bool CheckOvershift;
96+
bool AnnotateOnlyExternal;
9697
bool WithFPRuntime;
9798
bool WithPOSIXRuntime;
9899

@@ -102,14 +103,16 @@ class Interpreter {
102103
const std::string &_MainNameAfterMock,
103104
const std::string &_AnnotationsFile, bool _Optimize,
104105
bool _Simplify, bool _CheckDivZero, bool _CheckOvershift,
105-
bool _WithFPRuntime, bool _WithPOSIXRuntime)
106+
bool _AnnotateOnlyExternal, bool _WithFPRuntime,
107+
bool _WithPOSIXRuntime)
106108
: LibraryDir(_LibraryDir), EntryPoint(_EntryPoint),
107109
OptSuffix(_OptSuffix), MainCurrentName(_MainCurrentName),
108110
MainNameAfterMock(_MainNameAfterMock),
109111
AnnotationsFile(_AnnotationsFile), Optimize(_Optimize),
110112
Simplify(_Simplify), CheckDivZero(_CheckDivZero),
111-
CheckOvershift(_CheckOvershift), WithFPRuntime(_WithFPRuntime),
112-
WithPOSIXRuntime(_WithPOSIXRuntime) {}
113+
CheckOvershift(_CheckOvershift),
114+
AnnotateOnlyExternal(_AnnotateOnlyExternal),
115+
WithFPRuntime(_WithFPRuntime), WithPOSIXRuntime(_WithPOSIXRuntime) {}
113116
};
114117

115118
enum LogType {
@@ -161,7 +164,8 @@ class Interpreter {
161164
const std::unordered_set<std::string> &mainModuleFunctions,
162165
const std::unordered_set<std::string> &mainModuleGlobals,
163166
std::unique_ptr<InstructionInfoTable> origInfos,
164-
const std::set<std::string> &ignoredExternals) = 0;
167+
const std::set<std::string> &ignoredExternals,
168+
std::vector<std::pair<std::string, std::string>> redefinitions) = 0;
165169

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

include/klee/Core/MockBuilder.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef KLEE_MOCKBUILDER_H
22
#define KLEE_MOCKBUILDER_H
33

4+
#include "klee/Core/Interpreter.h"
45
#include "klee/Module/Annotation.h"
56

67
#include "llvm/IR/IRBuilder.h"
@@ -16,10 +17,15 @@ class MockBuilder {
1617
const llvm::Module *userModule;
1718
std::unique_ptr<llvm::Module> mockModule;
1819
std::unique_ptr<llvm::IRBuilder<>> builder;
19-
std::map<std::string, llvm::Type *> externals;
20-
AnnotationsMap annotations;
2120

22-
const std::string mockEntrypoint, userEntrypoint;
21+
const Interpreter::ModuleOptions &opts;
22+
23+
std::set<std::string> ignoredExternals;
24+
std::vector<std::pair<std::string, std::string>> redefinitions;
25+
26+
InterpreterHandler *interpreterHandler;
27+
28+
AnnotationsMap annotations;
2329

2430
void initMockModule();
2531
void buildMockMain();
@@ -38,14 +44,18 @@ class MockBuilder {
3844
void buildAnnotationForExternalFunctionProperties(
3945
llvm::Function *func, const std::set<Statement::Property> &properties);
4046

47+
std::map<std::string, llvm::FunctionType *> getExternalFunctions();
48+
std::map<std::string, llvm::Type *> getExternalGlobals();
49+
4150
llvm::Value *goByOffset(llvm::Value *value,
4251
const std::vector<std::string> &offset);
4352

4453
public:
45-
MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint,
46-
std::string userEntrypoint,
47-
std::map<std::string, llvm::Type *> externals,
48-
const std::string &annotationsFile);
54+
MockBuilder(const llvm::Module *initModule,
55+
const Interpreter::ModuleOptions &opts,
56+
const std::set<std::string> &ignoredExternals,
57+
std::vector<std::pair<std::string, std::string>> &redefinitions,
58+
InterpreterHandler *interpreterHandler);
4959

5060
std::unique_ptr<llvm::Module> build();
5161
};

lib/Core/Executor.cpp

Lines changed: 16 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -454,9 +454,9 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts,
454454
InterpreterHandler *ih)
455455
: Interpreter(opts), interpreterHandler(ih), searcher(nullptr),
456456
externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0),
457-
pathWriter(0), symPathWriter(0),
458-
specialFunctionHandler(0), timers{time::Span(TimerInterval)},
459-
guidanceKind(opts.Guidance), codeGraphDistance(new CodeGraphDistance()),
457+
pathWriter(0), symPathWriter(0), specialFunctionHandler(0),
458+
timers{time::Span(TimerInterval)}, guidanceKind(opts.Guidance),
459+
codeGraphDistance(new CodeGraphDistance()),
460460
distanceCalculator(new DistanceCalculator(*codeGraphDistance)),
461461
targetCalculator(new TargetCalculator(*codeGraphDistance)),
462462
targetManager(new TargetManager(guidanceKind, *distanceCalculator,
@@ -530,14 +530,15 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts,
530530
}
531531
}
532532

533-
llvm::Module *
534-
Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &userModules,
535-
std::vector<std::unique_ptr<llvm::Module>> &libsModules,
536-
const ModuleOptions &opts,
537-
const std::unordered_set<std::string> &mainModuleFunctions,
538-
const std::unordered_set<std::string> &mainModuleGlobals,
539-
std::unique_ptr<InstructionInfoTable> origInfos,
540-
const std::set<std::string> &ignoredExternals) {
533+
llvm::Module *Executor::setModule(
534+
std::vector<std::unique_ptr<llvm::Module>> &userModules,
535+
std::vector<std::unique_ptr<llvm::Module>> &libsModules,
536+
const ModuleOptions &opts,
537+
const std::unordered_set<std::string> &mainModuleFunctions,
538+
const std::unordered_set<std::string> &mainModuleGlobals,
539+
std::unique_ptr<InstructionInfoTable> origInfos,
540+
const std::set<std::string> &ignoredExternals,
541+
std::vector<std::pair<std::string, std::string>> redefinitions) {
541542
assert(!kmodule && !userModules.empty() &&
542543
"can only register one module"); // XXX gross
543544

@@ -576,25 +577,11 @@ Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &userModules,
576577
kmodule->instrument(opts);
577578
}
578579

579-
if (ExternalCalls == ExternalCallPolicy::All &&
580-
interpreterOpts.MockStrategy != MockStrategy::None) {
581-
// TODO: move this to function
582-
std::map<std::string, llvm::Type *> externals =
583-
getAllExternals(ignoredExternals);
584-
MockBuilder mockBuilder(kmodule->module.get(), opts.MainCurrentName,
585-
opts.MainNameAfterMock, externals,
586-
opts.AnnotationsFile);
580+
if (interpreterOpts.MockStrategy != MockStrategy::None) {
581+
MockBuilder mockBuilder(kmodule->module.get(), opts,
582+
ignoredExternals, redefinitions,
583+
interpreterHandler);
587584
std::unique_ptr<llvm::Module> mockModule = mockBuilder.build();
588-
if (!mockModule) {
589-
klee_error("Unable to generate mocks");
590-
}
591-
// TODO: change this to bc file
592-
std::unique_ptr<llvm::raw_fd_ostream> f(
593-
interpreterHandler->openOutputFile("externals.ll"));
594-
auto mainFn = mockModule->getFunction(opts.MainCurrentName);
595-
mainFn->setName(opts.EntryPoint);
596-
*f << *mockModule;
597-
mainFn->setName(opts.MainCurrentName);
598585

599586
std::vector<std::unique_ptr<llvm::Module>> mockModules;
600587
mockModules.push_back(std::move(mockModule));
@@ -661,37 +648,6 @@ Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &userModules,
661648
return kmodule->module.get();
662649
}
663650

664-
std::map<std::string, llvm::Type *>
665-
Executor::getAllExternals(const std::set<std::string> &ignoredExternals) const {
666-
std::map<std::string, llvm::Type *> externals;
667-
for (const auto &f : kmodule->module->functions()) {
668-
if (f.isDeclaration() && !f.use_empty() &&
669-
!ignoredExternals.count(f.getName().str()))
670-
// NOTE: here we detect all the externals, even linked.
671-
externals.insert(std::make_pair(f.getName(), f.getFunctionType()));
672-
}
673-
674-
for (const auto &global : kmodule->module->globals()) {
675-
if (global.isDeclaration() &&
676-
!ignoredExternals.count(global.getName().str()))
677-
externals.insert(std::make_pair(global.getName(), global.getValueType()));
678-
}
679-
680-
for (const auto &alias : kmodule->module->aliases()) {
681-
auto it = externals.find(alias.getName().str());
682-
if (it != externals.end()) {
683-
externals.erase(it);
684-
}
685-
}
686-
687-
for (const auto &e : externals) {
688-
klee_message("Mocking external %s %s",
689-
e.second->isFunctionTy() ? "function" : "variable",
690-
e.first.c_str());
691-
}
692-
return externals;
693-
}
694-
695651
Executor::~Executor() {
696652
delete typeSystemManager;
697653
delete externalDispatcher;

lib/Core/Executor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,8 @@ class Executor : public Interpreter {
736736
const std::unordered_set<std::string> &mainModuleFunctions,
737737
const std::unordered_set<std::string> &mainModuleGlobals,
738738
std::unique_ptr<InstructionInfoTable> origInfos,
739-
const std::set<std::string> &ignoredExternals) override;
739+
const std::set<std::string> &ignoredExternals,
740+
std::vector<std::pair<std::string, std::string>> redefinitions) override;
740741

741742
void useSeeds(const std::vector<struct KTest *> *seeds) override {
742743
usingSeeds = seeds;

lib/Core/MockBuilder.cpp

Lines changed: 93 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,89 @@
1313

1414
namespace klee {
1515

16-
MockBuilder::MockBuilder(const llvm::Module *initModule,
17-
std::string mockEntrypoint, std::string userEntrypoint,
18-
std::map<std::string, llvm::Type *> externals,
19-
const std::string &annotationsFile)
20-
: userModule(initModule), externals(std::move(externals)),
21-
mockEntrypoint(std::move(mockEntrypoint)),
22-
userEntrypoint(std::move(userEntrypoint)) {
23-
annotations = parseAnnotations(annotationsFile, userModule);
16+
template <typename T>
17+
void inline removeAliases(const llvm::Module *userModule,
18+
std::map<std::string, T *> &externals) {
19+
for (const auto &alias : userModule->aliases()) {
20+
auto it = externals.find(alias.getName().str());
21+
if (it != externals.end()) {
22+
externals.erase(it);
23+
}
24+
}
25+
}
26+
27+
std::map<std::string, llvm::FunctionType *>
28+
MockBuilder::getExternalFunctions() {
29+
std::map<std::string, llvm::FunctionType *> externals;
30+
for (const auto &f : userModule->functions()) {
31+
if (f.isDeclaration() && !f.use_empty() &&
32+
!ignoredExternals.count(f.getName().str())) {
33+
// NOTE: here we detect all the externals, even linked.
34+
externals.insert(std::make_pair(f.getName(), f.getFunctionType()));
35+
}
36+
}
37+
removeAliases(userModule, externals);
38+
39+
for (const auto &e : externals) {
40+
klee_message("Mocking external function %s", e.first.c_str());
41+
}
42+
43+
return externals;
44+
}
45+
46+
std::map<std::string, llvm::Type *> MockBuilder::getExternalGlobals() {
47+
std::map<std::string, llvm::Type *> externals;
48+
for (const auto &global : userModule->globals()) {
49+
if (global.isDeclaration() &&
50+
!ignoredExternals.count(global.getName().str())) {
51+
externals.insert(std::make_pair(global.getName(), global.getValueType()));
52+
}
53+
}
54+
removeAliases(userModule, externals);
55+
56+
for (const auto &e : externals) {
57+
klee_message("Mocking external variable %s", e.first.c_str());
58+
}
59+
60+
return externals;
61+
}
62+
63+
MockBuilder::MockBuilder(
64+
const llvm::Module *initModule, const Interpreter::ModuleOptions &opts,
65+
const std::set<std::string> &ignoredExternals,
66+
std::vector<std::pair<std::string, std::string>> &redefinitions,
67+
InterpreterHandler *interpreterHandler)
68+
: userModule(initModule), opts(opts), ignoredExternals(ignoredExternals),
69+
redefinitions(redefinitions), interpreterHandler(interpreterHandler) {
70+
annotations = parseAnnotations(opts.AnnotationsFile, userModule);
2471
}
2572

2673
std::unique_ptr<llvm::Module> MockBuilder::build() {
2774
initMockModule();
2875
buildMockMain();
2976
buildExternalFunctionsDefinitions();
77+
78+
if (!mockModule) {
79+
klee_error("Unable to generate mocks");
80+
}
81+
82+
{
83+
std::unique_ptr<llvm::raw_fd_ostream> of(
84+
interpreterHandler->openOutputFile("redefinitions.txt"));
85+
for (const auto &i : redefinitions) {
86+
*of << i.first << " " << i.second << "\n";
87+
}
88+
}
89+
90+
{
91+
auto mainFn = mockModule->getFunction(opts.MainCurrentName);
92+
mainFn->setName(opts.EntryPoint);
93+
std::unique_ptr<llvm::raw_fd_ostream> of(
94+
interpreterHandler->openOutputFile("externals.ll"));
95+
*of << *mockModule;
96+
mainFn->setName(opts.MainCurrentName);
97+
}
98+
3099
return std::move(mockModule);
31100
}
32101

@@ -42,17 +111,18 @@ void MockBuilder::initMockModule() {
42111
// Set up entrypoint in new module. Here we'll define external globals and then
43112
// call user's entrypoint.
44113
void MockBuilder::buildMockMain() {
45-
llvm::Function *userMainFn = userModule->getFunction(userEntrypoint);
114+
llvm::Function *userMainFn = userModule->getFunction(opts.MainNameAfterMock);
46115
if (!userMainFn) {
47116
klee_error("Mock: Entry function '%s' not found in module",
48-
userEntrypoint.c_str());
117+
opts.MainNameAfterMock.c_str());
49118
}
50-
mockModule->getOrInsertFunction(mockEntrypoint, userMainFn->getFunctionType(),
119+
mockModule->getOrInsertFunction(opts.MainCurrentName,
120+
userMainFn->getFunctionType(),
51121
userMainFn->getAttributes());
52-
llvm::Function *mockMainFn = mockModule->getFunction(mockEntrypoint);
122+
llvm::Function *mockMainFn = mockModule->getFunction(opts.MainCurrentName);
53123
if (!mockMainFn) {
54124
klee_error("Mock: Entry function '%s' not found in module",
55-
mockEntrypoint.c_str());
125+
opts.MainCurrentName.c_str());
56126
}
57127
auto globalsInitBlock =
58128
llvm::BasicBlock::Create(mockModule->getContext(), "entry", mockMainFn);
@@ -61,7 +131,7 @@ void MockBuilder::buildMockMain() {
61131
buildExternalGlobalsDefinitions();
62132

63133
auto userMainCallee = mockModule->getOrInsertFunction(
64-
userEntrypoint, userMainFn->getFunctionType());
134+
opts.MainNameAfterMock, userMainFn->getFunctionType());
65135
std::vector<llvm::Value *> args;
66136
args.reserve(userMainFn->arg_size());
67137
for (auto it = mockMainFn->arg_begin(); it != mockMainFn->arg_end(); it++) {
@@ -72,12 +142,8 @@ void MockBuilder::buildMockMain() {
72142
}
73143

74144
void MockBuilder::buildExternalGlobalsDefinitions() {
75-
for (const auto &it : externals) {
76-
if (it.second->isFunctionTy()) {
77-
continue;
78-
}
79-
const std::string &extName = it.first;
80-
llvm::Type *type = it.second;
145+
auto externalGlobals = getExternalGlobals();
146+
for (const auto &[extName, type] : externalGlobals) {
81147
mockModule->getOrInsertGlobal(extName, type);
82148
auto *global = mockModule->getGlobalVariable(extName);
83149
if (!global) {
@@ -89,7 +155,7 @@ void MockBuilder::buildExternalGlobalsDefinitions() {
89155
continue;
90156
}
91157

92-
auto *zeroInitializer = llvm::Constant::getNullValue(it.second);
158+
auto *zeroInitializer = llvm::Constant::getNullValue(type);
93159
if (!zeroInitializer) {
94160
klee_error("Mock: Unable to get zero initializer for '%s'",
95161
extName.c_str());
@@ -101,24 +167,19 @@ void MockBuilder::buildExternalGlobalsDefinitions() {
101167
}
102168

103169
void MockBuilder::buildExternalFunctionsDefinitions() {
104-
bool mockAllAnnotation = true;
170+
auto externalFunctions = getExternalFunctions();
105171

106-
if (mockAllAnnotation) {
172+
if (!opts.AnnotateOnlyExternal) {
107173
for (const auto &i : annotations) {
108174
llvm::Function *func = userModule->getFunction(i.first);
109-
auto ext = externals.find(i.first);
110-
if (ext == externals.end()) {
111-
externals[i.first] = func->getType();
175+
auto ext = externalFunctions.find(i.first);
176+
if (ext == externalFunctions.end()) {
177+
externalFunctions[i.first] = func->getFunctionType();
112178
}
113179
}
114180
}
115181

116-
for (const auto &it : externals) {
117-
if (!it.second->isFunctionTy()) {
118-
continue;
119-
}
120-
std::string extName = it.first;
121-
auto *type = llvm::cast<llvm::FunctionType>(it.second);
182+
for (const auto &[extName, type] : externalFunctions) {
122183
mockModule->getOrInsertFunction(extName, type);
123184
llvm::Function *func = mockModule->getFunction(extName);
124185
if (!func) {

0 commit comments

Comments
 (0)