blob: 8878451bdec2eb603ebea4922aaaadb7628dad53 [file] [log] [blame]
Lang Hames67de5d22017-02-20 05:45:14 +00001//===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
Lang Hames5f7fcef2015-10-29 03:53:42 +00002//
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
Chandler Carruth9a67b072017-06-06 11:06:56 +000010#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
Lang Hames859d73c2016-01-09 19:50:40 +000011#include "OrcTestCommon.h"
Lang Hames5f7fcef2015-10-29 03:53:42 +000012#include "llvm/ExecutionEngine/ExecutionEngine.h"
Lang Hames5f7fcef2015-10-29 03:53:42 +000013#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
14#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
Lang Hames2fe7acb2016-01-19 21:06:38 +000015#include "llvm/ExecutionEngine/Orc/NullResolver.h"
Chandler Carruth9a67b072017-06-06 11:06:56 +000016#include "llvm/ExecutionEngine/SectionMemoryManager.h"
Lang Hames5f7fcef2015-10-29 03:53:42 +000017#include "llvm/IR/Constants.h"
18#include "llvm/IR/LLVMContext.h"
19#include "gtest/gtest.h"
20
21using namespace llvm;
22using namespace llvm::orc;
23
24namespace {
25
Lang Hames67de5d22017-02-20 05:45:14 +000026class RTDyldObjectLinkingLayerExecutionTest : public testing::Test,
27 public OrcExecutionTest {
Mehdi Amini03b42e42016-04-14 21:59:01 +000028
Lang Hames859d73c2016-01-09 19:50:40 +000029};
30
NAKAMURA Takumi96e30312016-01-10 15:56:49 +000031class SectionMemoryManagerWrapper : public SectionMemoryManager {
32public:
33 int FinalizationCount = 0;
Lang Hames2fe7acb2016-01-19 21:06:38 +000034 int NeedsToReserveAllocationSpaceCount = 0;
35
36 bool needsToReserveAllocationSpace() override {
37 ++NeedsToReserveAllocationSpaceCount;
38 return SectionMemoryManager::needsToReserveAllocationSpace();
39 }
40
Eugene Zelenko6ac3f732016-01-26 18:48:36 +000041 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
NAKAMURA Takumi96e30312016-01-10 15:56:49 +000042 ++FinalizationCount;
43 return SectionMemoryManager::finalizeMemory(ErrMsg);
44 }
45};
46
Lang Hames67de5d22017-02-20 05:45:14 +000047TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
Lang Hames5f7fcef2015-10-29 03:53:42 +000048 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:
Lang Hamesd22bade2017-04-04 17:03:49 +000063 bool &DebugSeen;
Lang Hames5f7fcef2015-10-29 03:53:42 +000064 };
65
Lang Hames67de5d22017-02-20 05:45:14 +000066 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames5f7fcef2015-10-29 03:53:42 +000067
Mehdi Amini03b42e42016-04-14 21:59:01 +000068 LLVMContext Context;
69 auto M = llvm::make_unique<Module>("", Context);
Lang Hames5f7fcef2015-10-29 03:53:42 +000070 M->setTargetTriple("x86_64-unknown-linux-gnu");
Mehdi Amini03b42e42016-04-14 21:59:01 +000071 Type *Int32Ty = IntegerType::get(Context, 32);
Lang Hames5f7fcef2015-10-29 03:53:42 +000072 GlobalVariable *GV =
73 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
74 ConstantInt::get(Int32Ty, 42), "foo");
75
76 GV->setSection(".debug_str");
77
Lang Hamesd22bade2017-04-04 17:03:49 +000078
79 // Initialize the native target in case this is the first unit test
80 // to try to build a TM.
81 OrcNativeTarget::initialize();
Lang Hames5f7fcef2015-10-29 03:53:42 +000082 std::unique_ptr<TargetMachine> TM(
83 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
84 SmallVector<std::string, 1>()));
85 if (!TM)
86 return;
87
88 auto OwningObj = SimpleCompiler(*TM)(*M);
89 std::vector<object::ObjectFile*> Objs;
90 Objs.push_back(OwningObj.getBinary());
91
92 bool DebugSectionSeen = false;
Lang Hamesc936ac72017-05-09 21:32:18 +000093 auto SMMW =
94 std::make_shared<SectionMemoryManagerWrapper>(DebugSectionSeen);
Lang Hames5f7fcef2015-10-29 03:53:42 +000095 auto Resolver =
96 createLambdaResolver(
97 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +000098 return JITSymbol(nullptr);
Lang Hames5f7fcef2015-10-29 03:53:42 +000099 },
100 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +0000101 return JITSymbol(nullptr);
Lang Hames5f7fcef2015-10-29 03:53:42 +0000102 });
103
104 {
105 // Test with ProcessAllSections = false (the default).
Lang Hamesc936ac72017-05-09 21:32:18 +0000106 auto H = ObjLayer.addObjectSet(Objs, SMMW, &*Resolver);
Lang Hamesd22bade2017-04-04 17:03:49 +0000107 ObjLayer.emitAndFinalize(H);
Lang Hames5f7fcef2015-10-29 03:53:42 +0000108 EXPECT_EQ(DebugSectionSeen, false)
109 << "Unexpected debug info section";
110 ObjLayer.removeObjectSet(H);
111 }
112
113 {
114 // Test with ProcessAllSections = true.
115 ObjLayer.setProcessAllSections(true);
Lang Hamesc936ac72017-05-09 21:32:18 +0000116 auto H = ObjLayer.addObjectSet(Objs, SMMW, &*Resolver);
Lang Hamesd22bade2017-04-04 17:03:49 +0000117 ObjLayer.emitAndFinalize(H);
Lang Hames5f7fcef2015-10-29 03:53:42 +0000118 EXPECT_EQ(DebugSectionSeen, true)
119 << "Expected debug info section not seen";
120 ObjLayer.removeObjectSet(H);
121 }
122}
123
Lang Hames67de5d22017-02-20 05:45:14 +0000124TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
Lang Hames859d73c2016-01-09 19:50:40 +0000125 if (!TM)
126 return;
127
Lang Hames67de5d22017-02-20 05:45:14 +0000128 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames859d73c2016-01-09 19:50:40 +0000129 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(); }
Lang Hames133f1532016-01-18 01:00:19 +0000137 //
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.
Lang Hames859d73c2016-01-09 19:50:40 +0000142
Mehdi Amini03b42e42016-04-14 21:59:01 +0000143 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000144 {
145 MB1.getModule()->setDataLayout(TM->createDataLayout());
146 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000147 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000148 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000149 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames859d73c2016-01-09 19:50:40 +0000150 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
151 Builder.CreateRet(FourtyTwo);
152 }
153
154 auto Obj1 = Compile(*MB1.getModule());
155 std::vector<object::ObjectFile*> Obj1Set;
156 Obj1Set.push_back(Obj1.getBinary());
157
Mehdi Amini03b42e42016-04-14 21:59:01 +0000158 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000159 {
160 MB2.getModule()->setDataLayout(TM->createDataLayout());
161 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
162 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000163 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000164 IRBuilder<> Builder(FooEntry);
165 Builder.CreateRet(Builder.CreateCall(BarDecl));
166 }
167 auto Obj2 = Compile(*MB2.getModule());
168 std::vector<object::ObjectFile*> Obj2Set;
169 Obj2Set.push_back(Obj2.getBinary());
170
171 auto Resolver =
172 createLambdaResolver(
173 [&](const std::string &Name) {
174 if (auto Sym = ObjLayer.findSymbol(Name, true))
Lang Hamesad4a9112016-08-01 20:49:11 +0000175 return Sym;
176 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000177 },
178 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +0000179 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000180 });
181
Lang Hamesc936ac72017-05-09 21:32:18 +0000182 auto SMMW = std::make_shared<SectionMemoryManagerWrapper>();
183 ObjLayer.addObjectSet(std::move(Obj1Set), SMMW, &*Resolver);
184 auto H = ObjLayer.addObjectSet(std::move(Obj2Set), SMMW, &*Resolver);
Lang Hames859d73c2016-01-09 19:50:40 +0000185 ObjLayer.emitAndFinalize(H);
Lang Hamesc936ac72017-05-09 21:32:18 +0000186 ObjLayer.removeObjectSet(H);
187
Lang Hames859d73c2016-01-09 19:50:40 +0000188 // Finalization of module 2 should trigger finalization of module 1.
189 // Verify that finalize on SMMW is only called once.
Lang Hamesc936ac72017-05-09 21:32:18 +0000190 EXPECT_EQ(SMMW->FinalizationCount, 1)
Lang Hames859d73c2016-01-09 19:50:40 +0000191 << "Extra call to finalize";
192}
193
Lang Hames67de5d22017-02-20 05:45:14 +0000194TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
Lang Hames2fe7acb2016-01-19 21:06:38 +0000195 if (!TM)
196 return;
197
Lang Hames67de5d22017-02-20 05:45:14 +0000198 RTDyldObjectLinkingLayer<> ObjLayer;
Lang Hames2fe7acb2016-01-19 21:06:38 +0000199 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
Mehdi Amini03b42e42016-04-14 21:59:01 +0000214 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000215 {
216 MB1.getModule()->setDataLayout(TM->createDataLayout());
217 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000218 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000219 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000220 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000221 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
222 Builder.CreateRet(FourtyTwo);
223 }
224
225 auto Obj1 = Compile(*MB1.getModule());
226 std::vector<object::ObjectFile*> Obj1Set;
227 Obj1Set.push_back(Obj1.getBinary());
228
Mehdi Amini03b42e42016-04-14 21:59:01 +0000229 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000230 {
231 MB2.getModule()->setDataLayout(TM->createDataLayout());
232 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000233 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000234 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000235 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000236 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
237 Builder.CreateRet(Seven);
238 }
239 auto Obj2 = Compile(*MB2.getModule());
240 std::vector<object::ObjectFile*> Obj2Set;
241 Obj2Set.push_back(Obj2.getBinary());
242
Lang Hamesc936ac72017-05-09 21:32:18 +0000243 auto SMMW = std::make_shared<SectionMemoryManagerWrapper>();
Lang Hames2fe7acb2016-01-19 21:06:38 +0000244 NullResolver NR;
Lang Hamesc936ac72017-05-09 21:32:18 +0000245 auto H = ObjLayer.addObjectSet(std::move(Obj1Set), SMMW, &NR);
246 ObjLayer.addObjectSet(std::move(Obj2Set), SMMW, &NR);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000247 ObjLayer.emitAndFinalize(H);
Lang Hamesc936ac72017-05-09 21:32:18 +0000248 ObjLayer.removeObjectSet(H);
249
Lang Hames2fe7acb2016-01-19 21:06:38 +0000250 // Only one call to needsToReserveAllocationSpace should have been made.
Lang Hamesc936ac72017-05-09 21:32:18 +0000251 EXPECT_EQ(SMMW->NeedsToReserveAllocationSpaceCount, 1)
Lang Hames2fe7acb2016-01-19 21:06:38 +0000252 << "More than one call to needsToReserveAllocationSpace "
253 "(multiple unrelated objects loaded prior to finalization)";
254}
255
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000256} // end anonymous namespace