diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/kleaver/Makefile | 8 | ||||
-rw-r--r-- | tools/kleaver/main.cpp | 79 | ||||
-rw-r--r-- | tools/klee-stats/Makefile | 4 | ||||
-rw-r--r-- | tools/klee/Debug.cpp | 9 | ||||
-rw-r--r-- | tools/klee/Makefile | 8 | ||||
-rw-r--r-- | tools/klee/main.cpp | 310 | ||||
-rw-r--r-- | tools/ktest-tool/Makefile | 4 |
7 files changed, 232 insertions, 190 deletions
diff --git a/tools/kleaver/Makefile b/tools/kleaver/Makefile index b93e361d..656ffeae 100644 --- a/tools/kleaver/Makefile +++ b/tools/kleaver/Makefile @@ -29,5 +29,9 @@ ifeq ($(ENABLE_METASMT),1) -L$(METASMT_ROOT)/../../deps/boost-1_52_0/lib CXX.Flags += -DBOOST_HAS_GCC_TR1 CXX.Flags := $(filter-out -fno-exceptions,$(CXX.Flags)) - LIBS += -lrt -lgomp -lboost_iostreams -lboost_thread -lboost_system -lmetaSMT -lz3 -lboolector -lminisat_core -endif \ No newline at end of file + LIBS += -lgomp -lboost_iostreams -lboost_thread -lboost_system -lmetaSMT -lz3 -lrt -lboolector -lminisat_core +endif + +ifeq ($(STP_NEEDS_BOOST),1) + LIBS += $(UPSTREAM_STP_LINK_FLAGS) +endif diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp index abc37d4b..b19e2ea6 100644 --- a/tools/kleaver/main.cpp +++ b/tools/kleaver/main.cpp @@ -1,5 +1,3 @@ -#include <iostream> - #include "expr/Lexer.h" #include "expr/Parser.h" @@ -124,9 +122,11 @@ static std::string getQueryLogPath(const char filename[]) struct stat s; if( !(stat(directoryToWriteQueryLogs.c_str(),&s) == 0 && S_ISDIR(s.st_mode)) ) { - std::cerr << "Directory to log queries \"" << directoryToWriteQueryLogs << "\" does not exist!" << std::endl; - exit(1); - } + llvm::errs() << "Directory to log queries \"" + << directoryToWriteQueryLogs << "\" does not exist!" + << "\n"; + exit(1); + } //check permissions okay if( !( (s.st_mode & S_IWUSR) && getuid() == s.st_uid) && @@ -134,9 +134,11 @@ static std::string getQueryLogPath(const char filename[]) !( s.st_mode & S_IWOTH) ) { - std::cerr << "Directory to log queries \"" << directoryToWriteQueryLogs << "\" is not writable!" << std::endl; - exit(1); - } + llvm::errs() << "Directory to log queries \"" + << directoryToWriteQueryLogs << "\" is not writable!" + << "\n"; + exit(1); + } std::string path=directoryToWriteQueryLogs; path+="/"; @@ -167,10 +169,9 @@ static void PrintInputTokens(const MemoryBuffer *MB) { Token T; do { L.Lex(T); - std::cout << "(Token \"" << T.getKindName() << "\" " - << "\"" << escapedString(T.start, T.length) << "\" " - << T.length << " " - << T.line << " " << T.column << ")\n"; + llvm::outs() << "(Token \"" << T.getKindName() << "\" " + << "\"" << escapedString(T.start, T.length) << "\" " + << T.length << " " << T.line << " " << T.column << ")\n"; } while (T.kind != Token::EndOfFile); } @@ -185,7 +186,7 @@ static bool PrintInputAST(const char *Filename, while (Decl *D = P->ParseTopLevelDecl()) { if (!P->GetNumErrors()) { if (isa<QueryCommand>(D)) - std::cout << "# Query " << ++NumQueries << "\n"; + llvm::outs() << "# Query " << ++NumQueries << "\n"; D->dump(); } @@ -194,8 +195,7 @@ static bool PrintInputAST(const char *Filename, bool success = true; if (unsigned N = P->GetNumErrors()) { - std::cerr << Filename << ": parse failure: " - << N << " errors.\n"; + llvm::errs() << Filename << ": parse failure: " << N << " errors.\n"; success = false; } @@ -220,8 +220,7 @@ static bool EvaluateInputAST(const char *Filename, bool success = true; if (unsigned N = P->GetNumErrors()) { - std::cerr << Filename << ": parse failure: " - << N << " errors.\n"; + llvm::errs() << Filename << ": parse failure: " << N << " errors.\n"; success = false; } @@ -253,7 +252,7 @@ static bool EvaluateInputAST(const char *Filename, assert(false); break; }; - std::cerr << "Starting MetaSMTSolver(" << backend << ") ...\n"; + llvm::errs() << "Starting MetaSMTSolver(" << backend << ") ...\n"; } else { coreSolver = UseDummySolver ? createDummySolver() : new STPSolver(UseForkedCoreSolver); @@ -280,16 +279,16 @@ static bool EvaluateInputAST(const char *Filename, ie = Decls.end(); it != ie; ++it) { Decl *D = *it; if (QueryCommand *QC = dyn_cast<QueryCommand>(D)) { - std::cout << "Query " << Index << ":\t"; + llvm::outs() << "Query " << Index << ":\t"; assert("FIXME: Support counterexample query commands!"); if (QC->Values.empty() && QC->Objects.empty()) { bool result; if (S->mustBeTrue(Query(ConstraintManager(QC->Constraints), QC->Query), result)) { - std::cout << (result ? "VALID" : "INVALID"); + llvm::outs() << (result ? "VALID" : "INVALID"); } else { - std::cout << "FAIL (reason: " + llvm::outs() << "FAIL (reason: " << SolverImpl::getOperationStatusString(S->impl->getOperationStatusCode()) << ")"; } @@ -304,10 +303,10 @@ static bool EvaluateInputAST(const char *Filename, if (S->getValue(Query(ConstraintManager(QC->Constraints), QC->Values[0]), result)) { - std::cout << "INVALID\n"; - std::cout << "\tExpr 0:\t" << result; + llvm::outs() << "INVALID\n"; + llvm::outs() << "\tExpr 0:\t" << result; } else { - std::cout << "FAIL (reason: " + llvm::outs() << "FAIL (reason: " << SolverImpl::getOperationStatusString(S->impl->getOperationStatusCode()) << ")"; } @@ -317,35 +316,35 @@ static bool EvaluateInputAST(const char *Filename, if (S->getInitialValues(Query(ConstraintManager(QC->Constraints), QC->Query), QC->Objects, result)) { - std::cout << "INVALID\n"; + llvm::outs() << "INVALID\n"; for (unsigned i = 0, e = result.size(); i != e; ++i) { - std::cout << "\tArray " << i << ":\t" + llvm::outs() << "\tArray " << i << ":\t" << QC->Objects[i]->name << "["; for (unsigned j = 0; j != QC->Objects[i]->size; ++j) { - std::cout << (unsigned) result[i][j]; + llvm::outs() << (unsigned) result[i][j]; if (j + 1 != QC->Objects[i]->size) - std::cout << ", "; + llvm::outs() << ", "; } - std::cout << "]"; + llvm::outs() << "]"; if (i + 1 != e) - std::cout << "\n"; + llvm::outs() << "\n"; } } else { SolverImpl::SolverRunStatus retCode = S->impl->getOperationStatusCode(); if (SolverImpl::SOLVER_RUN_STATUS_TIMEOUT == retCode) { - std::cout << " FAIL (reason: " + llvm::outs() << " FAIL (reason: " << SolverImpl::getOperationStatusString(retCode) << ")"; } else { - std::cout << "VALID (counterexample request ignored)"; + llvm::outs() << "VALID (counterexample request ignored)"; } } } - std::cout << "\n"; + llvm::outs() << "\n"; ++Index; } } @@ -358,7 +357,7 @@ static bool EvaluateInputAST(const char *Filename, delete S; if (uint64_t queries = *theStatisticManager->getStatisticByName("Queries")) { - std::cout + llvm::outs() << "--\n" << "total queries = " << queries << "\n" << "total queries constructs = " @@ -390,7 +389,7 @@ static bool printInputAsSMTLIBv2(const char *Filename, bool success = true; if (unsigned N = P->GetNumErrors()) { - std::cerr << Filename << ": parse failure: " + llvm::errs() << Filename << ": parse failure: " << N << " errors.\n"; success = false; } @@ -399,7 +398,7 @@ static bool printInputAsSMTLIBv2(const char *Filename, return false; ExprSMTLIBPrinter* printer = createSMTLIBPrinter(); - printer->setOutput(std::cout); + printer->setOutput(llvm::outs()); unsigned int queryNumber = 0; //Loop over the declarations @@ -409,10 +408,10 @@ static bool printInputAsSMTLIBv2(const char *Filename, if (QueryCommand *QC = dyn_cast<QueryCommand>(D)) { //print line break to separate from previous query - if(queryNumber!=0) std::cout << std::endl; + if(queryNumber!=0) llvm::outs() << "\n"; //Output header for this query as a SMT-LIBv2 comment - std::cout << ";SMTLIBv2 Query " << queryNumber << std::endl; + llvm::outs() << ";SMTLIBv2 Query " << queryNumber << "\n"; /* Can't pass ConstraintManager constructor directly * as argument to Query object. Like... @@ -458,7 +457,7 @@ int main(int argc, char **argv) { OwningPtr<MemoryBuffer> MB; error_code ec=MemoryBuffer::getFileOrSTDIN(InputFile.c_str(), MB); if (ec) { - std::cerr << argv[0] << ": error: " << ec.message() << "\n"; + llvm::errs() << argv[0] << ": error: " << ec.message() << "\n"; return 1; } @@ -494,7 +493,7 @@ int main(int argc, char **argv) { success = printInputAsSMTLIBv2(InputFile=="-"? "<stdin>" : InputFile.c_str(), MB.get(),Builder); break; default: - std::cerr << argv[0] << ": error: Unknown program action!\n"; + llvm::errs() << argv[0] << ": error: Unknown program action!\n"; } delete Builder; diff --git a/tools/klee-stats/Makefile b/tools/klee-stats/Makefile index 0b35fa51..89578b12 100644 --- a/tools/klee-stats/Makefile +++ b/tools/klee-stats/Makefile @@ -11,6 +11,10 @@ LEVEL = ../.. TOOLSCRIPTNAME := klee-stats +# Hack to prevent install trying to strip +# symbols from a python script +KEEP_SYMBOLS := 1 + include $(LEVEL)/Makefile.common # FIXME: Move this stuff (to "build" a script) into Makefile.rules. diff --git a/tools/klee/Debug.cpp b/tools/klee/Debug.cpp index 3d46de03..fbabed9d 100644 --- a/tools/klee/Debug.cpp +++ b/tools/klee/Debug.cpp @@ -1,12 +1,11 @@ #include <klee/Expr.h> -#include <iostream> void kdb_printExpr(klee::Expr *e) { - std::cerr << "expr: " << e << " -- "; + llvm::errs() << "expr: " << e << " -- "; if (e) { - std::cerr << *e; + llvm::errs() << *e; } else { - std::cerr << "(null)"; + llvm::errs() << "(null)"; } - std::cerr << "\n"; + llvm::errs() << "\n"; } diff --git a/tools/klee/Makefile b/tools/klee/Makefile index f050bf74..e526f2a2 100644 --- a/tools/klee/Makefile +++ b/tools/klee/Makefile @@ -30,5 +30,9 @@ ifeq ($(ENABLE_METASMT),1) -L$(METASMT_ROOT)/../../deps/boost-1_52_0/lib CXX.Flags += -DBOOST_HAS_GCC_TR1 CXX.Flags := $(filter-out -fno-exceptions,$(CXX.Flags)) - LIBS += -lrt -lgomp -lboost_iostreams -lboost_thread -lboost_system -lmetaSMT -lz3 -lboolector -lminisat_core -endif \ No newline at end of file + LIBS += -lgomp -lboost_iostreams -lboost_thread -lboost_system -lmetaSMT -lz3 -lrt -lboolector -lminisat_core +endif + +ifeq ($(STP_NEEDS_BOOST),1) + LIBS += $(UPSTREAM_STP_LINK_FLAGS) +endif diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 3616bfa6..aecf6991 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -34,8 +34,10 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" // FIXME: Ugh, this is gross. But otherwise our config.h conflicts with LLVMs. #undef PACKAGE_BUGREPORT @@ -60,7 +62,6 @@ #include <cerrno> #include <fstream> #include <iomanip> -#include <iostream> #include <iterator> #include <sstream> @@ -169,7 +170,7 @@ namespace { cl::opt<bool> ReplayKeepSymbolic("replay-keep-symbolic", - cl::desc("Replay the test cases only by asserting" + cl::desc("Replay the test cases only by asserting " "the bytes, not necessarily making them concrete.")); cl::list<std::string> @@ -195,7 +196,9 @@ namespace { cl::opt<unsigned> MakeConcreteSymbolic("make-concrete-symbolic", - cl::desc("Rate at which to make concrete reads symbolic (0=off)"), + cl::desc("Probabilistic rate at which to make concrete reads symbolic, " + "i.e. approximately 1 in n concrete reads will be made symbolic (0=off, 1=all). " + "Used for testing."), cl::init(0)); cl::opt<unsigned> @@ -217,9 +220,10 @@ class KleeHandler : public InterpreterHandler { private: Interpreter *m_interpreter; TreeStreamWriter *m_pathWriter, *m_symPathWriter; - std::ostream *m_infoFile; + llvm::raw_ostream *m_infoFile; + + SmallString<128> m_outputDirectory; - sys::Path m_outputDirectory; unsigned m_testIndex; // number of tests written so far unsigned m_pathsExplored; // number of paths explored so far @@ -231,7 +235,7 @@ public: KleeHandler(int argc, char **argv); ~KleeHandler(); - std::ostream &getInfoStream() const { return *m_infoFile; } + llvm::raw_ostream &getInfoStream() const { return *m_infoFile; } unsigned getNumTestCases() { return m_testIndex; } unsigned getNumPathsExplored() { return m_pathsExplored; } void incPathsExplored() { m_pathsExplored++; } @@ -243,9 +247,9 @@ public: const char *errorSuffix); std::string getOutputFilename(const std::string &filename); - std::ostream *openOutputFile(const std::string &filename); + llvm::raw_fd_ostream *openOutputFile(const std::string &filename); std::string getTestFilename(const std::string &suffix, unsigned id); - std::ostream *openTestFile(const std::string &suffix, unsigned id); + llvm::raw_fd_ostream *openTestFile(const std::string &suffix, unsigned id); // load a .out file static void loadOutFile(std::string name, @@ -257,6 +261,8 @@ public: static void getOutFiles(std::string path, std::vector<std::string> &results); + + static std::string getRunTimeLibraryPath(const char *argv0); }; KleeHandler::KleeHandler(int argc, char **argv) @@ -270,81 +276,66 @@ KleeHandler::KleeHandler(int argc, char **argv) m_argc(argc), m_argv(argv) { - if (OutputDir=="") { - llvm::sys::Path directory(InputFile); - std::stringstream dirname; - directory.eraseComponent(); - - if (directory.isEmpty()) - directory.set("."); - - for (int i = 0; i< INT_MAX ; i++) { - dirname << "klee-out-"; - dirname << i; + // create output directory (OutputDir or "klee-out-<i>") + bool dir_given = OutputDir != ""; + SmallString<128> directory(dir_given ? OutputDir : InputFile); - m_outputDirectory = llvm::sys::Path(directory); // Copy - if (!m_outputDirectory.appendComponent(dirname.str())) - klee_error("Failed to append \"%s\" to \"%s\"", dirname.str().c_str(), directory.c_str()); - - bool isDir = true; - llvm::error_code e = llvm::sys::fs::exists(m_outputDirectory.str(), isDir); - if ( e != llvm::errc::success ) - klee_error("Failed to check if \"%s\" exists.", m_outputDirectory.str().c_str()); - - if (!isDir) - { - break; // Found an available directory name - } + error_code ec; + if (!dir_given) sys::path::remove_filename(directory); + if ((ec = sys::fs::make_absolute(directory)) != errc::success) + klee_error("unable to determine absolute path: %s", ec.message().c_str()); - // Warn the user if the klee-out-* exists but is not a directory - e = llvm::sys::fs::is_directory(m_outputDirectory.str(), isDir); - if ( e == llvm::errc::success && !isDir ) - klee_warning("A file \"%s\" exists, but it is not a directory", - m_outputDirectory.str().c_str()); + if (dir_given) { + // OutputDir + if (mkdir(directory.c_str(), 0775) < 0) + klee_error("cannot create \"%s\": %s", directory.c_str(), strerror(errno)); - dirname.str(""); // Clear - m_outputDirectory.clear(); - } + m_outputDirectory = directory; + } else { + // "klee-out-<i>" + int i = 0; + for (; i <= INT_MAX; ++i) { + SmallString<128> d(directory); + llvm::sys::path::append(d, "klee-out-"); + raw_svector_ostream ds(d); ds << i; ds.flush(); - if (m_outputDirectory.empty()) - klee_error("Failed to find available output directory in %s", dirname.str().c_str()); + // create directory and try to link klee-last + if (mkdir(d.c_str(), 0775) == 0) { + m_outputDirectory = d; - std::cerr << "KLEE: output directory = \"" << dirname.str() << "\"\n"; + SmallString<128> klee_last(directory); + llvm::sys::path::append(klee_last, "klee-last"); - llvm::sys::Path klee_last(directory); - if(!klee_last.appendComponent("klee-last")) - klee_error("cannot create path name for klee-last"); + if (((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) || + symlink(m_outputDirectory.c_str(), klee_last.c_str()) < 0) { - if ((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) - klee_error("cannot unlink klee-last: %s", strerror(errno)); - - if (symlink(dirname.str().c_str(), klee_last.c_str()) < 0) - klee_error("cannot create klee-last symlink: %s", strerror(errno)); + klee_warning("cannot create klee-last symlink: %s", strerror(errno)); + } - } else { - if (!m_outputDirectory.set(OutputDir)) - klee_error("cannot use klee output directory: %s", OutputDir.c_str()); - } - - if (!sys::path::is_absolute(m_outputDirectory.c_str())) { - sys::Path cwd = sys::Path::GetCurrentDirectory(); - if(!cwd.appendComponent( m_outputDirectory.c_str())) - klee_error("cannot create absolute path name for output directory"); + break; + } - m_outputDirectory = cwd; + // otherwise try again or exit on error + if (errno != EEXIST) + klee_error("cannot create \"%s\": %s", m_outputDirectory.c_str(), strerror(errno)); + } + if (i == INT_MAX && m_outputDirectory.str().equals("")) + klee_error("cannot create output directory: index out of range"); } - if (mkdir(m_outputDirectory.c_str(), 0775) < 0) - klee_error("cannot create directory \"%s\": %s", m_outputDirectory.c_str(), strerror(errno)); + klee_message("output directory is \"%s\"", m_outputDirectory.c_str()); + // open warnings.txt std::string file_path = getOutputFilename("warnings.txt"); if ((klee_warning_file = fopen(file_path.c_str(), "w")) == NULL) klee_error("cannot open file \"%s\": %s", file_path.c_str(), strerror(errno)); + // open messages.txt file_path = getOutputFilename("messages.txt"); if ((klee_message_file = fopen(file_path.c_str(), "w")) == NULL) klee_error("cannot open file \"%s\": %s", file_path.c_str(), strerror(errno)); + // open info m_infoFile = openOutputFile("info"); } @@ -373,24 +364,25 @@ void KleeHandler::setInterpreter(Interpreter *i) { } std::string KleeHandler::getOutputFilename(const std::string &filename) { - sys::Path path(m_outputDirectory); - if(!path.appendComponent(filename)) { - klee_error("cannot create path name for \"%s\"", filename.c_str()); - } - + SmallString<128> path = m_outputDirectory; + sys::path::append(path,filename); return path.str(); } -std::ostream *KleeHandler::openOutputFile(const std::string &filename) { - std::ios::openmode io_mode = std::ios::out | std::ios::trunc - | std::ios::binary; - std::ostream *f; +llvm::raw_fd_ostream *KleeHandler::openOutputFile(const std::string &filename) { + llvm::raw_fd_ostream *f; + std::string Error; std::string path = getOutputFilename(filename); - f = new std::ofstream(path.c_str(), io_mode); - if (!f) { - klee_error("error opening file \"%s\" (out of memory)", filename.c_str()); - } else if (!f->good()) { - klee_error("error opening file \"%s\". KLEE may have run out of file descriptors: try to increase the maximum number of open file descriptors by using ulimit.", filename.c_str()); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3,0) + f = new llvm::raw_fd_ostream(path.c_str(), Error, llvm::sys::fs::F_Binary); +#else + f = new llvm::raw_fd_ostream(path.c_str(), Error, llvm::raw_fd_ostream::F_Binary); +#endif + if (!Error.empty()) { + klee_error("error opening file \"%s\". KLEE may have run out of file " + "descriptors: try to increase the maximum number of open file " + "descriptors by using ulimit (%s).", + filename.c_str(), Error.c_str()); delete f; f = NULL; } @@ -404,7 +396,8 @@ std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id) return filename.str(); } -std::ostream *KleeHandler::openTestFile(const std::string &suffix, unsigned id) { +llvm::raw_fd_ostream *KleeHandler::openTestFile(const std::string &suffix, + unsigned id) { return openOutputFile(getTestFilename(suffix, id)); } @@ -414,7 +407,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, const char *errorMessage, const char *errorSuffix) { if (errorMessage && ExitOnError) { - std::cerr << "EXITING ON ERROR:\n" << errorMessage << "\n"; + llvm::errs() << "EXITING ON ERROR:\n" << errorMessage << "\n"; exit(1); } @@ -457,7 +450,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, } if (errorMessage) { - std::ostream *f = openTestFile(errorSuffix, id); + llvm::raw_ostream *f = openTestFile(errorSuffix, id); *f << errorMessage; delete f; } @@ -466,16 +459,19 @@ void KleeHandler::processTestCase(const ExecutionState &state, std::vector<unsigned char> concreteBranches; m_pathWriter->readStream(m_interpreter->getPathStreamID(state), concreteBranches); - std::ostream *f = openTestFile("path", id); - std::copy(concreteBranches.begin(), concreteBranches.end(), - std::ostream_iterator<unsigned char>(*f, "\n")); + llvm::raw_fd_ostream *f = openTestFile("path", id); + for (std::vector<unsigned char>::iterator I = concreteBranches.begin(), + E = concreteBranches.end(); + I != E; ++I) { + *f << *I << "\n"; + } delete f; } if (errorMessage || WritePCs) { std::string constraints; m_interpreter->getConstraintLog(state, constraints,Interpreter::KQUERY); - std::ostream *f = openTestFile("pc", id); + llvm::raw_ostream *f = openTestFile("pc", id); *f << constraints; delete f; } @@ -483,7 +479,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, if (WriteCVCs) { std::string constraints; m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); - std::ostream *f = openTestFile("cvc", id); + llvm::raw_ostream *f = openTestFile("cvc", id); *f << constraints; delete f; } @@ -491,7 +487,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, if(WriteSMT2s) { std::string constraints; m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); - std::ostream *f = openTestFile("smt2", id); + llvm::raw_ostream *f = openTestFile("smt2", id); *f << constraints; delete f; } @@ -500,16 +496,17 @@ void KleeHandler::processTestCase(const ExecutionState &state, std::vector<unsigned char> symbolicBranches; m_symPathWriter->readStream(m_interpreter->getSymbolicPathStreamID(state), symbolicBranches); - std::ostream *f = openTestFile("sym.path", id); - std::copy(symbolicBranches.begin(), symbolicBranches.end(), - std::ostream_iterator<unsigned char>(*f, "\n")); + llvm::raw_fd_ostream *f = openTestFile("sym.path", id); + for (std::vector<unsigned char>::iterator I = symbolicBranches.begin(), E = symbolicBranches.end(); I!=E; ++I) { + *f << *I << "\n"; + } delete f; } if (WriteCov) { std::map<const std::string*, std::set<unsigned> > cov; m_interpreter->getCoveredLines(state, cov); - std::ostream *f = openTestFile("cov", id); + llvm::raw_ostream *f = openTestFile("cov", id); for (std::map<const std::string*, std::set<unsigned> >::iterator it = cov.begin(), ie = cov.end(); it != ie; ++it) { @@ -526,7 +523,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, if (WriteTestInfo) { double elapsed_time = util::getWallTime() - start_time; - std::ostream *f = openTestFile("info", id); + llvm::raw_ostream *f = openTestFile("info", id); *f << "Time to generate test case: " << elapsed_time << "s\n"; delete f; @@ -552,21 +549,56 @@ void KleeHandler::loadPathFile(std::string name, void KleeHandler::getOutFiles(std::string path, std::vector<std::string> &results) { - llvm::sys::Path p(path); - std::set<llvm::sys::Path> contents; - std::string error; - if (p.getDirectoryContents(contents, &error)) { - std::cerr << "ERROR: unable to read output directory: " << path - << ": " << error << "\n"; - exit(1); - } - for (std::set<llvm::sys::Path>::iterator it = contents.begin(), - ie = contents.end(); it != ie; ++it) { - std::string f = it->str(); + error_code ec; + for (llvm::sys::fs::directory_iterator i(path,ec),e; i!=e && !ec; i.increment(ec)){ + std::string f = (*i).path(); if (f.substr(f.size()-6,f.size()) == ".ktest") { - results.push_back(f); + results.push_back(f); } } + + if (ec) { + llvm::errs() << "ERROR: unable to read output directory: " << path << ": " + << ec.message() << "\n"; + exit(1); + } +} + +std::string KleeHandler::getRunTimeLibraryPath(const char *argv0) { + // Take any function from the execution binary but not main (as not allowed by + // C++ standard) + void *MainExecAddr = (void *)(intptr_t)getRunTimeLibraryPath; + SmallString<128> toolRoot( + #if LLVM_VERSION_CODE >= LLVM_VERSION(3,4) + llvm::sys::fs::getMainExecutable(argv0, MainExecAddr) + #else + llvm::sys::Path::GetMainExecutable(argv0, MainExecAddr).str() + #endif + ); + + // Strip off executable so we have a directory path + llvm::sys::path::remove_filename(toolRoot); + + SmallString<128> libDir; + + if ( strcmp(toolRoot.c_str(), KLEE_INSTALL_BIN_DIR ) == 0) + { + DEBUG_WITH_TYPE("klee_runtime", llvm::dbgs() << + "Using installed KLEE library runtime: "); + libDir = KLEE_INSTALL_LIB_DIR ; + } + else + { + DEBUG_WITH_TYPE("klee_runtime", llvm::dbgs() << + "Using build directory KLEE library runtime :"); + libDir = KLEE_DIR; + llvm::sys::path::append(libDir,RUNTIME_CONFIGURATION); + llvm::sys::path::append(libDir,"lib"); + } + + DEBUG_WITH_TYPE("klee_runtime", llvm::dbgs() << + libDir.c_str() << "\n"); + return libDir.str(); } //===----------------------------------------------------------------------===// @@ -932,11 +964,11 @@ void stop_forking() { static void interrupt_handle() { if (!interrupted && theInterpreter) { - std::cerr << "KLEE: ctrl-c detected, requesting interpreter to halt.\n"; + llvm::errs() << "KLEE: ctrl-c detected, requesting interpreter to halt.\n"; halt_execution(); sys::SetInterruptFunction(interrupt_handle); } else { - std::cerr << "KLEE: ctrl-c detected, exiting.\n"; + llvm::errs() << "KLEE: ctrl-c detected, exiting.\n"; exit(1); } interrupted = true; @@ -977,8 +1009,8 @@ static char *format_tdiff(char *buf, long seconds) return buf; } -#ifndef KLEE_UCLIBC -static llvm::Module *linkWithUclibc(llvm::Module *mainModule) { +#ifndef SUPPORT_KLEE_UCLIBC +static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir) { fprintf(stderr, "error: invalid libc, no uclibc support!\n"); exit(1); return 0; @@ -1000,13 +1032,15 @@ static void replaceOrRenameFunction(llvm::Module *module, } } } +static llvm::Module *linkWithUclibc(llvm::Module *mainModule, StringRef libDir) { + // Ensure that klee-uclibc exists + SmallString<128> uclibcBCA(libDir); + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME); -static llvm::Module *linkWithUclibc(llvm::Module *mainModule) { - // Ensure that KLEE_UCLIBC exists - bool uclibcRootExists=false; - llvm::sys::fs::is_directory(KLEE_UCLIBC, uclibcRootExists); - if (!uclibcRootExists) - klee_error("Cannot link with uclibc. KLEE_UCLIBC (\"" KLEE_UCLIBC "\") is not a directory."); + bool uclibcExists=false; + llvm::sys::fs::exists(uclibcBCA.c_str(), uclibcExists); + if (!uclibcExists) + klee_error("Cannot find klee-uclibc : %s", uclibcBCA.c_str()); Function *f; // force import of __uClibc_main @@ -1065,8 +1099,7 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule) { } } - mainModule = klee::linkWithLibrary(mainModule, - KLEE_UCLIBC "/lib/libc.a"); + mainModule = klee::linkWithLibrary(mainModule, uclibcBCA.c_str()); assert(mainModule && "unable to link with uclibc"); @@ -1119,6 +1152,7 @@ static llvm::Module *linkWithUclibc(llvm::Module *mainModule) { new UnreachableInst(getGlobalContext(), bb); + klee_message("NOTE: Using klee-uclibc : %s", uclibcBCA.c_str()); return mainModule; } #endif @@ -1227,14 +1261,7 @@ int main(int argc, char **argv, char **envp) { return r; } -#if defined(KLEE_LIB_DIR) && defined(USE_KLEE_LIB_DIR) - /* KLEE_LIB_DIR is the lib dir of installed files as opposed to - * where libs in the klee source tree are generated. - */ - llvm::sys::Path LibraryDir(KLEE_LIB_DIR); -#else - llvm::sys::Path LibraryDir(KLEE_DIR "/" RUNTIME_CONFIGURATION "/lib"); -#endif + std::string LibraryDir = KleeHandler::getRunTimeLibraryPath(argv[0]); Interpreter::ModuleOptions Opts(LibraryDir.c_str(), /*Optimize=*/OptimizeModule, /*CheckDivZero=*/CheckDivZero, @@ -1246,11 +1273,11 @@ int main(int argc, char **argv, char **envp) { case KleeLibc: { // FIXME: Find a reasonable solution for this. - llvm::sys::Path Path(Opts.LibraryDir); -#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3) - Path.appendComponent("klee-libc.bc"); + SmallString<128> Path(Opts.LibraryDir); +#if LLVM_VERSION_CODE >= LLVM_VERSION(3,3) + llvm::sys::path::append(Path, "klee-libc.bc"); #else - Path.appendComponent("libklee-libc.bca"); + llvm::sys::path::append(Path, "libklee-libc.bca"); #endif mainModule = klee::linkWithLibrary(mainModule, Path.c_str()); assert(mainModule && "unable to link with klee-libc"); @@ -1258,13 +1285,13 @@ int main(int argc, char **argv, char **envp) { } case UcLibc: - mainModule = linkWithUclibc(mainModule); + mainModule = linkWithUclibc(mainModule, LibraryDir); break; } if (WithPOSIXRuntime) { - llvm::sys::Path Path(Opts.LibraryDir); - Path.appendComponent("libkleeRuntimePOSIX.bca"); + SmallString<128> Path(Opts.LibraryDir); + llvm::sys::path::append(Path, "libkleeRuntimePOSIX.bca"); klee_message("NOTE: Using model: %s", Path.c_str()); mainModule = klee::linkWithLibrary(mainModule, Path.c_str()); assert(mainModule && "unable to link with simple model"); @@ -1274,7 +1301,7 @@ int main(int argc, char **argv, char **envp) { // locale and other data and then calls main. Function *mainFn = mainModule->getFunction("main"); if (!mainFn) { - std::cerr << "'main' function not found in module.\n"; + llvm::errs() << "'main' function not found in module.\n"; return -1; } @@ -1329,8 +1356,8 @@ int main(int argc, char **argv, char **envp) { Interpreter *interpreter = theInterpreter = Interpreter::create(IOpts, handler); handler->setInterpreter(interpreter); - - std::ostream &infoFile = handler->getInfoStream(); + + llvm::raw_ostream &infoFile = handler->getInfoStream(); for (int i=0; i<argc; i++) { infoFile << argv[i] << (i+1<argc ? " ":"\n"); } @@ -1368,7 +1395,7 @@ int main(int argc, char **argv, char **envp) { if (out) { kTests.push_back(out); } else { - std::cerr << "KLEE: unable to open: " << *it << "\n"; + llvm::errs() << "KLEE: unable to open: " << *it << "\n"; } } @@ -1385,8 +1412,9 @@ int main(int argc, char **argv, char **envp) { it != ie; ++it) { KTest *out = *it; interpreter->setReplayOut(out); - std::cerr << "KLEE: replaying: " << *it << " (" << kTest_numBytes(out) << " bytes)" - << " (" << ++i << "/" << outFiles.size() << ")\n"; + llvm::errs() << "KLEE: replaying: " << *it << " (" << kTest_numBytes(out) + << " bytes)" + << " (" << ++i << "/" << outFiles.size() << ")\n"; // XXX should put envp in .ktest ? interpreter->runFunctionAsMain(mainFn, out->numArgs, out->args, pEnvp); if (interrupted) break; @@ -1403,7 +1431,7 @@ int main(int argc, char **argv, char **envp) { it != ie; ++it) { KTest *out = kTest_fromFile(it->c_str()); if (!out) { - std::cerr << "KLEE: unable to open: " << *it << "\n"; + llvm::errs() << "KLEE: unable to open: " << *it << "\n"; exit(1); } seeds.push_back(out); @@ -1418,19 +1446,19 @@ int main(int argc, char **argv, char **envp) { it2 != ie; ++it2) { KTest *out = kTest_fromFile(it2->c_str()); if (!out) { - std::cerr << "KLEE: unable to open: " << *it2 << "\n"; + llvm::errs() << "KLEE: unable to open: " << *it2 << "\n"; exit(1); } seeds.push_back(out); } if (outFiles.empty()) { - std::cerr << "KLEE: seeds directory is empty: " << *it << "\n"; + llvm::errs() << "KLEE: seeds directory is empty: " << *it << "\n"; exit(1); } } if (!seeds.empty()) { - std::cerr << "KLEE: using " << seeds.size() << " seeds\n"; + llvm::errs() << "KLEE: using " << seeds.size() << " seeds\n"; interpreter->useSeeds(&seeds); } if (RunInDir != "") { @@ -1500,7 +1528,7 @@ int main(int argc, char **argv, char **envp) { << handler->getNumPathsExplored() << "\n"; stats << "KLEE: done: generated tests = " << handler->getNumTestCases() << "\n"; - std::cerr << stats.str(); + llvm::errs() << stats.str(); handler->getInfoStream() << stats.str(); BufferPtr.take(); diff --git a/tools/ktest-tool/Makefile b/tools/ktest-tool/Makefile index 69d7324c..580b1f6a 100644 --- a/tools/ktest-tool/Makefile +++ b/tools/ktest-tool/Makefile @@ -11,6 +11,10 @@ LEVEL = ../.. TOOLSCRIPTNAME := ktest-tool +# Hack to prevent install trying to strip +# symbols from a python script +KEEP_SYMBOLS := 1 + include $(LEVEL)/Makefile.common # FIXME: Move this stuff (to "build" a script) into Makefile.rules. |