about summary refs log tree commit diff homepage
path: root/lib/Module
diff options
context:
space:
mode:
authorJulian Büning <julian.buening@rwth-aachen.de>2018-11-04 11:34:10 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2019-03-05 15:15:39 +0000
commit7e33d5cb292c88ae10f4a0ffa86c498168fbe16a (patch)
tree769f3ff2ba656810198fe7a4416058c68f6096f0 /lib/Module
parentd5de3df2c7e481426c39220072b42dfd307a3526 (diff)
downloadklee-7e33d5cb292c88ae10f4a0ffa86c498168fbe16a.tar.gz
workaround for LLVM PR39177
provides a workaround for LLVM bug PR39177, which affects LLVM
versions 3.9 - 7.0.0: https://bugs.llvm.org/show_bug.cgi?id=39177

This commit is intended to be reverted once support for LLVM
versions <= 7 is dropped from KLEE.
Diffstat (limited to 'lib/Module')
-rw-r--r--lib/Module/CMakeLists.txt10
-rw-r--r--lib/Module/Optimize.cpp8
-rw-r--r--lib/Module/Passes.h12
-rw-r--r--lib/Module/WorkaroundLLVMPR39177.cpp92
4 files changed, 121 insertions, 1 deletions
diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt
index 4347b67d..73f003c2 100644
--- a/lib/Module/CMakeLists.txt
+++ b/lib/Module/CMakeLists.txt
@@ -6,7 +6,7 @@
 # License. See LICENSE.TXT for details.
 #
 #===------------------------------------------------------------------------===#
-klee_add_component(kleeModule
+set(KLEE_MODULE_COMPONENT_SRCS
   Checks.cpp
   InstructionInfoTable.cpp
   InstructionOperandTypeCheckPass.cpp
@@ -21,6 +21,14 @@ klee_add_component(kleeModule
   Scalarizer.cpp
 )
 
+if (USE_WORKAROUND_LLVM_PR39177)
+  list(APPEND KLEE_MODULE_COMPONENT_SRCS WorkaroundLLVMPR39177.cpp)
+endif()
+
+klee_add_component(kleeModule
+  ${KLEE_MODULE_COMPONENT_SRCS}
+)
+
 set(LLVM_COMPONENTS
   bitreader
   bitwriter
diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp
index 627921cb..e0a8fc41 100644
--- a/lib/Module/Optimize.cpp
+++ b/lib/Module/Optimize.cpp
@@ -18,6 +18,10 @@
 #include "klee/Config/Version.h"
 #include "klee/Internal/Module/LLVMPassManager.h"
 
+#ifdef USE_WORKAROUND_LLVM_PR39177
+#include "Passes.h"
+#endif
+
 #include "llvm/Analysis/Passes.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/IR/Module.h"
@@ -180,6 +184,10 @@ void Optimize(Module *M, llvm::ArrayRef<const char *> preservedFunctions) {
   if (VerifyEach)
     Passes.add(createVerifierPass());
 
+#ifdef USE_WORKAROUND_LLVM_PR39177
+  addPass(Passes, new klee::WorkaroundLLVMPR39177Pass());
+#endif
+
   // Add an appropriate DataLayout instance for this module...
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 7)
   // LLVM 3.7+ doesn't have DataLayoutPass anymore.
diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h
index 9d39e8f2..417ebe7d 100644
--- a/lib/Module/Passes.h
+++ b/lib/Module/Passes.h
@@ -173,6 +173,18 @@ public:
   bool runOnModule(llvm::Module &M) override;
   bool checkPassed() const { return instructionOperandsConform; }
 };
+
+#ifdef USE_WORKAROUND_LLVM_PR39177
+/// WorkaroundLLVMPR39177Pass - Workaround for LLVM PR39177 within KLEE repo.
+/// For more information on this, please refer to the comments in
+/// cmake/workaround_llvm_pr39177.cmake
+class WorkaroundLLVMPR39177Pass : public llvm::ModulePass {
+public:
+  static char ID;
+  WorkaroundLLVMPR39177Pass() : llvm::ModulePass(ID) {}
+  bool runOnModule(llvm::Module &M) override;
+};
+#endif
 } // namespace klee
 
 #endif
diff --git a/lib/Module/WorkaroundLLVMPR39177.cpp b/lib/Module/WorkaroundLLVMPR39177.cpp
new file mode 100644
index 00000000..23eeb932
--- /dev/null
+++ b/lib/Module/WorkaroundLLVMPR39177.cpp
@@ -0,0 +1,92 @@
+//===-- WorkaroundLLVMPR39177.cpp -------------------------------*- C++ -*-===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// This pass provides a workaround for LLVM bug PR39177 within the KLEE repo.
+// For more information on this, please refer to the comments in
+// cmake/workaround_llvm_pr39177.cmake
+
+#include "Passes.h"
+#include "klee/Internal/Support/ErrorHandling.h"
+
+#include "llvm/Transforms/Utils/Cloning.h"
+
+using namespace llvm;
+
+namespace klee {
+
+bool WorkaroundLLVMPR39177Pass::runOnModule(Module &M) {
+  bool modified = false;
+
+  const char *libfunctions[] = {
+    "strlen",
+    "strchr",
+    "strncmp",
+    "strcpy",
+    "strncpy",
+    "__memcpy_chk",
+    "memchr",
+    "memcmp",
+    "putchar",
+    "puts",
+    "fputc",
+    "fputc_unlocked",
+    "fputs",
+    "fputs_unlocked",
+    "fwrite",
+    "malloc",
+    "calloc",
+    "fwrite_unlocked",
+    "fgetc_unlocked",
+    "fgets_unlocked",
+    "fread_unlocked",
+    "memset_pattern16",
+    "fopen"
+  };
+
+  for (auto *funcname : libfunctions) {
+    if (M.getFunction(funcname) != nullptr)
+      continue;
+
+    GlobalValue *gv = M.getNamedValue(funcname);
+    auto *alias = dyn_cast_or_null<GlobalAlias>(gv);
+    if (alias == nullptr)
+      continue;
+
+    // get aliasee function if exists
+    while (auto *ga = dyn_cast<GlobalAlias>(alias->getAliasee())) {
+      assert(ga != alias && "alias pointing to itself");
+      alias = ga;
+    }
+    Function *f = dyn_cast<Function>(alias->getAliasee());
+    if (f == nullptr)
+      continue;
+
+    std::string aliasName = alias->getName().str();
+
+    // clone function
+    ValueToValueMapTy VMap;
+    Function *g = CloneFunction(f, VMap);
+
+    // replace alias with cloned function
+    alias->replaceAllUsesWith(g);
+    g->takeName(alias);
+    alias->eraseFromParent();
+
+    klee_message(
+        "WorkaroundLLVMPR39177: replaced alias @%s with clone of function @%s",
+        aliasName.c_str(), f->getName().str().c_str());
+    modified = true;
+  }
+
+  return modified;
+}
+
+char WorkaroundLLVMPR39177Pass::ID = 0;
+
+} // namespace klee