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 SectionMemoryManagerWrapper : public SectionMemoryManager { 49 public: 50 SectionMemoryManagerWrapper(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 RTDyldObjectLinkingLayer ObjLayer; 67 68 LLVMContext Context; 69 auto M = llvm::make_unique<Module>("", Context); 70 M->setTargetTriple("x86_64-unknown-linux-gnu"); 71 Type *Int32Ty = IntegerType::get(Context, 32); 72 GlobalVariable *GV = 73 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, 74 ConstantInt::get(Int32Ty, 42), "foo"); 75 76 GV->setSection(".debug_str"); 77 78 79 // Initialize the native target in case this is the first unit test 80 // to try to build a TM. 81 OrcNativeTarget::initialize(); 82 std::unique_ptr<TargetMachine> TM( 83 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "", 84 SmallVector<std::string, 1>())); 85 if (!TM) 86 return; 87 88 auto Obj = 89 std::make_shared<object::OwningBinary<object::ObjectFile>>( 90 SimpleCompiler(*TM)(*M)); 91 92 bool DebugSectionSeen = false; 93 auto SMMW = 94 std::make_shared<SectionMemoryManagerWrapper>(DebugSectionSeen); 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 = ObjLayer.addObject(Obj, SMMW, &*Resolver); 107 ObjLayer.emitAndFinalize(H); 108 EXPECT_EQ(DebugSectionSeen, false) 109 << "Unexpected debug info section"; 110 ObjLayer.removeObject(H); 111 } 112 113 { 114 // Test with ProcessAllSections = true. 115 ObjLayer.setProcessAllSections(true); 116 auto H = ObjLayer.addObject(Obj, SMMW, &*Resolver); 117 ObjLayer.emitAndFinalize(H); 118 EXPECT_EQ(DebugSectionSeen, true) 119 << "Expected debug info section not seen"; 120 ObjLayer.removeObject(H); 121 } 122 } 123 124 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { 125 if (!TM) 126 return; 127 128 RTDyldObjectLinkingLayer ObjLayer; 129 SimpleCompiler Compile(*TM); 130 131 // Create a pair of modules that will trigger recursive finalization: 132 // Module 1: 133 // int bar() { return 42; } 134 // Module 2: 135 // int bar(); 136 // int foo() { return bar(); } 137 // 138 // Verify that the memory manager is only finalized once (for Module 2). 139 // Failure suggests that finalize is being called on the inner RTDyld 140 // instance (for Module 1) which is unsafe, as it will prevent relocation of 141 // Module 2. 142 143 ModuleBuilder MB1(Context, "", "dummy"); 144 { 145 MB1.getModule()->setDataLayout(TM->createDataLayout()); 146 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar"); 147 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 148 IRBuilder<> Builder(BarEntry); 149 IntegerType *Int32Ty = IntegerType::get(Context, 32); 150 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 151 Builder.CreateRet(FourtyTwo); 152 } 153 154 auto Obj1 = 155 std::make_shared<object::OwningBinary<object::ObjectFile>>( 156 Compile(*MB1.getModule())); 157 158 ModuleBuilder MB2(Context, "", "dummy"); 159 { 160 MB2.getModule()->setDataLayout(TM->createDataLayout()); 161 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar"); 162 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo"); 163 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl); 164 IRBuilder<> Builder(FooEntry); 165 Builder.CreateRet(Builder.CreateCall(BarDecl)); 166 } 167 auto Obj2 = 168 std::make_shared<object::OwningBinary<object::ObjectFile>>( 169 Compile(*MB2.getModule())); 170 171 auto Resolver = 172 createLambdaResolver( 173 [&](const std::string &Name) { 174 if (auto Sym = ObjLayer.findSymbol(Name, true)) 175 return Sym; 176 return JITSymbol(nullptr); 177 }, 178 [](const std::string &Name) { 179 return JITSymbol(nullptr); 180 }); 181 182 auto SMMW = std::make_shared<SectionMemoryManagerWrapper>(); 183 ObjLayer.addObject(std::move(Obj1), SMMW, &*Resolver); 184 auto H = ObjLayer.addObject(std::move(Obj2), SMMW, &*Resolver); 185 ObjLayer.emitAndFinalize(H); 186 ObjLayer.removeObject(H); 187 188 // Finalization of module 2 should trigger finalization of module 1. 189 // Verify that finalize on SMMW is only called once. 190 EXPECT_EQ(SMMW->FinalizationCount, 1) 191 << "Extra call to finalize"; 192 } 193 194 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) { 195 if (!TM) 196 return; 197 198 RTDyldObjectLinkingLayer ObjLayer; 199 SimpleCompiler Compile(*TM); 200 201 // Create a pair of unrelated modules: 202 // 203 // Module 1: 204 // int foo() { return 42; } 205 // Module 2: 206 // int bar() { return 7; } 207 // 208 // Both modules will share a memory manager. We want to verify that the 209 // second object is not loaded before the first one is finalized. To do this 210 // in a portable way, we abuse the 211 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is 212 // called once per object before any sections are allocated. 213 214 ModuleBuilder MB1(Context, "", "dummy"); 215 { 216 MB1.getModule()->setDataLayout(TM->createDataLayout()); 217 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo"); 218 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 219 IRBuilder<> Builder(BarEntry); 220 IntegerType *Int32Ty = IntegerType::get(Context, 32); 221 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 222 Builder.CreateRet(FourtyTwo); 223 } 224 225 auto Obj1 = 226 std::make_shared<object::OwningBinary<object::ObjectFile>>( 227 Compile(*MB1.getModule())); 228 229 ModuleBuilder MB2(Context, "", "dummy"); 230 { 231 MB2.getModule()->setDataLayout(TM->createDataLayout()); 232 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar"); 233 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 234 IRBuilder<> Builder(BarEntry); 235 IntegerType *Int32Ty = IntegerType::get(Context, 32); 236 Value *Seven = ConstantInt::getSigned(Int32Ty, 7); 237 Builder.CreateRet(Seven); 238 } 239 auto Obj2 = 240 std::make_shared<object::OwningBinary<object::ObjectFile>>( 241 Compile(*MB2.getModule())); 242 243 auto SMMW = std::make_shared<SectionMemoryManagerWrapper>(); 244 NullResolver NR; 245 auto H = ObjLayer.addObject(std::move(Obj1), SMMW, &NR); 246 ObjLayer.addObject(std::move(Obj2), SMMW, &NR); 247 ObjLayer.emitAndFinalize(H); 248 ObjLayer.removeObject(H); 249 250 // Only one call to needsToReserveAllocationSpace should have been made. 251 EXPECT_EQ(SMMW->NeedsToReserveAllocationSpaceCount, 1) 252 << "More than one call to needsToReserveAllocationSpace " 253 "(multiple unrelated objects loaded prior to finalization)"; 254 } 255 256 } // end anonymous namespace 257