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