diff options
Diffstat (limited to 'lib/Core')
-rw-r--r-- | lib/Core/Context.h | 2 | ||||
-rw-r--r-- | lib/Core/Executor.cpp | 90 | ||||
-rw-r--r-- | lib/Core/Executor.h | 6 | ||||
-rw-r--r-- | lib/Core/SpecialFunctionHandler.cpp | 8 | ||||
-rw-r--r-- | lib/Core/SpecialFunctionHandler.h | 5 | ||||
-rw-r--r-- | lib/Core/StatsTracker.cpp | 13 |
6 files changed, 79 insertions, 45 deletions
diff --git a/lib/Core/Context.h b/lib/Core/Context.h index 6c6eb936..e8b48363 100644 --- a/lib/Core/Context.h +++ b/lib/Core/Context.h @@ -28,7 +28,7 @@ namespace klee { public: Context() {} - + /// initialize - Construct the global Context instance. static void initialize(bool IsLittleEndian, Expr::Width PointerWidth); diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 24fcea88..3d7eb21d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -49,22 +49,22 @@ #include "klee/Internal/System/MemoryUsage.h" #include "klee/SolverStats.h" -#include "llvm/IR/Function.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/IR/DataLayout.h" #include "llvm/IR/TypeBuilder.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" @@ -324,8 +324,8 @@ const char *Executor::TerminateReasonNames[] = { }; Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, - InterpreterHandler *ih) - : Interpreter(opts), kmodule(0), interpreterHandler(ih), searcher(0), + InterpreterHandler *ih) + : Interpreter(opts), interpreterHandler(ih), searcher(0), externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0), pathWriter(0), symPathWriter(0), specialFunctionHandler(0), processTree(0), replayKTest(0), replayPath(0), usingSeeds(0), @@ -393,22 +393,51 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, } } +llvm::Module * +Executor::setModule(std::vector<std::unique_ptr<llvm::Module>> &modules, + const ModuleOptions &opts) { + assert(!kmodule && !modules.empty() && + "can only register one module"); // XXX gross -const Module *Executor::setModule(llvm::Module *module, - const ModuleOptions &opts) { - assert(!kmodule && module && "can only register one module"); // XXX gross - - kmodule = new KModule(module); + kmodule = std::unique_ptr<KModule>(new KModule()); - // Initialize the context. - DataLayout *TD = kmodule->targetData; - Context::initialize(TD->isLittleEndian(), - (Expr::Width) TD->getPointerSizeInBits()); + // Preparing the final module happens in multiple stages + + // Link with KLEE intrinsics library before running any optimizations + SmallString<128> LibPath(opts.LibraryDir); + llvm::sys::path::append(LibPath, "libkleeRuntimeIntrinsic.bca"); + std::string error; + if (!klee::loadFile(LibPath.str(), modules[0]->getContext(), modules, + error)) { + klee_error("Could not load KLEE intrinsic file %s", LibPath.c_str()); + } + // 1.) Link the modules together + while (kmodule->link(modules, opts.EntryPoint)) { + // 2.) Apply different instrumentation + kmodule->instrument(opts); + } + + // 3.) Optimise and prepare for KLEE + + // Create a list of functions that should be preserved if used + std::vector<const char *> preservedFunctions; specialFunctionHandler = new SpecialFunctionHandler(*this); + specialFunctionHandler->prepare(preservedFunctions); + + preservedFunctions.push_back(opts.EntryPoint.c_str()); + + // Preserve the free-standing library calls + preservedFunctions.push_back("memset"); + preservedFunctions.push_back("memcpy"); + preservedFunctions.push_back("memcmp"); + preservedFunctions.push_back("memmove"); + + kmodule->optimiseAndPrepare(opts, preservedFunctions); + + // 4.) Manifest the module + kmodule->manifest(interpreterHandler, StatsTracker::useStatistics()); - specialFunctionHandler->prepare(); - kmodule->prepare(opts, interpreterHandler); specialFunctionHandler->bind(); if (StatsTracker::useStatistics() || userSearcherRequiresMD2U()) { @@ -417,8 +446,13 @@ const Module *Executor::setModule(llvm::Module *module, interpreterHandler->getOutputFilename("assembly.ll"), userSearcherRequiresMD2U()); } - - return module; + + // Initialize the context. + DataLayout *TD = kmodule->targetData.get(); + Context::initialize(TD->isLittleEndian(), + (Expr::Width)TD->getPointerSizeInBits()); + + return kmodule->module.get(); } Executor::~Executor() { @@ -428,7 +462,6 @@ Executor::~Executor() { delete specialFunctionHandler; delete statsTracker; delete solver; - delete kmodule; while(!timers.empty()) { delete timers.back(); timers.pop_back(); @@ -441,7 +474,7 @@ Executor::~Executor() { void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, const Constant *c, unsigned offset) { - DataLayout *targetData = kmodule->targetData; + const auto targetData = kmodule->targetData.get(); if (const ConstantVector *cp = dyn_cast<ConstantVector>(c)) { unsigned elementSize = targetData->getTypeStoreSize(cp->getType()->getElementType()); @@ -501,7 +534,7 @@ MemoryObject * Executor::addExternalObject(ExecutionState &state, extern void *__dso_handle __attribute__ ((__weak__)); void Executor::initializeGlobals(ExecutionState &state) { - Module *m = kmodule->module; + Module *m = kmodule->module.get(); if (m->getModuleInlineAsm() != "") klee_warning("executable has module level assembly (ignoring)"); @@ -1400,9 +1433,8 @@ Function* Executor::getTargetFunction(Value *calledVal, ExecutionState &state) { #endif std::string alias = state.getFnAlias(gv->getName()); if (alias != "") { - llvm::Module* currModule = kmodule->module; GlobalValue *old_gv = gv; - gv = currModule->getNamedValue(alias); + gv = kmodule->module->getNamedValue(alias); if (!gv) { klee_error("Function %s(), alias for %s not found!\n", alias.c_str(), old_gv->getName().str().c_str()); @@ -1738,7 +1770,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Function *f = getTargetFunction(fp, state); // Skip debug intrinsics, we can't evaluate their metadata arguments. - if (f && isDebugIntrinsic(f, kmodule)) + if (f && isDebugIntrinsic(f, kmodule.get())) break; if (isa<InlineAsm>(fp)) { @@ -2595,14 +2627,14 @@ void Executor::bindInstructionConstants(KInstruction *KI) { } void Executor::bindModuleConstants() { - for (std::vector<KFunction*>::iterator it = kmodule->functions.begin(), - ie = kmodule->functions.end(); it != ie; ++it) { - KFunction *kf = *it; + for (auto &kfp : kmodule->functions) { + KFunction *kf = kfp.get(); for (unsigned i=0; i<kf->numInstructions; ++i) bindInstructionConstants(kf->instructions[i]); } - kmodule->constantTable = new Cell[kmodule->constants.size()]; + kmodule->constantTable = + std::unique_ptr<Cell[]>(new Cell[kmodule->constants.size()]); for (unsigned i=0; i<kmodule->constants.size(); ++i) { Cell &c = kmodule->constantTable[i]; c.value = evalConstant(kmodule->constants[i]); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index a0174ab7..6ad5e987 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -120,7 +120,7 @@ private: class TimerInfo; - KModule *kmodule; + std::unique_ptr<KModule> kmodule; InterpreterHandler *interpreterHandler; Searcher *searcher; @@ -491,8 +491,8 @@ public: replayPosition = 0; } - virtual const llvm::Module * - setModule(llvm::Module *module, const ModuleOptions &opts); + llvm::Module *setModule(std::vector<std::unique_ptr<llvm::Module>> &modules, + const ModuleOptions &opts) override; virtual void useSeeds(const std::vector<struct KTest *> *seeds) { usingSeeds = seeds; diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 11a73da3..62526c94 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -169,18 +169,18 @@ int SpecialFunctionHandler::size() { SpecialFunctionHandler::SpecialFunctionHandler(Executor &_executor) : executor(_executor) {} - -void SpecialFunctionHandler::prepare() { +void SpecialFunctionHandler::prepare( + std::vector<const char *> &preservedFunctions) { unsigned N = size(); for (unsigned i=0; i<N; ++i) { HandlerInfo &hi = handlerInfo[i]; Function *f = executor.kmodule->module->getFunction(hi.name); - + // No need to create if the function doesn't exist, since it cannot // be called in that case. - if (f && (!hi.doNotOverride || f->isDeclaration())) { + preservedFunctions.push_back(hi.name); // Make sure NoReturn attribute is set, for optimization and // coverage counting. if (hi.doesNotReturn) diff --git a/lib/Core/SpecialFunctionHandler.h b/lib/Core/SpecialFunctionHandler.h index b11a4974..f99a212f 100644 --- a/lib/Core/SpecialFunctionHandler.h +++ b/lib/Core/SpecialFunctionHandler.h @@ -77,7 +77,10 @@ namespace klee { /// prepared for execution. At the moment this involves deleting /// unused function bodies and marking intrinsics with appropriate /// flags for use in optimizations. - void prepare(); + /// + /// @param preservedFunctions contains all the function names which should + /// be preserved during optimization + void prepare(std::vector<const char *> &preservedFunctions); /// Initialize the internal handler map after the module has been /// prepared for execution. diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index f2a989e2..725cfd56 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -195,7 +195,7 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, "--istats-write-after-instructions cannot be enabled at the same " "time."); - KModule *km = executor.kmodule; + KModule *km = executor.kmodule.get(); if (!sys::path::is_absolute(objectFilename)) { SmallString<128> current(objectFilename); @@ -219,9 +219,8 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, if (OutputIStats) theStatisticManager->useIndexedStats(km->infos->getMaxID()); - for (std::vector<KFunction*>::iterator it = km->functions.begin(), - ie = km->functions.end(); it != ie; ++it) { - KFunction *kf = *it; + for (auto &kfp : km->functions) { + KFunction *kf = kfp.get(); kf->trackCoverage = 1; for (unsigned i=0; i<kf->numInstructions; ++i) { @@ -469,7 +468,7 @@ void StatsTracker::updateStateStatistics(uint64_t addend) { } void StatsTracker::writeIStats() { - Module *m = executor.kmodule->module; + const auto m = executor.kmodule->module.get(); uint64_t istatsMask = 0; llvm::raw_fd_ostream &of = *istatsFile; @@ -666,8 +665,8 @@ uint64_t klee::computeMinDistToUncovered(const KInstruction *ki, } void StatsTracker::computeReachableUncovered() { - KModule *km = executor.kmodule; - Module *m = km->module; + KModule *km = executor.kmodule.get(); + const auto m = km->module.get(); static bool init = true; const InstructionInfoTable &infos = *km->infos; StatisticManager &sm = *theStatisticManager; |