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