1 //===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "OrcTestCommon.h" 11 #include "llvm/ExecutionEngine/ExecutionEngine.h" 12 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 13 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 14 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" 15 #include "llvm/ExecutionEngine/Orc/Legacy.h" 16 #include "llvm/ExecutionEngine/Orc/NullResolver.h" 17 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 18 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 19 #include "llvm/IR/Constants.h" 20 #include "llvm/IR/LLVMContext.h" 21 #include "gtest/gtest.h" 22 23 using namespace llvm; 24 using namespace llvm::orc; 25 26 namespace { 27 28 class RTDyldObjectLinkingLayerExecutionTest : public testing::Test, 29 public OrcExecutionTest {}; 30 31 // Adds an object with a debug section to RuntimeDyld and then returns whether 32 // the debug section was passed to the memory manager. 33 static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, 34 bool ProcessAllSections) { 35 class MemoryManagerWrapper : public SectionMemoryManager { 36 public: 37 MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {} 38 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 39 unsigned SectionID, StringRef SectionName, 40 bool IsReadOnly) override { 41 if (SectionName == ".debug_str") 42 DebugSeen = true; 43 return SectionMemoryManager::allocateDataSection( 44 Size, Alignment, SectionID, SectionName, IsReadOnly); 45 } 46 47 private: 48 bool &DebugSeen; 49 }; 50 51 bool DebugSectionSeen = false; 52 53 ExecutionSession ES; 54 auto &JD = ES.createJITDylib("main"); 55 auto Foo = ES.intern("foo"); 56 57 RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() { 58 return llvm::make_unique<MemoryManagerWrapper>(DebugSectionSeen); 59 }); 60 61 auto OnResolveDoNothing = [](Expected<SymbolMap> R) { 62 cantFail(std::move(R)); 63 }; 64 65 auto OnReadyDoNothing = [](Error Err) { cantFail(std::move(Err)); }; 66 67 ObjLayer.setProcessAllSections(ProcessAllSections); 68 cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule())); 69 ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, OnResolveDoNothing, 70 OnReadyDoNothing, NoDependenciesToRegister); 71 return DebugSectionSeen; 72 } 73 74 TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { 75 LLVMContext Context; 76 auto M = llvm::make_unique<Module>("", Context); 77 M->setTargetTriple("x86_64-unknown-linux-gnu"); 78 Type *Int32Ty = IntegerType::get(Context, 32); 79 GlobalVariable *GV = 80 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, 81 ConstantInt::get(Int32Ty, 42), "foo"); 82 83 GV->setSection(".debug_str"); 84 85 // Initialize the native target in case this is the first unit test 86 // to try to build a TM. 87 OrcNativeTarget::initialize(); 88 std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget( 89 Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>())); 90 if (!TM) 91 return; 92 93 auto Obj = SimpleCompiler(*TM)(*M); 94 95 EXPECT_FALSE(testSetProcessAllSections( 96 MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false)) 97 << "Debug section seen despite ProcessAllSections being false"; 98 EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true)) 99 << "Expected to see debug section when ProcessAllSections is true"; 100 } 101 102 TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) { 103 104 OrcNativeTarget::initialize(); 105 106 std::unique_ptr<TargetMachine> TM( 107 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", 108 SmallVector<std::string, 1>())); 109 110 if (!TM) 111 return; 112 113 // Our compiler is going to modify symbol visibility settings without telling 114 // ORC. This will test our ability to override the flags later. 115 class FunkySimpleCompiler : public SimpleCompiler { 116 public: 117 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} 118 119 CompileResult operator()(Module &M) { 120 auto *Foo = M.getFunction("foo"); 121 assert(Foo && "Expected function Foo not found"); 122 Foo->setVisibility(GlobalValue::HiddenVisibility); 123 return SimpleCompiler::operator()(M); 124 } 125 }; 126 127 // Create a module with two void() functions: foo and bar. 128 ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 129 ThreadSafeModule M; 130 { 131 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy"); 132 MB.getModule()->setDataLayout(TM->createDataLayout()); 133 134 Function *FooImpl = MB.createFunctionDecl<void()>("foo"); 135 BasicBlock *FooEntry = 136 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl); 137 IRBuilder<> B1(FooEntry); 138 B1.CreateRetVoid(); 139 140 Function *BarImpl = MB.createFunctionDecl<void()>("bar"); 141 BasicBlock *BarEntry = 142 BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl); 143 IRBuilder<> B2(BarEntry); 144 B2.CreateRetVoid(); 145 146 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx)); 147 } 148 149 // Create a simple stack and set the override flags option. 150 ExecutionSession ES; 151 auto &JD = ES.createJITDylib("main"); 152 auto Foo = ES.intern("foo"); 153 RTDyldObjectLinkingLayer ObjLayer( 154 ES, []() { return llvm::make_unique<SectionMemoryManager>(); }); 155 IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); 156 157 ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); 158 159 cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); 160 ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, 161 [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 162 [](Error Err) { cantFail(std::move(Err)); }, 163 NoDependenciesToRegister); 164 } 165 166 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { 167 168 OrcNativeTarget::initialize(); 169 170 std::unique_ptr<TargetMachine> TM( 171 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", 172 SmallVector<std::string, 1>())); 173 174 if (!TM) 175 return; 176 177 // Our compiler is going to add a new symbol without telling ORC. 178 // This will test our ability to auto-claim responsibility later. 179 class FunkySimpleCompiler : public SimpleCompiler { 180 public: 181 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} 182 183 CompileResult operator()(Module &M) { 184 Function *BarImpl = 185 Function::Create(TypeBuilder<void(), false>::get(M.getContext()), 186 GlobalValue::ExternalLinkage, "bar", &M); 187 BasicBlock *BarEntry = 188 BasicBlock::Create(M.getContext(), "entry", BarImpl); 189 IRBuilder<> B(BarEntry); 190 B.CreateRetVoid(); 191 192 return SimpleCompiler::operator()(M); 193 } 194 }; 195 196 // Create a module with two void() functions: foo and bar. 197 ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 198 ThreadSafeModule M; 199 { 200 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy"); 201 MB.getModule()->setDataLayout(TM->createDataLayout()); 202 203 Function *FooImpl = MB.createFunctionDecl<void()>("foo"); 204 BasicBlock *FooEntry = 205 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl); 206 IRBuilder<> B(FooEntry); 207 B.CreateRetVoid(); 208 209 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx)); 210 } 211 212 // Create a simple stack and set the override flags option. 213 ExecutionSession ES; 214 auto &JD = ES.createJITDylib("main"); 215 auto Foo = ES.intern("foo"); 216 RTDyldObjectLinkingLayer ObjLayer( 217 ES, []() { return llvm::make_unique<SectionMemoryManager>(); }); 218 IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); 219 220 ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); 221 222 cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); 223 ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, 224 [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 225 [](Error Err) { cantFail(std::move(Err)); }, 226 NoDependenciesToRegister); 227 } 228 229 } // end anonymous namespace 230