1 //===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 11 #include "OrcTestCommon.h" 12 #include "llvm/ExecutionEngine/ExecutionEngine.h" 13 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 14 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" 15 #include "llvm/ExecutionEngine/Orc/NullResolver.h" 16 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 17 #include "llvm/IR/Constants.h" 18 #include "llvm/IR/LLVMContext.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 using namespace llvm::orc; 23 24 namespace { 25 26 class RTDyldObjectLinkingLayerExecutionTest : public testing::Test, 27 public OrcExecutionTest { 28 29 }; 30 31 class SectionMemoryManagerWrapper : public SectionMemoryManager { 32 public: 33 int FinalizationCount = 0; 34 int NeedsToReserveAllocationSpaceCount = 0; 35 36 bool needsToReserveAllocationSpace() override { 37 ++NeedsToReserveAllocationSpaceCount; 38 return SectionMemoryManager::needsToReserveAllocationSpace(); 39 } 40 41 bool finalizeMemory(std::string *ErrMsg = nullptr) override { 42 ++FinalizationCount; 43 return SectionMemoryManager::finalizeMemory(ErrMsg); 44 } 45 }; 46 47 TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) { 48 class MemoryManagerWrapper : public SectionMemoryManager { 49 public: 50 MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {} 51 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 52 unsigned SectionID, 53 StringRef SectionName, 54 bool IsReadOnly) override { 55 if (SectionName == ".debug_str") 56 DebugSeen = true; 57 return SectionMemoryManager::allocateDataSection(Size, Alignment, 58 SectionID, 59 SectionName, 60 IsReadOnly); 61 } 62 private: 63 bool &DebugSeen; 64 }; 65 66 bool DebugSectionSeen = false; 67 auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen); 68 69 RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; }); 70 71 LLVMContext Context; 72 auto M = llvm::make_unique<Module>("", Context); 73 M->setTargetTriple("x86_64-unknown-linux-gnu"); 74 Type *Int32Ty = IntegerType::get(Context, 32); 75 GlobalVariable *GV = 76 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, 77 ConstantInt::get(Int32Ty, 42), "foo"); 78 79 GV->setSection(".debug_str"); 80 81 82 // Initialize the native target in case this is the first unit test 83 // to try to build a TM. 84 OrcNativeTarget::initialize(); 85 std::unique_ptr<TargetMachine> TM( 86 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "", 87 SmallVector<std::string, 1>())); 88 if (!TM) 89 return; 90 91 auto Obj = 92 std::make_shared<object::OwningBinary<object::ObjectFile>>( 93 SimpleCompiler(*TM)(*M)); 94 95 auto Resolver = 96 createLambdaResolver( 97 [](const std::string &Name) { 98 return JITSymbol(nullptr); 99 }, 100 [](const std::string &Name) { 101 return JITSymbol(nullptr); 102 }); 103 104 { 105 // Test with ProcessAllSections = false (the default). 106 auto H = cantFail(ObjLayer.addObject(Obj, Resolver)); 107 cantFail(ObjLayer.emitAndFinalize(H)); 108 EXPECT_EQ(DebugSectionSeen, false) 109 << "Unexpected debug info section"; 110 cantFail(ObjLayer.removeObject(H)); 111 } 112 113 { 114 // Test with ProcessAllSections = true. 115 ObjLayer.setProcessAllSections(true); 116 auto H = cantFail(ObjLayer.addObject(Obj, Resolver)); 117 cantFail(ObjLayer.emitAndFinalize(H)); 118 EXPECT_EQ(DebugSectionSeen, true) 119 << "Expected debug info section not seen"; 120 cantFail(ObjLayer.removeObject(H)); 121 } 122 } 123 124 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { 125 if (!TM) 126 return; 127 128 auto MM = std::make_shared<SectionMemoryManagerWrapper>(); 129 130 RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; }); 131 SimpleCompiler Compile(*TM); 132 133 // Create a pair of modules that will trigger recursive finalization: 134 // Module 1: 135 // int bar() { return 42; } 136 // Module 2: 137 // int bar(); 138 // int foo() { return bar(); } 139 // 140 // Verify that the memory manager is only finalized once (for Module 2). 141 // Failure suggests that finalize is being called on the inner RTDyld 142 // instance (for Module 1) which is unsafe, as it will prevent relocation of 143 // Module 2. 144 145 ModuleBuilder MB1(Context, "", "dummy"); 146 { 147 MB1.getModule()->setDataLayout(TM->createDataLayout()); 148 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar"); 149 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 150 IRBuilder<> Builder(BarEntry); 151 IntegerType *Int32Ty = IntegerType::get(Context, 32); 152 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 153 Builder.CreateRet(FourtyTwo); 154 } 155 156 auto Obj1 = 157 std::make_shared<object::OwningBinary<object::ObjectFile>>( 158 Compile(*MB1.getModule())); 159 160 ModuleBuilder MB2(Context, "", "dummy"); 161 { 162 MB2.getModule()->setDataLayout(TM->createDataLayout()); 163 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar"); 164 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo"); 165 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl); 166 IRBuilder<> Builder(FooEntry); 167 Builder.CreateRet(Builder.CreateCall(BarDecl)); 168 } 169 auto Obj2 = 170 std::make_shared<object::OwningBinary<object::ObjectFile>>( 171 Compile(*MB2.getModule())); 172 173 auto Resolver = 174 createLambdaResolver( 175 [&](const std::string &Name) { 176 if (auto Sym = ObjLayer.findSymbol(Name, true)) 177 return Sym; 178 return JITSymbol(nullptr); 179 }, 180 [](const std::string &Name) { 181 return JITSymbol(nullptr); 182 }); 183 184 cantFail(ObjLayer.addObject(std::move(Obj1), Resolver)); 185 auto H = cantFail(ObjLayer.addObject(std::move(Obj2), Resolver)); 186 cantFail(ObjLayer.emitAndFinalize(H)); 187 cantFail(ObjLayer.removeObject(H)); 188 189 // Finalization of module 2 should trigger finalization of module 1. 190 // Verify that finalize on SMMW is only called once. 191 EXPECT_EQ(MM->FinalizationCount, 1) 192 << "Extra call to finalize"; 193 } 194 195 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { 196 if (!TM) 197 return; 198 199 auto MM = std::make_shared<SectionMemoryManagerWrapper>(); 200 201 RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; }); 202 SimpleCompiler Compile(*TM); 203 204 // Create a pair of unrelated modules: 205 // 206 // Module 1: 207 // int foo() { return 42; } 208 // Module 2: 209 // int bar() { return 7; } 210 // 211 // Both modules will share a memory manager. We want to verify that the 212 // second object is not loaded before the first one is finalized. To do this 213 // in a portable way, we abuse the 214 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is 215 // called once per object before any sections are allocated. 216 217 ModuleBuilder MB1(Context, "", "dummy"); 218 { 219 MB1.getModule()->setDataLayout(TM->createDataLayout()); 220 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo"); 221 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 222 IRBuilder<> Builder(BarEntry); 223 IntegerType *Int32Ty = IntegerType::get(Context, 32); 224 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 225 Builder.CreateRet(FourtyTwo); 226 } 227 228 auto Obj1 = 229 std::make_shared<object::OwningBinary<object::ObjectFile>>( 230 Compile(*MB1.getModule())); 231 232 ModuleBuilder MB2(Context, "", "dummy"); 233 { 234 MB2.getModule()->setDataLayout(TM->createDataLayout()); 235 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar"); 236 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 237 IRBuilder<> Builder(BarEntry); 238 IntegerType *Int32Ty = IntegerType::get(Context, 32); 239 Value *Seven = ConstantInt::getSigned(Int32Ty, 7); 240 Builder.CreateRet(Seven); 241 } 242 auto Obj2 = 243 std::make_shared<object::OwningBinary<object::ObjectFile>>( 244 Compile(*MB2.getModule())); 245 246 auto NR = std::make_shared<NullResolver>(); 247 auto H = cantFail(ObjLayer.addObject(std::move(Obj1), NR)); 248 cantFail(ObjLayer.addObject(std::move(Obj2), NR)); 249 cantFail(ObjLayer.emitAndFinalize(H)); 250 cantFail(ObjLayer.removeObject(H)); 251 252 // Only one call to needsToReserveAllocationSpace should have been made. 253 EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1) 254 << "More than one call to needsToReserveAllocationSpace " 255 "(multiple unrelated objects loaded prior to finalization)"; 256 } 257 258 TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) { 259 RTDyldObjectLinkingLayer ObjLayer( 260 []() { return nullptr; }, 261 [](RTDyldObjectLinkingLayer::ObjHandleT, 262 const RTDyldObjectLinkingLayer::ObjectPtr &obj, 263 const RuntimeDyld::LoadedObjectInfo &info) {}); 264 } 265 266 } // end anonymous namespace 267