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 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(ObjectLinkingLayerTest, 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 ObjectLinkingLayer<> 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 std::unique_ptr<TargetMachine> TM( 79 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "", 80 SmallVector<std::string, 1>())); 81 if (!TM) 82 return; 83 84 auto OwningObj = SimpleCompiler(*TM)(*M); 85 std::vector<object::ObjectFile*> Objs; 86 Objs.push_back(OwningObj.getBinary()); 87 88 bool DebugSectionSeen = false; 89 SectionMemoryManagerWrapper SMMW(DebugSectionSeen); 90 auto Resolver = 91 createLambdaResolver( 92 [](const std::string &Name) { 93 return RuntimeDyld::SymbolInfo(nullptr); 94 }, 95 [](const std::string &Name) { 96 return RuntimeDyld::SymbolInfo(nullptr); 97 }); 98 99 { 100 // Test with ProcessAllSections = false (the default). 101 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); 102 EXPECT_EQ(DebugSectionSeen, false) 103 << "Unexpected debug info section"; 104 ObjLayer.removeObjectSet(H); 105 } 106 107 { 108 // Test with ProcessAllSections = true. 109 ObjLayer.setProcessAllSections(true); 110 auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver); 111 EXPECT_EQ(DebugSectionSeen, true) 112 << "Expected debug info section not seen"; 113 ObjLayer.removeObjectSet(H); 114 } 115 } 116 117 TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) { 118 if (!TM) 119 return; 120 121 ObjectLinkingLayer<> ObjLayer; 122 SimpleCompiler Compile(*TM); 123 124 // Create a pair of modules that will trigger recursive finalization: 125 // Module 1: 126 // int bar() { return 42; } 127 // Module 2: 128 // int bar(); 129 // int foo() { return bar(); } 130 // 131 // Verify that the memory manager is only finalized once (for Module 2). 132 // Failure suggests that finalize is being called on the inner RTDyld 133 // instance (for Module 1) which is unsafe, as it will prevent relocation of 134 // Module 2. 135 136 ModuleBuilder MB1(Context, "", "dummy"); 137 { 138 MB1.getModule()->setDataLayout(TM->createDataLayout()); 139 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar"); 140 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 141 IRBuilder<> Builder(BarEntry); 142 IntegerType *Int32Ty = IntegerType::get(Context, 32); 143 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 144 Builder.CreateRet(FourtyTwo); 145 } 146 147 auto Obj1 = Compile(*MB1.getModule()); 148 std::vector<object::ObjectFile*> Obj1Set; 149 Obj1Set.push_back(Obj1.getBinary()); 150 151 ModuleBuilder MB2(Context, "", "dummy"); 152 { 153 MB2.getModule()->setDataLayout(TM->createDataLayout()); 154 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar"); 155 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo"); 156 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", 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 Sym.toRuntimeDyldSymbol(); 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(Context, "", "dummy"); 207 { 208 MB1.getModule()->setDataLayout(TM->createDataLayout()); 209 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo"); 210 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 211 IRBuilder<> Builder(BarEntry); 212 IntegerType *Int32Ty = IntegerType::get(Context, 32); 213 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42); 214 Builder.CreateRet(FourtyTwo); 215 } 216 217 auto Obj1 = Compile(*MB1.getModule()); 218 std::vector<object::ObjectFile*> Obj1Set; 219 Obj1Set.push_back(Obj1.getBinary()); 220 221 ModuleBuilder MB2(Context, "", "dummy"); 222 { 223 MB2.getModule()->setDataLayout(TM->createDataLayout()); 224 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar"); 225 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl); 226 IRBuilder<> Builder(BarEntry); 227 IntegerType *Int32Ty = IntegerType::get(Context, 32); 228 Value *Seven = ConstantInt::getSigned(Int32Ty, 7); 229 Builder.CreateRet(Seven); 230 } 231 auto Obj2 = Compile(*MB2.getModule()); 232 std::vector<object::ObjectFile*> Obj2Set; 233 Obj2Set.push_back(Obj2.getBinary()); 234 235 SectionMemoryManagerWrapper SMMW; 236 NullResolver NR; 237 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR); 238 ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR); 239 ObjLayer.emitAndFinalize(H); 240 241 // Only one call to needsToReserveAllocationSpace should have been made. 242 EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1) 243 << "More than one call to needsToReserveAllocationSpace " 244 "(multiple unrelated objects loaded prior to finalization)"; 245 } 246 247 } // end anonymous namespace 248