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({&JD}, {Foo}, OnResolveDoNothing, OnReadyDoNothing, 70 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({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 161 [](Error Err) { cantFail(std::move(Err)); }, 162 NoDependenciesToRegister); 163 } 164 165 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { 166 167 OrcNativeTarget::initialize(); 168 169 std::unique_ptr<TargetMachine> TM( 170 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", 171 SmallVector<std::string, 1>())); 172 173 if (!TM) 174 return; 175 176 // Our compiler is going to add a new symbol without telling ORC. 177 // This will test our ability to auto-claim responsibility later. 178 class FunkySimpleCompiler : public SimpleCompiler { 179 public: 180 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} 181 182 CompileResult operator()(Module &M) { 183 Function *BarImpl = 184 Function::Create(TypeBuilder<void(), false>::get(M.getContext()), 185 GlobalValue::ExternalLinkage, "bar", &M); 186 BasicBlock *BarEntry = 187 BasicBlock::Create(M.getContext(), "entry", BarImpl); 188 IRBuilder<> B(BarEntry); 189 B.CreateRetVoid(); 190 191 return SimpleCompiler::operator()(M); 192 } 193 }; 194 195 // Create a module with two void() functions: foo and bar. 196 ThreadSafeContext TSCtx(llvm::make_unique<LLVMContext>()); 197 ThreadSafeModule M; 198 { 199 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy"); 200 MB.getModule()->setDataLayout(TM->createDataLayout()); 201 202 Function *FooImpl = MB.createFunctionDecl<void()>("foo"); 203 BasicBlock *FooEntry = 204 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl); 205 IRBuilder<> B(FooEntry); 206 B.CreateRetVoid(); 207 208 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx)); 209 } 210 211 // Create a simple stack and set the override flags option. 212 ExecutionSession ES; 213 auto &JD = ES.createJITDylib("main"); 214 auto Foo = ES.intern("foo"); 215 RTDyldObjectLinkingLayer ObjLayer( 216 ES, []() { return llvm::make_unique<SectionMemoryManager>(); }); 217 IRCompileLayer CompileLayer(ES, ObjLayer, FunkySimpleCompiler(*TM)); 218 219 ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); 220 221 cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); 222 ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 223 [](Error Err) { cantFail(std::move(Err)); }, 224 NoDependenciesToRegister); 225 } 226 227 } // end anonymous namespace 228