about summary refs log tree commit diff homepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/klee/main.cpp142
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",