diff options
Diffstat (limited to 'lib/Module')
-rw-r--r-- | lib/Module/IntrinsicCleaner.cpp | 6 | ||||
-rw-r--r-- | lib/Module/ModuleUtil.cpp | 64 |
2 files changed, 51 insertions, 19 deletions
diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp index 030a75ca..cd93b3ec 100644 --- a/lib/Module/IntrinsicCleaner.cpp +++ b/lib/Module/IntrinsicCleaner.cpp @@ -364,7 +364,6 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) { #if LLVM_VERSION_CODE >= LLVM_VERSION(7, 0) case Intrinsic::dbg_label: #endif - case Intrinsic::eh_typeid_for: case Intrinsic::exp2: case Intrinsic::exp: case Intrinsic::expect: @@ -400,6 +399,11 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) { dirty = true; break; + case Intrinsic::eh_typeid_for: { + // Don't lower this, we need it for exception handling + break; + } + // Warn about any unrecognized intrinsics. default: { const Function *Callee = ii->getCalledFunction(); diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index f4cc3048..2316ef45 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -203,41 +203,69 @@ klee::linkModules(std::vector<std::unique_ptr<llvm::Module>> &modules, return nullptr; } - while (true) { + auto containsUsedSymbols = [](const llvm::Module *module) { + GlobalValue *GV = + dyn_cast_or_null<GlobalValue>(module->getNamedValue("llvm.used")); + if (!GV) + return false; + KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Used attribute in " + << module->getModuleIdentifier() + << '\n'); + return true; + }; + + for (auto &module : modules) { + if (!module || !containsUsedSymbols(module.get())) + continue; + if (!linkTwoModules(composite.get(), std::move(module), errorMsg)) { + // Linking failed + errorMsg = "Linking module containing '__attribute__((used))'" + " symbols with composite failed:" + + errorMsg; + return nullptr; + } + module = nullptr; + } + + bool symbolsLinked = true; + while (symbolsLinked) { + symbolsLinked = false; std::set<std::string> undefinedSymbols; GetAllUndefinedSymbols(composite.get(), undefinedSymbols); + auto hasRequiredDefinition = [&undefinedSymbols]( + const llvm::Module *module) { + for (auto symbol : undefinedSymbols) { + GlobalValue *GV = + dyn_cast_or_null<GlobalValue>(module->getNamedValue(symbol)); + if (GV && !GV->isDeclaration()) { + KLEE_DEBUG_WITH_TYPE("klee_linker", + dbgs() << "Found " << GV->getName() << " in " + << module->getModuleIdentifier() << "\n"); + return true; + } + } + return false; + }; // Stop in nothing is undefined if (undefinedSymbols.empty()) break; - bool merged = false; for (auto &module : modules) { if (!module) continue; - for (auto symbol : undefinedSymbols) { - GlobalValue *GV = - dyn_cast_or_null<GlobalValue>(module->getNamedValue(symbol)); - if (!GV || GV->isDeclaration()) - continue; + if (!hasRequiredDefinition(module.get())) + continue; - // Found symbol, therefore merge in module - KLEE_DEBUG_WITH_TYPE("klee_linker", - dbgs() << "Found " << GV->getName() << " in " - << module->getModuleIdentifier() << "\n"); - if (linkTwoModules(composite.get(), std::move(module), errorMsg)) { - module = nullptr; - merged = true; - break; - } + if (!linkTwoModules(composite.get(), std::move(module), errorMsg)) { // Linking failed errorMsg = "Linking archive module with composite failed:" + errorMsg; return nullptr; } + module = nullptr; + symbolsLinked = true; } - if (!merged) - break; } // Condense the module array |