diff options
-rwxr-xr-x | .travis/testing-utils.sh | 6 | ||||
-rw-r--r-- | Dockerfile | 3 | ||||
-rw-r--r-- | include/klee/CommandLine.h | 10 | ||||
-rw-r--r-- | include/klee/Internal/Support/ErrorHandling.h | 6 | ||||
-rw-r--r-- | include/klee/Interpreter.h | 11 | ||||
-rw-r--r-- | lib/Basic/CmdLineOptions.cpp | 13 | ||||
-rw-r--r-- | lib/Basic/ConstructSolverChain.cpp | 102 | ||||
-rw-r--r-- | lib/Module/KModule.cpp | 4 | ||||
-rw-r--r-- | lib/Module/Optimize.cpp | 5 | ||||
-rw-r--r-- | lib/Solver/CoreSolver.cpp | 4 | ||||
-rw-r--r-- | runtime/POSIX/klee_init_env.c | 4 | ||||
-rw-r--r-- | test/regression/2016-08-11-entry-point-internalize-pass.c | 7 | ||||
-rw-r--r-- | test/regression/2016-08-12-empty-file.c | 10 | ||||
-rw-r--r-- | tools/klee/main.cpp | 9 |
14 files changed, 118 insertions, 76 deletions
diff --git a/.travis/testing-utils.sh b/.travis/testing-utils.sh index 27bd420d..b2f608db 100755 --- a/.travis/testing-utils.sh +++ b/.travis/testing-utils.sh @@ -4,9 +4,9 @@ set -e if [ "${LLVM_VERSION}" != "2.9" ]; then # Using LLVM3.4 all we need is vanilla GoogleTest :) - wget https://googletest.googlecode.com/files/gtest-1.7.0.zip - unzip gtest-1.7.0.zip - cd gtest-1.7.0/ + wget https://github.com/google/googletest/archive/release-1.7.0.zip + unzip release-1.7.0.zip + cd googletest-release-1.7.0/ cmake . make # Normally I wouldn't do something like this but hey we're running on a temporary virtual machine, so who cares? diff --git a/Dockerfile b/Dockerfile index ae5312d5..6ee9a9ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -136,4 +136,7 @@ RUN echo 'export PATH=$PATH:'${BUILD_DIR}'/klee/Release+Asserts/bin' >> /home/kl # Link klee to /usr/bin so that it can be used by docker run USER root RUN for exec in ${BUILD_DIR}/klee/Release+Asserts/bin/* ; do ln -s ${exec} /usr/bin/`basename ${exec}`; done + +# Link klee to the libkleeRuntest library needed by docker run +RUN ln -s ${BUILD_DIR}/klee/Release+Asserts/lib/libkleeRuntest.so /usr/lib/libkleeRuntest.so.1.0 USER klee diff --git a/include/klee/CommandLine.h b/include/klee/CommandLine.h index 00cdeebb..dc69de6e 100644 --- a/include/klee/CommandLine.h +++ b/include/klee/CommandLine.h @@ -44,9 +44,17 @@ enum QueryLoggingSolverType */ extern llvm::cl::list<QueryLoggingSolverType> queryLoggingOptions; -enum CoreSolverType { STP_SOLVER, METASMT_SOLVER, DUMMY_SOLVER, Z3_SOLVER }; +enum CoreSolverType { + STP_SOLVER, + METASMT_SOLVER, + DUMMY_SOLVER, + Z3_SOLVER, + NO_SOLVER +}; extern llvm::cl::opt<CoreSolverType> CoreSolverToUse; +extern llvm::cl::opt<CoreSolverType> DebugCrossCheckCoreSolverWith; + #ifdef ENABLE_METASMT enum MetaSMTBackendType diff --git a/include/klee/Internal/Support/ErrorHandling.h b/include/klee/Internal/Support/ErrorHandling.h index 330985e9..29451692 100644 --- a/include/klee/Internal/Support/ErrorHandling.h +++ b/include/klee/Internal/Support/ErrorHandling.h @@ -23,7 +23,7 @@ namespace klee { extern FILE *klee_warning_file; extern FILE *klee_message_file; -/// Print "KLEE: ERROR" followed by the msg in printf format and a +/// Print "KLEE: ERROR: " followed by the msg in printf format and a /// newline on stderr and to warnings.txt, then exit with an error. void klee_error(const char *msg, ...) __attribute__((format(printf, 1, 2), noreturn)); @@ -37,11 +37,11 @@ void klee_message(const char *msg, ...) __attribute__((format(printf, 1, 2))); void klee_message_to_file(const char *msg, ...) __attribute__((format(printf, 1, 2))); -/// Print "KLEE: WARNING" followed by the msg in printf format and a +/// Print "KLEE: WARNING: " followed by the msg in printf format and a /// newline on stderr and to warnings.txt. void klee_warning(const char *msg, ...) __attribute__((format(printf, 1, 2))); -/// Print "KLEE: WARNING" followed by the msg in printf format and a +/// Print "KLEE: WARNING: " followed by the msg in printf format and a /// newline on stderr and to warnings.txt. However, the warning is only /// printed once for each unique (id, msg) pair (as pointers). void klee_warning_once(const void *id, const char *msg, ...) diff --git a/include/klee/Interpreter.h b/include/klee/Interpreter.h index b40ad0d5..3a4d40b4 100644 --- a/include/klee/Interpreter.h +++ b/include/klee/Interpreter.h @@ -51,15 +51,16 @@ public: /// registering a module with the interpreter. struct ModuleOptions { std::string LibraryDir; + std::string EntryPoint; bool Optimize; bool CheckDivZero; bool CheckOvershift; - ModuleOptions(const std::string& _LibraryDir, - bool _Optimize, bool _CheckDivZero, - bool _CheckOvershift) - : LibraryDir(_LibraryDir), Optimize(_Optimize), - CheckDivZero(_CheckDivZero), CheckOvershift(_CheckOvershift) {} + ModuleOptions(const std::string &_LibraryDir, + const std::string &_EntryPoint, bool _Optimize, + bool _CheckDivZero, bool _CheckOvershift) + : LibraryDir(_LibraryDir), EntryPoint(_EntryPoint), Optimize(_Optimize), + CheckDivZero(_CheckDivZero), CheckOvershift(_CheckOvershift) {} }; enum LogType diff --git a/lib/Basic/CmdLineOptions.cpp b/lib/Basic/CmdLineOptions.cpp index 20c190a5..399c27a2 100644 --- a/lib/Basic/CmdLineOptions.cpp +++ b/lib/Basic/CmdLineOptions.cpp @@ -139,6 +139,19 @@ llvm::cl::opt<CoreSolverType> CoreSolverToUse( clEnumValN(Z3_SOLVER, "z3", "Z3" Z3_IS_DEFAULT_STR), clEnumValEnd), llvm::cl::init(DEFAULT_CORE_SOLVER)); + +llvm::cl::opt<CoreSolverType> DebugCrossCheckCoreSolverWith( + "debug-crosscheck-core-solver", + llvm::cl::desc( + "Specifiy a solver to use for cross checking with the core solver"), + llvm::cl::values(clEnumValN(STP_SOLVER, "stp", "stp"), + clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT"), + clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), + clEnumValN(Z3_SOLVER, "z3", "Z3"), + clEnumValN(NO_SOLVER, "none", + "Do not cross check (default)"), + clEnumValEnd), + llvm::cl::init(NO_SOLVER)); } #undef STP_IS_DEFAULT_STR #undef METASMT_IS_DEFAULT_STR diff --git a/lib/Basic/ConstructSolverChain.cpp b/lib/Basic/ConstructSolverChain.cpp index 59790551..2df87d51 100644 --- a/lib/Basic/ConstructSolverChain.cpp +++ b/lib/Basic/ConstructSolverChain.cpp @@ -1,4 +1,4 @@ -//===-- ConstructSolverChain.cpp ------------------------------------------------*- C++ -*-===// +//===-- ConstructSolverChain.cpp ------------------------------------++ -*-===// // // The KLEE Symbolic Virtual Machine // @@ -14,69 +14,59 @@ #include "klee/CommandLine.h" #include "llvm/Support/raw_ostream.h" -namespace klee -{ - Solver *constructSolverChain(Solver *coreSolver, - std::string querySMT2LogPath, - std::string baseSolverQuerySMT2LogPath, - std::string queryPCLogPath, - std::string baseSolverQueryPCLogPath) - { - Solver *solver = coreSolver; +namespace klee { +Solver *constructSolverChain(Solver *coreSolver, std::string querySMT2LogPath, + std::string baseSolverQuerySMT2LogPath, + std::string queryPCLogPath, + std::string baseSolverQueryPCLogPath) { + Solver *solver = coreSolver; - if (optionIsSet(queryLoggingOptions, SOLVER_PC)) - { - solver = createPCLoggingSolver(solver, - baseSolverQueryPCLogPath, - MinQueryTimeToLog); - llvm::errs() << "Logging queries that reach solver in .pc format to " - << baseSolverQueryPCLogPath.c_str() << "\n"; - } + if (optionIsSet(queryLoggingOptions, SOLVER_PC)) { + solver = createPCLoggingSolver(solver, baseSolverQueryPCLogPath, + MinQueryTimeToLog); + llvm::errs() << "Logging queries that reach solver in .pc format to " + << baseSolverQueryPCLogPath.c_str() << "\n"; + } - if (optionIsSet(queryLoggingOptions, SOLVER_SMTLIB)) - { - solver = createSMTLIBLoggingSolver(solver, - baseSolverQuerySMT2LogPath, - MinQueryTimeToLog); - llvm::errs() << "Logging queries that reach solver in .smt2 format to " - << baseSolverQuerySMT2LogPath.c_str() << "\n"; - } + if (optionIsSet(queryLoggingOptions, SOLVER_SMTLIB)) { + solver = createSMTLIBLoggingSolver(solver, baseSolverQuerySMT2LogPath, + MinQueryTimeToLog); + llvm::errs() << "Logging queries that reach solver in .smt2 format to " + << baseSolverQuerySMT2LogPath.c_str() << "\n"; + } - if (UseFastCexSolver) - solver = createFastCexSolver(solver); + if (UseFastCexSolver) + solver = createFastCexSolver(solver); - if (UseCexCache) - solver = createCexCachingSolver(solver); + if (UseCexCache) + solver = createCexCachingSolver(solver); - if (UseCache) - solver = createCachingSolver(solver); + if (UseCache) + solver = createCachingSolver(solver); - if (UseIndependentSolver) - solver = createIndependentSolver(solver); + if (UseIndependentSolver) + solver = createIndependentSolver(solver); - if (DebugValidateSolver) - solver = createValidatingSolver(solver, coreSolver); + if (DebugValidateSolver) + solver = createValidatingSolver(solver, coreSolver); - if (optionIsSet(queryLoggingOptions, ALL_PC)) - { - solver = createPCLoggingSolver(solver, - queryPCLogPath, - MinQueryTimeToLog); - llvm::errs() << "Logging all queries in .pc format to " - << queryPCLogPath.c_str() << "\n"; - } + if (optionIsSet(queryLoggingOptions, ALL_PC)) { + solver = createPCLoggingSolver(solver, queryPCLogPath, MinQueryTimeToLog); + llvm::errs() << "Logging all queries in .pc format to " + << queryPCLogPath.c_str() << "\n"; + } - if (optionIsSet(queryLoggingOptions, ALL_SMTLIB)) - { - solver = createSMTLIBLoggingSolver(solver,querySMT2LogPath, - MinQueryTimeToLog); - llvm::errs() << "Logging all queries in .smt2 format to " - << querySMT2LogPath.c_str() << "\n"; - } - - return solver; - } + if (optionIsSet(queryLoggingOptions, ALL_SMTLIB)) { + solver = + createSMTLIBLoggingSolver(solver, querySMT2LogPath, MinQueryTimeToLog); + llvm::errs() << "Logging all queries in .smt2 format to " + << querySMT2LogPath.c_str() << "\n"; + } + if (DebugCrossCheckCoreSolverWith != NO_SOLVER) { + Solver *oracleSolver = createCoreSolver(DebugCrossCheckCoreSolverWith); + solver = createValidatingSolver(/*s=*/solver, /*oracle=*/oracleSolver); + } + return solver; +} } - - diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 01165e94..57346a31 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -132,7 +132,7 @@ KModule::~KModule() { /***/ namespace llvm { -extern void Optimize(Module*); +extern void Optimize(Module *, const std::string &EntryPoint); } // what a hack @@ -308,7 +308,7 @@ void KModule::prepare(const Interpreter::ModuleOptions &opts, pm.run(*module); if (opts.Optimize) - Optimize(module); + Optimize(module, opts.EntryPoint); #if LLVM_VERSION_CODE < LLVM_VERSION(3, 3) // Force importing functions required by intrinsic lowering. Kind of // unfortunate clutter when we don't need them but we won't know diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index ce43cd96..3d9c8cc1 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -163,7 +163,7 @@ static void AddStandardCompilePasses(PassManager &PM) { /// Optimize - Perform link time optimizations. This will run the scalar /// optimizations, any loaded plugin-optimization modules, and then the /// inter-procedural optimizations if applicable. -void Optimize(Module* M) { +void Optimize(Module *M, const std::string &EntryPoint) { // Instantiate the pass manager to organize the passes. PassManager Passes; @@ -192,7 +192,8 @@ void Optimize(Module* M) { // internal. if (!DisableInternalize) { #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 2) - ModulePass *pass = createInternalizePass(std::vector<const char *>(1, "main")); + ModulePass *pass = createInternalizePass( + std::vector<const char *>(1, EntryPoint.c_str())); #else ModulePass *pass = createInternalizePass(true); #endif diff --git a/lib/Solver/CoreSolver.cpp b/lib/Solver/CoreSolver.cpp index 66328f30..783047f8 100644 --- a/lib/Solver/CoreSolver.cpp +++ b/lib/Solver/CoreSolver.cpp @@ -83,11 +83,15 @@ Solver *createCoreSolver(CoreSolverType cst) { return createDummySolver(); case Z3_SOLVER: #ifdef ENABLE_Z3 + llvm::errs() << "Using Z3 solver backend\n"; return new Z3Solver(); #else llvm::errs() << "Not compiled with Z3 support\n"; return NULL; #endif + case NO_SOLVER: + llvm::errs() << "Invalid solver\n"; + return NULL; default: llvm_unreachable("Unsupported CoreSolverType"); } diff --git a/runtime/POSIX/klee_init_env.c b/runtime/POSIX/klee_init_env.c index 7ac9804c..1fa6adea 100644 --- a/runtime/POSIX/klee_init_env.c +++ b/runtime/POSIX/klee_init_env.c @@ -112,6 +112,10 @@ usage: (klee_init_env) [options] [program arguments]\n\ each with size N\n\ -sym-stdin <N> - Make stdin symbolic with size N.\n\ -sym-stdout - Make stdout symbolic.\n\ + -save-all-writes - Allow write operations to execute as expected\n\ + even if they exceed the file size. If set to 0, all\n\ + writes exceeding the initial file size are discarded.\n\ + Note: file offset is always incremented.\n\ -max-fail <N> - Allow up to N injected failures\n\ -fd-fail - Shortcut for '-max-fail 1'\n\n"); } diff --git a/test/regression/2016-08-11-entry-point-internalize-pass.c b/test/regression/2016-08-11-entry-point-internalize-pass.c new file mode 100644 index 00000000..4cd8ff8d --- /dev/null +++ b/test/regression/2016-08-11-entry-point-internalize-pass.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -emit-llvm -g -O0 -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --entry-point=entry %t.bc + +int entry() { + return 0; +} diff --git a/test/regression/2016-08-12-empty-file.c b/test/regression/2016-08-12-empty-file.c new file mode 100644 index 00000000..b9650278 --- /dev/null +++ b/test/regression/2016-08-12-empty-file.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc %s -emit-llvm -g -O0 -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: not %klee --output-dir=%t.klee-out %t.bc >%t1.log 2>&1 +// RUN: FileCheck -input-file=%t1.log -check-prefix=CHECK-MAIN-NOT-FOUND %s +// RUN: rm -rf %t.klee-out +// RUN: rm -rf %t1.log +// RUN: not %klee --output-dir=%t.klee-out --posix-runtime %t.bc >%t1.log 2>&1 +// RUN: FileCheck -input-file=%t1.log -check-prefix=CHECK-MAIN-NOT-FOUND %s + +// CHECK-MAIN-NOT-FOUND: 'main' function not found in module. diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 3e469a6e..1eab170f 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -669,6 +669,9 @@ static int initEnv(Module *mainModule) { */ Function *mainFn = mainModule->getFunction(EntryPoint); + if (!mainFn) { + klee_error("'%s' function not found in module.", EntryPoint.c_str()); + } if (mainFn->arg_size() < 2) { klee_error("Cannot handle ""--posix-runtime"" when main() has less than two arguments.\n"); @@ -1276,7 +1279,6 @@ int main(int argc, char **argv, char **envp) { } #endif - if (WithPOSIXRuntime) { int r = initEnv(mainModule); if (r != 0) @@ -1284,7 +1286,7 @@ int main(int argc, char **argv, char **envp) { } std::string LibraryDir = KleeHandler::getRunTimeLibraryPath(argv[0]); - Interpreter::ModuleOptions Opts(LibraryDir.c_str(), + Interpreter::ModuleOptions Opts(LibraryDir.c_str(), EntryPoint, /*Optimize=*/OptimizeModule, /*CheckDivZero=*/CheckDivZero, /*CheckOvershift=*/CheckOvershift); @@ -1331,8 +1333,7 @@ int main(int argc, char **argv, char **envp) { // locale and other data and then calls main. Function *mainFn = mainModule->getFunction(EntryPoint); if (!mainFn) { - llvm::errs() << "'" << EntryPoint << "' function not found in module.\n"; - return -1; + klee_error("'%s' function not found in module.", EntryPoint.c_str()); } // FIXME: Change me to std types. |