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/RTDyldObjectLinkingLayer.h" 14 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 15 #include "llvm/IR/Constants.h" 16 #include "llvm/IR/LLVMContext.h" 17 #include "gtest/gtest.h" 18 19 using namespace llvm; 20 using namespace llvm::orc; 21 22 namespace { 23 24 class RTDyldObjectLinkingLayerExecutionTest : public testing::Test, 25 public OrcExecutionTest {}; 26 27 // Adds an object with a debug section to RuntimeDyld and then returns whether 28 // the debug section was passed to the memory manager. 29 static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, 30 bool ProcessAllSections) { 31 class MemoryManagerWrapper : public SectionMemoryManager { 32 public: 33 MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {} 34 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 35 unsigned SectionID, StringRef SectionName, 36 bool IsReadOnly) override { 37 if (SectionName == ".debug_str") 38 DebugSeen = true; 39 return SectionMemoryManager::allocateDataSection( 40 Size, Alignment, SectionID, SectionName, IsReadOnly); 41 } 42 43 private: 44 bool &DebugSeen; 45 }; 46 47 bool DebugSectionSeen = false; 48 49 ExecutionSession ES; 50 auto &JD = ES.createBareJITDylib("main"); 51 auto Foo = ES.intern("foo"); 52 53 RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() { 54 return std::make_unique<MemoryManagerWrapper>(DebugSectionSeen); 55 }); 56 57 auto OnResolveDoNothing = [](Expected<SymbolMap> R) { 58 cantFail(std::move(R)); 59 }; 60 61 ObjLayer.setProcessAllSections(ProcessAllSections); 62 cantFail(ObjLayer.add(JD, std::move(Obj))); 63 ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), 64 SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing, 65 NoDependenciesToRegister); 66 67 if (auto Err = ES.endSession()) 68 ES.reportError(std::move(Err)); 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))); 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 if (auto Err = ES.endSession()) 173 ES.reportError(std::move(Err)); 174 } 175 176 TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { 177 178 OrcNativeTarget::initialize(); 179 180 std::unique_ptr<TargetMachine> TM( 181 EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "", 182 SmallVector<std::string, 1>())); 183 184 if (!TM) 185 return; 186 187 // Our compiler is going to add a new symbol without telling ORC. 188 // This will test our ability to auto-claim responsibility later. 189 class FunkySimpleCompiler : public SimpleCompiler { 190 public: 191 FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} 192 193 Expected<CompileResult> operator()(Module &M) override { 194 Function *BarImpl = Function::Create( 195 FunctionType::get(Type::getVoidTy(M.getContext()), {}, false), 196 GlobalValue::ExternalLinkage, "bar", &M); 197 BasicBlock *BarEntry = 198 BasicBlock::Create(M.getContext(), "entry", BarImpl); 199 IRBuilder<> B(BarEntry); 200 B.CreateRetVoid(); 201 202 return SimpleCompiler::operator()(M); 203 } 204 }; 205 206 // Create a module with two void() functions: foo and bar. 207 ThreadSafeContext TSCtx(std::make_unique<LLVMContext>()); 208 ThreadSafeModule M; 209 { 210 ModuleBuilder MB(*TSCtx.getContext(), TM->getTargetTriple().str(), "dummy"); 211 MB.getModule()->setDataLayout(TM->createDataLayout()); 212 213 Function *FooImpl = MB.createFunctionDecl( 214 FunctionType::get(Type::getVoidTy(*TSCtx.getContext()), {}, false), 215 "foo"); 216 BasicBlock *FooEntry = 217 BasicBlock::Create(*TSCtx.getContext(), "entry", FooImpl); 218 IRBuilder<> B(FooEntry); 219 B.CreateRetVoid(); 220 221 M = ThreadSafeModule(MB.takeModule(), std::move(TSCtx)); 222 } 223 224 // Create a simple stack and set the override flags option. 225 ExecutionSession ES; 226 auto &JD = ES.createBareJITDylib("main"); 227 auto Foo = ES.intern("foo"); 228 RTDyldObjectLinkingLayer ObjLayer( 229 ES, []() { return std::make_unique<SectionMemoryManager>(); }); 230 IRCompileLayer CompileLayer(ES, ObjLayer, 231 std::make_unique<FunkySimpleCompiler>(*TM)); 232 233 ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); 234 235 cantFail(CompileLayer.add(JD, std::move(M))); 236 ES.lookup( 237 LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo), 238 SymbolState::Resolved, 239 [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 240 NoDependenciesToRegister); 241 242 if (auto Err = ES.endSession()) 243 ES.reportError(std::move(Err)); 244 } 245 246 } // end anonymous namespace 247