1 //===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===// 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 "OrcTestCommon.h" 11 #include "llvm/ExecutionEngine/ExecutionEngine.h" 12 #include "llvm/ExecutionEngine/SectionMemoryManager.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/Orc/ObjectLinkingLayer.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 ObjectLinkingLayerExecutionTest : public testing::Test, 27 public OrcExecutionTest { 28 }; 29 30 class SectionMemoryManagerWrapper : public SectionMemoryManager { 31 public: 32 int FinalizationCount = 0; 33 int NeedsToReserveAllocationSpaceCount = 0; 34 35 bool needsToReserveAllocationSpace() override { 36 ++NeedsToReserveAllocationSpaceCount; 37 return SectionMemoryManager::needsToReserveAllocationSpace(); 38 } 39 40 bool finalizeMemory(std::string *ErrMsg = 0) override { 41 ++FinalizationCount; 42 return SectionMemoryManager::finalizeMemory(ErrMsg); 43 } 44 }; 45 46 TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) { 47 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 ObjectLinkingLayer<> ObjLayer; 67 68 auto M = llvm::make_unique<Module>("", getGlobalContext()); 69 M->setTargetTriple("x86_64-unknown-linux-gnu"); 70 Type *Int32Ty = IntegerType::get(getGlobalContext(), 32); 71 GlobalVariable *GV = 72 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, 73 ConstantInt::get(Int32Ty, 42), "foo"); 74 75 GV->setSection(".debug_str"); 76 77 std::unique_ptr<TargetMachine> TM( 78 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "", 79 SmallVector<std::string, 1>())); 80 if (!TM) 81 return; 82 83 auto OwningObj = SimpleCompiler(*TM)(*M); 84 std::vector<object::ObjectFile*> Objs; 85 Objs.push_back(OwningObj.getBinary()); 86 87 bool DebugSectionSeen = false; 88 SectionMemoryManagerWrapper SMMW(DebugSectionSeen); 89 auto Resolver = 90 createLambdaResolver( 91 [](const std::string &Name) { 92 return RuntimeDyld::SymbolInfo(nullptr); 93 }, 94 [](const std::string &Name) { 95 return RuntimeDyld::SymbolInfo(nullptr); 96 }); 97 98 { 99 // Test with ProcessAllSections = false (the default). 100 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); 101 EXPECT_EQ(DebugSectionSeen, false) 102 << "Unexpected debug info section"; 103 ObjLayer.removeObjectSet(H); 104 } 105 106 { 107 // Test with ProcessAllSections = true. 108 ObjLayer.setProcessAllSections(true); 109 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); 110 EXPECT_EQ(DebugSectionSeen, true) 111 << "Expected debug info section not seen"; 112 ObjLayer.removeObjectSet(H); 113 } 114 } 115 116 117 TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { 118 119 if (!TM) 120 return; 121 122 ObjectLinkingLayer<> ObjLayer; 123 SimpleCompiler Compile(*TM); 124 125 // Create a pair of modules that will trigger recursive finalization: 126 // Module 1: 127 // int bar() { return 42; } 128 // Module 2: 129 // int bar(); 130 // int foo() { return bar(); } 131 // 132 // Verify that the memory manager is only finalized once (for Module 2). 133 // Failure suggests that finalize is being called on the inner RTDyld 134 // instance (for Module 1) which is unsafe, as it will prevent relocation of 135 // Module 2. 136 137 ModuleBuilder MB1(getGlobalContext(), "", "dummy"); 138 { 139 MB1.getModule()->setDataLayout(TM->createDataLayout()); 140 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar"); 141 BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry", 142 BarImpl); 143 IRBuilder<> Builder(BarEntry); 144 IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32); 145 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 146 Builder.CreateRet(FourtyTwo); 147 } 148 149 auto Obj1 = Compile(*MB1.getModule()); 150 std::vector<object::ObjectFile*> Obj1Set; 151 Obj1Set.push_back(Obj1.getBinary()); 152 153 ModuleBuilder MB2(getGlobalContext(), "", "dummy"); 154 { 155 MB2.getModule()->setDataLayout(TM->createDataLayout()); 156 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar"); 157 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo"); 158 BasicBlock *FooEntry = BasicBlock::Create(getGlobalContext(), "entry", 159 FooImpl); 160 IRBuilder<> Builder(FooEntry); 161 Builder.CreateRet(Builder.CreateCall(BarDecl)); 162 } 163 auto Obj2 = Compile(*MB2.getModule()); 164 std::vector<object::ObjectFile*> Obj2Set; 165 Obj2Set.push_back(Obj2.getBinary()); 166 167 auto Resolver = 168 createLambdaResolver( 169 [&](const std::string &Name) { 170 if (auto Sym = ObjLayer.findSymbol(Name, true)) 171 return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); 172 return RuntimeDyld::SymbolInfo(nullptr); 173 }, 174 [](const std::string &Name) { 175 return RuntimeDyld::SymbolInfo(nullptr); 176 }); 177 178 SectionMemoryManagerWrapper SMMW; 179 ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver); 180 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver); 181 ObjLayer.emitAndFinalize(H); 182 183 // Finalization of module 2 should trigger finalization of module 1. 184 // Verify that finalize on SMMW is only called once. 185 EXPECT_EQ(SMMW.FinalizationCount, 1) 186 << "Extra call to finalize"; 187 } 188 189 TEST_F(ObjectLinkingLayerExecutionTest, NoPrematureAllocation) { 190 191 if (!TM) 192 return; 193 194 ObjectLinkingLayer<> ObjLayer; 195 SimpleCompiler Compile(*TM); 196 197 // Create a pair of unrelated modules: 198 // 199 // Module 1: 200 // int foo() { return 42; } 201 // Module 2: 202 // int bar() { return 7; } 203 // 204 // Both modules will share a memory manager. We want to verify that the 205 // second object is not loaded before the first one is finalized. To do this 206 // in a portable way, we abuse the 207 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is 208 // called once per object before any sections are allocated. 209 210 ModuleBuilder MB1(getGlobalContext(), "", "dummy"); 211 { 212 MB1.getModule()->setDataLayout(TM->createDataLayout()); 213 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo"); 214 BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry", 215 BarImpl); 216 IRBuilder<> Builder(BarEntry); 217 IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32); 218 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 219 Builder.CreateRet(FourtyTwo); 220 } 221 222 auto Obj1 = Compile(*MB1.getModule()); 223 std::vector<object::ObjectFile*> Obj1Set; 224 Obj1Set.push_back(Obj1.getBinary()); 225 226 ModuleBuilder MB2(getGlobalContext(), "", "dummy"); 227 { 228 MB2.getModule()->setDataLayout(TM->createDataLayout()); 229 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar"); 230 BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry", 231 BarImpl); 232 IRBuilder<> Builder(BarEntry); 233 IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32); 234 Value *Seven = ConstantInt::getSigned(Int32Ty, 7); 235 Builder.CreateRet(Seven); 236 } 237 auto Obj2 = Compile(*MB2.getModule()); 238 std::vector<object::ObjectFile*> Obj2Set; 239 Obj2Set.push_back(Obj2.getBinary()); 240 241 SectionMemoryManagerWrapper SMMW; 242 NullResolver NR; 243 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR); 244 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR); 245 ObjLayer.emitAndFinalize(H); 246 247 // Only one call to needsToReserveAllocationSpace should have been made. 248 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1) 249 << "More than one call to needsToReserveAllocationSpace " 250 "(multiple unrelated objects loaded prior to finalization)"; 251 } 252 253 } 254