diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/klee/main.cpp | 142 |
1 files changed, 79 insertions, 63 deletions
diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 0e576415..769be28e 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -30,11 +30,13 @@ #include "llvm/Instructions.h" #if LLVM_VERSION_CODE >= LLVM_VERSION(2, 7) #include "llvm/LLVMContext.h" +#include "llvm/Support/FileSystem.h" #endif #endif #if LLVM_VERSION_CODE < LLVM_VERSION(2, 7) #include "llvm/ModuleProvider.h" #endif +#include "llvm/Support/FileSystem.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" @@ -57,21 +59,21 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/system_error.h" #endif -#include <iostream> -#include <fstream> -#include <cerrno> + #include <dirent.h> +#include <signal.h> #include <unistd.h> -#include <errno.h> #include <sys/stat.h> #include <sys/wait.h> -#include <signal.h> +#include <cerrno> +#include <fstream> +#include <iomanip> #include <iostream> #include <iterator> -#include <fstream> #include <sstream> + using namespace llvm; using namespace klee; @@ -226,7 +228,7 @@ private: TreeStreamWriter *m_pathWriter, *m_symPathWriter; std::ostream *m_infoFile; - char m_outputDirectory[1024]; + sys::Path m_outputDirectory; unsigned m_testIndex; // number of tests written so far unsigned m_pathsExplored; // number of paths explored so far @@ -271,79 +273,86 @@ KleeHandler::KleeHandler(int argc, char **argv) m_pathWriter(0), m_symPathWriter(0), m_infoFile(0), + m_outputDirectory(), m_testIndex(0), m_pathsExplored(0), m_argc(argc), m_argv(argv) { - std::string theDir; if (OutputDir=="") { llvm::sys::Path directory(InputFile); - std::string dirname = ""; + std::stringstream dirname; directory.eraseComponent(); if (directory.isEmpty()) directory.set("."); - for (int i = 0; ; i++) { - char buf[256], tmp[64]; - sprintf(tmp, "klee-out-%d", i); - dirname = tmp; - sprintf(buf, "%s/%s", directory.c_str(), tmp); - theDir = buf; + for (int i = 0; i< INT_MAX ; i++) { + dirname << "klee-out-"; + dirname << i; + + 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()); - if (DIR *dir = opendir(theDir.c_str())) { - closedir(dir); - } else { - break; + 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 } + + // 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()); + + dirname.str(""); // Clear + m_outputDirectory.clear(); } - std::cerr << "KLEE: output directory = \"" << dirname << "\"\n"; + if (m_outputDirectory.empty()) + klee_error("Failed to find available output directory in %s", dirname.str().c_str()); + + std::cerr << "KLEE: output directory = \"" << dirname.str() << "\"\n"; llvm::sys::Path klee_last(directory); - klee_last.appendComponent("klee-last"); - - if ((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) { - perror("Cannot unlink klee-last"); - assert(0 && "exiting."); - } + if(!klee_last.appendComponent("klee-last")) + klee_error("cannot create path name for klee-last"); + + if ((unlink(klee_last.c_str()) < 0) && (errno != ENOENT)) + klee_error("cannot unlink klee-last: %s", strerror(errno)); - if (symlink(dirname.c_str(), klee_last.c_str()) < 0) { - perror("Cannot make symlink"); - assert(0 && "exiting."); - } + if (symlink(dirname.str().c_str(), klee_last.c_str()) < 0) + klee_error("cannot create klee-last symlink: %s", strerror(errno)); + } else { - theDir = OutputDir; + if (!m_outputDirectory.set(OutputDir)) + klee_error("cannot use klee output directory: %s", OutputDir.c_str()); } - sys::Path p(theDir); -#if LLVM_VERSION_CODE < LLVM_VERSION(3, 1) - if (!p.isAbsolute()) { -#else - if (!sys::path::is_absolute(p.c_str())) { -#endif + if (!sys::path::is_absolute(m_outputDirectory.c_str())) { sys::Path cwd = sys::Path::GetCurrentDirectory(); - cwd.appendComponent(theDir); - p = cwd; - } - strcpy(m_outputDirectory, p.c_str()); + if(!cwd.appendComponent( m_outputDirectory.c_str())) + klee_error("cannot create absolute path name for output directory"); - if (mkdir(m_outputDirectory, 0775) < 0) { - std::cerr << "KLEE: ERROR: Unable to make output directory: \"" - << m_outputDirectory - << "\", refusing to overwrite.\n"; - exit(1); + m_outputDirectory = cwd; } - char fname[1024]; - snprintf(fname, sizeof(fname), "%s/warnings.txt", m_outputDirectory); - klee_warning_file = fopen(fname, "w"); - assert(klee_warning_file); + if (mkdir(m_outputDirectory.c_str(), 0775) < 0) + klee_error("cannot create directory \"%s\": %s", m_outputDirectory.c_str(), strerror(errno)); + + 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)); - snprintf(fname, sizeof(fname), "%s/messages.txt", m_outputDirectory); - klee_message_file = fopen(fname, "w"); - assert(klee_message_file); + 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)); m_infoFile = openOutputFile("info"); } @@ -371,9 +380,12 @@ void KleeHandler::setInterpreter(Interpreter *i) { } std::string KleeHandler::getOutputFilename(const std::string &filename) { - char outfile[1024]; - sprintf(outfile, "%s/%s", m_outputDirectory, filename.c_str()); - return outfile; + sys::Path path(m_outputDirectory); + if(!path.appendComponent(filename)) { + klee_error("cannot create path name for \"%s\"", filename.c_str()); + } + + return path.str(); } std::ostream *KleeHandler::openOutputFile(const std::string &filename) { @@ -394,15 +406,13 @@ std::ostream *KleeHandler::openOutputFile(const std::string &filename) { } std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id) { - char filename[1024]; - sprintf(filename, "test%06d.%s", id, suffix.c_str()); - return getOutputFilename(filename); + std::stringstream filename; + filename << "test" << std::setfill('0') << std::setw(6) << id << '.' << suffix; + return filename.str(); } std::ostream *KleeHandler::openTestFile(const std::string &suffix, unsigned id) { - char filename[1024]; - sprintf(filename, "test%06d.%s", id, suffix.c_str()); - return openOutputFile(filename); + return openOutputFile(getTestFilename(suffix, id)); } @@ -444,7 +454,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, std::copy(out[i].second.begin(), out[i].second.end(), o->bytes); } - if (!kTest_toFile(&b, getTestFilename("ktest", id).c_str())) { + if (!kTest_toFile(&b, getOutputFilename(getTestFilename("ktest", id)).c_str())) { klee_warning("unable to write output test case, losing it"); } @@ -1004,6 +1014,12 @@ static void replaceOrRenameFunction(llvm::Module *module, } 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."); + Function *f; // force import of __uClibc_main mainModule->getOrInsertFunction("__uClibc_main", |