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 // Adds an object with a debug section to RuntimeDyld and then returns whether 25 // the debug section was passed to the memory manager. 26 static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj, 27 bool ProcessAllSections) { 28 class MemoryManagerWrapper : public SectionMemoryManager { 29 public: 30 MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {} 31 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 32 unsigned SectionID, StringRef SectionName, 33 bool IsReadOnly) override { 34 if (SectionName == ".debug_str") 35 DebugSeen = true; 36 return SectionMemoryManager::allocateDataSection( 37 Size, Alignment, SectionID, SectionName, IsReadOnly); 38 } 39 40 private: 41 bool &DebugSeen; 42 }; 43 44 bool DebugSectionSeen = false; 45 46 ExecutionSession ES; 47 auto &JD = ES.createBareJITDylib("main"); 48 auto Foo = ES.intern("foo"); 49 50 RTDyldObjectLinkingLayer ObjLayer(ES, [&DebugSectionSeen]() { 51 return std::make_unique<MemoryManagerWrapper>(DebugSectionSeen); 52 }); 53 54 auto OnResolveDoNothing = [](Expected<SymbolMap> R) { 55 cantFail(std::move(R)); 56 }; 57 58 ObjLayer.setProcessAllSections(ProcessAllSections); 59 cantFail(ObjLayer.add(JD, std::move(Obj))); 60 ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD), 61 SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing, 62 NoDependenciesToRegister); 63 64 if (auto Err = ES.endSession()) 65 ES.reportError(std::move(Err)); 66 67 return DebugSectionSeen; 68 } 69 70 TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { 71 LLVMContext Context; 72 auto M = std::make_unique<Module>("", Context); 73 M->setTargetTriple("x86_64-unknown-linux-gnu"); 74 Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two"); 75 auto *GV = 76 new GlobalVariable(*M, StrConstant->getType(), true, 77 GlobalValue::ExternalLinkage, StrConstant, "foo"); 78 GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 79 GV->setAlignment(Align(1)); 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 = cantFail(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 Expected<CompileResult> operator()(Module &M) override { 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(std::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.createBareJITDylib("main"); 154 auto Foo = ES.intern("foo"); 155 RTDyldObjectLinkingLayer ObjLayer( 156 ES, []() { return std::make_unique<SectionMemoryManager>(); }); 157 IRCompileLayer CompileLayer(ES, ObjLayer, 158 std::make_unique<FunkySimpleCompiler>(*TM)); 159 160 ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); 161 162 cantFail(CompileLayer.add(JD, std::move(M))); 163 ES.lookup( 164 LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo), 165 SymbolState::Resolved, 166 [](Expected<SymbolMap> R) { cantFail(std::move(R)); }, 167 NoDependenciesToRegister); 168 169 if (auto Err = ES.endSession()) 170 ES.reportError(std::move(Err)); 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))); 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 if (auto Err = ES.endSession()) 240 ES.reportError(std::move(Err)); 241 } 242 243 } // end anonymous namespace 244