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.createBareJITDylib("main"); 54 auto Foo = ES.intern("foo"); 55 56 RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() { 57 return std::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(LookupKind::Static, makeJITDylibSearchOrder(&JD), 67 SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing, 68 NoDependenciesToRegister); 69 70 return DebugSectionSeen; 71 } 72 73 TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { 74 LLVMContext Context; 75 auto M = std::make_unique<Module>("", Context); 76 M->setTargetTriple("x86_64-unknown-linux-gnu"); 77 Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two"); 78 auto *GV = 79 new GlobalVariable(*M, StrConstant->getType(), true, 80 GlobalValue::ExternalLinkage, StrConstant, "foo"); 81 GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 82 GV->setAlignment(Align(1)); 83 84 GV->setSection(".debug_str"); 85 86 // Initialize the native target in case this is the first unit test 87 // to try to build a TM. 88 OrcNativeTarget::initialize(); 89 std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget( 90 Triple(M->getTargetTriple()), "", "", SmallVector<std::string, 1>())); 91 if (!TM) 92 return; 93 94 auto Obj = cantFail(SimpleCompiler(*TM)(*M)); 95 96 EXPECT_FALSE(testSetProcessAllSections( 97 MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false)) 98 << "Debug section seen despite ProcessAllSections being false"; 99 EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true)) 100 << "Expected to see debug section when ProcessAllSections is true"; 101 } 102 103 TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) { 104 105 OrcNativeTarget::initialize(); 106 107 std::unique_ptr<TargetMachine> TM( 108 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", 109 SmallVector<std::string, 1>())); 110 111 if (!TM) 112 return; 113 114 // Our compiler is going to modify symbol visibility settings without telling 115 // ORC. This will test our ability to override the flags later. 116 class FunkySimpleCompiler : public SimpleCompiler { 117 public: 118 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} 119 120 Expected<CompileResult> operator()(Module &M) override { 121 auto *Foo = M.getFunction("foo"); 122 assert(Foo && "Expected function Foo not found"); 123 Foo->setVisibility(GlobalValue::HiddenVisibility); 124 return SimpleCompiler::operator()(M); 125 } 126 }; 127 128 // Create a module with two void() functions: foo and bar. 129 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>()); 130 ThreadSafeModule M; 131 { 132 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy"); 133 MB.getModule()->setDataLayout(TM->createDataLayout()); 134 135 Function *FooImpl = MB.createFunctionDecl( 136 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false), 137 "foo"); 138 BasicBlock *FooEntry = 139 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl); 140 IRBuilder<> B1(FooEntry); 141 B1.CreateRetVoid(); 142 143 Function *BarImpl = MB.createFunctionDecl( 144 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false), 145 "bar"); 146 BasicBlock *BarEntry = 147 BasicBlock::Create(*TSCtx.getContext(), "entry", BarImpl); 148 IRBuilder<> B2(BarEntry); 149 B2.CreateRetVoid(); 150 151 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx)); 152 } 153 154 // Create a simple stack and set the override flags option. 155 ExecutionSession ES; 156 auto &JD = ES.createBareJITDylib("main"); 157 auto Foo = ES.intern("foo"); 158 RTDyldObjectLinkingLayer ObjLayer( 159 ES, []() { return std::make_unique<SectionMemoryManager>(); }); 160 IRCompileLayer CompileLayer(ES, ObjLayer, 161 std::make_unique<FunkySimpleCompiler>(*TM)); 162 163 ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); 164 165 cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); 166 ES.lookup( 167 LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo), 168 SymbolState::Resolved, 169 [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 170 NoDependenciesToRegister); 171 } 172 173 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { 174 175 OrcNativeTarget::initialize(); 176 177 std::unique_ptr<TargetMachine> TM( 178 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", 179 SmallVector<std::string, 1>())); 180 181 if (!TM) 182 return; 183 184 // Our compiler is going to add a new symbol without telling ORC. 185 // This will test our ability to auto-claim responsibility later. 186 class FunkySimpleCompiler : public SimpleCompiler { 187 public: 188 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} 189 190 Expected<CompileResult> operator()(Module &M) override { 191 Function *BarImpl = Function::Create( 192 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false), 193 GlobalValue::ExternalLinkage, "bar", &M); 194 BasicBlock *BarEntry = 195 BasicBlock::Create(M.getContext(), "entry", BarImpl); 196 IRBuilder<> B(BarEntry); 197 B.CreateRetVoid(); 198 199 return SimpleCompiler::operator()(M); 200 } 201 }; 202 203 // Create a module with two void() functions: foo and bar. 204 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>()); 205 ThreadSafeModule M; 206 { 207 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy"); 208 MB.getModule()->setDataLayout(TM->createDataLayout()); 209 210 Function *FooImpl = MB.createFunctionDecl( 211 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false), 212 "foo"); 213 BasicBlock *FooEntry = 214 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl); 215 IRBuilder<> B(FooEntry); 216 B.CreateRetVoid(); 217 218 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx)); 219 } 220 221 // Create a simple stack and set the override flags option. 222 ExecutionSession ES; 223 auto &JD = ES.createBareJITDylib("main"); 224 auto Foo = ES.intern("foo"); 225 RTDyldObjectLinkingLayer ObjLayer( 226 ES, []() { return std::make_unique<SectionMemoryManager>(); }); 227 IRCompileLayer CompileLayer(ES, ObjLayer, 228 std::make_unique<FunkySimpleCompiler>(*TM)); 229 230 ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); 231 232 cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); 233 ES.lookup( 234 LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo), 235 SymbolState::Resolved, 236 [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 237 NoDependenciesToRegister); 238 } 239 240 } // end anonymous namespace 241