From 7e33d5cb292c88ae10f4a0ffa86c498168fbe16a Mon Sep 17 00:00:00 2001 From: Julian Büning Date: Sun, 4 Nov 2018 11:34:10 +0100 Subject: 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. --- lib/Module/CMakeLists.txt | 10 +++- lib/Module/Optimize.cpp | 8 ++++ lib/Module/Passes.h | 12 +++++ lib/Module/WorkaroundLLVMPR39177.cpp | 92 ++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 lib/Module/WorkaroundLLVMPR39177.cpp (limited to 'lib/Module') 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 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(gv); + if (alias == nullptr) + continue; + + // get aliasee function if exists + while (auto *ga = dyn_cast(alias->getAliasee())) { + assert(ga != alias && "alias pointing to itself"); + alias = ga; + } + Function *f = dyn_cast(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 -- cgit 1.4.1