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