Skip to content

Commit 9a8d4f9

Browse files
committed
add xml annotation support
1 parent cd62c3a commit 9a8d4f9

15 files changed

Lines changed: 247 additions & 97 deletions

File tree

.gitmodules

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
[submodule "json"]
2-
path = json
2+
path = submodules/json
33
url = https://github.com/nlohmann/json.git
44
[submodule "optional"]
5-
path = optional
5+
path = submodules/optional
66
url = https://github.com/martinmoene/optional-lite.git
7+
[submodule "submodules/pugixml"]
8+
path = submodules/pugixml
9+
url = https://github.com/zeux/pugixml.git

CMakeLists.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,19 @@ configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/CompileTimeInfo.h.cmin
657657
################################################################################
658658
include_directories("${CMAKE_BINARY_DIR}/include")
659659
include_directories("${CMAKE_SOURCE_DIR}/include")
660-
include_directories("${CMAKE_SOURCE_DIR}/json/include")
661-
include_directories("${CMAKE_SOURCE_DIR}/optional/include")
660+
include_directories("${CMAKE_SOURCE_DIR}/submodules/json/include")
661+
include_directories("${CMAKE_SOURCE_DIR}/submodules/optional/include")
662+
663+
664+
option(ENABLE_XML_ANNOTATION "Enable XML annotation" ON)
665+
666+
if (ENABLE_XML_ANNOTATION)
667+
message(STATUS "XML annotation is enabled")
668+
include_directories("${CMAKE_SOURCE_DIR}/submodules/pugixml/src")
669+
else()
670+
message(STATUS "XML annotation is disabled")
671+
set(ENABLE_XML_ANNOTATION 0)
672+
endif()
662673
# set(KLEE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include)
663674

664675
################################################################################

include/klee/Config/config.h.cmin

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,7 @@ macro for that. That would simplify the C++ code. */
119119
/* Install directory for KLEE runtime */
120120
#define KLEE_INSTALL_RUNTIME_DIR "@KLEE_INSTALL_RUNTIME_DIR@"
121121

122+
/* Enable XML annotation parser */
123+
#define ENABLE_XML_ANNOTATION "@ENABLE_XML_ANNOTATION@"
124+
122125
#endif /* KLEE_CONFIG_H */

include/klee/Core/Interpreter.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ class Interpreter {
8888
std::string OptSuffix;
8989
std::string MainCurrentName;
9090
std::string MainNameAfterMock;
91+
std::string AnnotationsFile;
9192
bool Optimize;
9293
bool Simplify;
9394
bool CheckDivZero;
@@ -98,12 +99,14 @@ class Interpreter {
9899
ModuleOptions(const std::string &_LibraryDir,
99100
const std::string &_EntryPoint, const std::string &_OptSuffix,
100101
const std::string &_MainCurrentName,
101-
const std::string &_MainNameAfterMock, bool _Optimize,
102+
const std::string &_MainNameAfterMock,
103+
const std::string &_AnnotationsFile, bool _Optimize,
102104
bool _Simplify, bool _CheckDivZero, bool _CheckOvershift,
103105
bool _WithFPRuntime, bool _WithPOSIXRuntime)
104106
: LibraryDir(_LibraryDir), EntryPoint(_EntryPoint),
105107
OptSuffix(_OptSuffix), MainCurrentName(_MainCurrentName),
106-
MainNameAfterMock(_MainNameAfterMock), Optimize(_Optimize),
108+
MainNameAfterMock(_MainNameAfterMock),
109+
AnnotationsFile(_AnnotationsFile), Optimize(_Optimize),
107110
Simplify(_Simplify), CheckDivZero(_CheckDivZero),
108111
CheckOvershift(_CheckOvershift), WithFPRuntime(_WithFPRuntime),
109112
WithPOSIXRuntime(_WithPOSIXRuntime) {}
@@ -158,11 +161,7 @@ class Interpreter {
158161
const std::unordered_set<std::string> &mainModuleFunctions,
159162
const std::unordered_set<std::string> &mainModuleGlobals,
160163
std::unique_ptr<InstructionInfoTable> origInfos,
161-
const std::set<std::string> &ignoredExternals,
162-
const AnnotationsMap &annotations) = 0;
163-
164-
virtual std::map<std::string, llvm::Type *>
165-
getAllExternals(const std::set<std::string> &ignoredExternals) = 0;
164+
const std::set<std::string> &ignoredExternals) = 0;
166165

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

include/klee/Core/MockBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class MockBuilder {
4545
MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint,
4646
std::string userEntrypoint,
4747
std::map<std::string, llvm::Type *> externals,
48-
AnnotationsMap annotations);
48+
const std::string &annotationsFile);
4949

5050
std::unique_ptr<llvm::Module> build();
5151
};

include/klee/Module/Annotation.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
#include "nlohmann/json.hpp"
1010
#include "nonstd/optional.hpp"
1111

12+
#include "klee/Config/config.h"
13+
14+
#include "llvm/IR/Module.h"
15+
1216
using nonstd::nullopt;
1317
using nonstd::optional;
1418
using json = nlohmann::json;
@@ -37,11 +41,11 @@ struct Unknown {
3741
virtual bool operator==(const Unknown &other) const;
3842
[[nodiscard]] virtual Kind getKind() const;
3943

40-
std::string statementStr;
44+
std::string str;
4145
std::vector<std::string> offset;
4246

4347
private:
44-
void parseOffset(const std::string &str);
48+
void initOffset();
4549
};
4650

4751
struct Deref final : public Unknown {
@@ -69,16 +73,11 @@ struct Annotation {
6973
std::vector<Statement::Ptr> returnStatements;
7074
std::vector<std::vector<Statement::Ptr>> argsStatements;
7175
std::set<Statement::Property> properties;
72-
73-
static void printWarrning(const std::string &message,
74-
const std::string &functionName);
7576
};
7677

7778
using AnnotationsMap = std::map<std::string, Annotation>;
7879

79-
AnnotationsMap parseAnnotationsPath(const std::string &path);
80-
AnnotationsMap parseAnnotationsJson(const json &annotationsJson);
81-
80+
AnnotationsMap parseAnnotations(const std::string &path, const llvm::Module *m);
8281
} // namespace klee
8382

8483
#endif // KLEE_ANNOTATION_H

lib/Core/Executor.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,7 @@ Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &userModules,
537537
const std::unordered_set<std::string> &mainModuleFunctions,
538538
const std::unordered_set<std::string> &mainModuleGlobals,
539539
std::unique_ptr<InstructionInfoTable> origInfos,
540-
const std::set<std::string> &ignoredExternals,
541-
const AnnotationsMap &annotations) {
540+
const std::set<std::string> &ignoredExternals) {
542541
assert(!kmodule && !userModules.empty() &&
543542
"can only register one module"); // XXX gross
544543

@@ -583,7 +582,7 @@ Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &userModules,
583582
std::map<std::string, llvm::Type *> externals =
584583
getAllExternals(ignoredExternals);
585584
MockBuilder builder(kmodule->module.get(), opts.MainCurrentName,
586-
opts.MainNameAfterMock, externals, annotations);
585+
opts.MainNameAfterMock, externals, opts.AnnotationsFile);
587586
std::unique_ptr<llvm::Module> mockModule = builder.build();
588587
if (!mockModule) {
589588
klee_error("Unable to generate mocks");
@@ -662,7 +661,7 @@ Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &userModules,
662661
}
663662

664663
std::map<std::string, llvm::Type *>
665-
Executor::getAllExternals(const std::set<std::string> &ignoredExternals) {
664+
Executor::getAllExternals(const std::set<std::string> &ignoredExternals) const {
666665
std::map<std::string, llvm::Type *> externals;
667666
for (const auto &f : kmodule->module->functions()) {
668667
if (f.isDeclaration() && !f.use_empty() &&

lib/Core/Executor.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ class Executor : public Interpreter {
421421
KType *type, const ref<SymbolicSource> source,
422422
bool isLocal);
423423

424-
// void executeMakeMock(ExecutionState &state, KInstruction *target,
425-
// std::vector<ref<Expr>> &arguments);
424+
// void executeMakeMock(ExecutionState &state, KInstruction *target,
425+
// std::vector<ref<Expr>> &arguments);
426426

427427
void updateStateWithSymcretes(ExecutionState &state,
428428
const Assignment &assignment);
@@ -699,6 +699,9 @@ class Executor : public Interpreter {
699699
const KBlock *getKBlock(const llvm::BasicBlock *bb) const;
700700
const KFunction *getKFunction(const llvm::Function *f) const;
701701

702+
std::map<std::string, llvm::Type *>
703+
getAllExternals(const std::set<std::string> &ignoredExternals) const;
704+
702705
public:
703706
Executor(llvm::LLVMContext &ctx, const InterpreterOptions &opts,
704707
InterpreterHandler *ie);
@@ -733,11 +736,7 @@ class Executor : public Interpreter {
733736
const std::unordered_set<std::string> &mainModuleFunctions,
734737
const std::unordered_set<std::string> &mainModuleGlobals,
735738
std::unique_ptr<InstructionInfoTable> origInfos,
736-
const std::set<std::string> &ignoredExternals,
737-
const AnnotationsMap &annotations) override;
738-
739-
std::map<std::string, llvm::Type *>
740-
getAllExternals(const std::set<std::string> &ignoredExternals) override;
739+
const std::set<std::string> &ignoredExternals) override;
741740

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

lib/Core/MockBuilder.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ namespace klee {
1414
MockBuilder::MockBuilder(const llvm::Module *initModule,
1515
std::string mockEntrypoint, std::string userEntrypoint,
1616
std::map<std::string, llvm::Type *> externals,
17-
AnnotationsMap annotations)
17+
const std::string &annotationsFile)
1818
: userModule(initModule), externals(std::move(externals)),
19-
annotations(std::move(annotations)),
2019
mockEntrypoint(std::move(mockEntrypoint)),
21-
userEntrypoint(std::move(userEntrypoint)) {}
20+
userEntrypoint(std::move(userEntrypoint)) {
21+
annotations = parseAnnotations(annotationsFile, userModule);
22+
}
2223

2324
std::unique_ptr<llvm::Module> MockBuilder::build() {
2425
initMockModule();
@@ -41,14 +42,14 @@ void MockBuilder::initMockModule() {
4142
void MockBuilder::buildMockMain() {
4243
llvm::Function *userMainFn = userModule->getFunction(userEntrypoint);
4344
if (!userMainFn) {
44-
klee_error("Entry function '%s' not found in module.",
45+
klee_error("Mock: Entry function '%s' not found in module",
4546
userEntrypoint.c_str());
4647
}
4748
mockModule->getOrInsertFunction(mockEntrypoint, userMainFn->getFunctionType(),
4849
userMainFn->getAttributes());
4950
llvm::Function *mockMainFn = mockModule->getFunction(mockEntrypoint);
5051
if (!mockMainFn) {
51-
klee_error("Entry function '%s' not found in module.",
52+
klee_error("Mock: Entry function '%s' not found in module",
5253
mockEntrypoint.c_str());
5354
}
5455
auto globalsInitBlock =
@@ -78,7 +79,7 @@ void MockBuilder::buildExternalGlobalsDefinitions() {
7879
mockModule->getOrInsertGlobal(extName, type);
7980
auto *global = mockModule->getGlobalVariable(extName);
8081
if (!global) {
81-
klee_error("Unable to add global variable '%s' to module",
82+
klee_error("Mock: Unable to add global variable '%s' to module",
8283
extName.c_str());
8384
}
8485
global->setLinkage(llvm::GlobalValue::ExternalLinkage);
@@ -88,14 +89,16 @@ void MockBuilder::buildExternalGlobalsDefinitions() {
8889

8990
auto *zeroInitializer = llvm::Constant::getNullValue(it.second);
9091
if (!zeroInitializer) {
91-
klee_error("Unable to get zero initializer for '%s'", extName.c_str());
92+
klee_error("Mock: Unable to get zero initializer for '%s'",
93+
extName.c_str());
9294
}
9395
global->setInitializer(zeroInitializer);
9496
buildCallKleeMakeSymbolic("klee_make_symbolic", global, type,
9597
"external_" + extName);
9698
}
9799
}
98100

101+
// TODO: discuss should we annotate not external function
99102
void MockBuilder::buildExternalFunctionsDefinitions() {
100103
for (const auto &it : externals) {
101104
if (!it.second->isFunctionTy()) {
@@ -106,7 +109,8 @@ void MockBuilder::buildExternalFunctionsDefinitions() {
106109
mockModule->getOrInsertFunction(extName, type);
107110
llvm::Function *func = mockModule->getFunction(extName);
108111
if (!func) {
109-
klee_error("Unable to find function '%s' in module", extName.c_str());
112+
klee_error("Mock: Unable to find function '%s' in module",
113+
extName.c_str());
110114
}
111115
if (!func->empty()) {
112116
continue;
@@ -322,7 +326,7 @@ void MockBuilder::buildAnnotationForExternalFunctionReturn(
322326
switch (statement->getKind()) {
323327
case Statement::Kind::Deref:
324328
klee_warning("Annotation: unused Deref for return function \"%s\"",
325-
func->getName());
329+
func->getName().str().c_str());
326330
break;
327331
case Statement::Kind::InitNull: {
328332
if (!returnType->isPointerTy()) {

0 commit comments

Comments
 (0)