blob: b3696c6ca4a6785ab2cffa87ef75703e2be559f2 [file] [log] [blame]
Lang Hames079df9a2018-10-15 22:56:10 +00001//===- 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/Legacy.h"
16#include "llvm/ExecutionEngine/Orc/NullResolver.h"
17#include "llvm/ExecutionEngine/SectionMemoryManager.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/LLVMContext.h"
20#include "gtest/gtest.h"
21
22using namespace llvm;
23using namespace llvm::orc;
24
25namespace {
26
27class LegacyRTDyldObjectLinkingLayerExecutionTest : public testing::Test,
28 public OrcExecutionTest {
29
30};
31
32class SectionMemoryManagerWrapper : public SectionMemoryManager {
33public:
34 int FinalizationCount = 0;
35 int NeedsToReserveAllocationSpaceCount = 0;
36
37 bool needsToReserveAllocationSpace() override {
38 ++NeedsToReserveAllocationSpaceCount;
39 return SectionMemoryManager::needsToReserveAllocationSpace();
40 }
41
42 bool finalizeMemory(std::string *ErrMsg = nullptr) override {
43 ++FinalizationCount;
44 return SectionMemoryManager::finalizeMemory(ErrMsg);
45 }
46};
47
48TEST(LegacyRTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
49 class MemoryManagerWrapper : public SectionMemoryManager {
50 public:
51 MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
52 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
53 unsigned SectionID,
54 StringRef SectionName,
55 bool IsReadOnly) override {
56 if (SectionName == ".debug_str")
57 DebugSeen = true;
58 return SectionMemoryManager::allocateDataSection(Size, Alignment,
59 SectionID,
60 SectionName,
61 IsReadOnly);
62 }
63 private:
64 bool &DebugSeen;
65 };
66
67 bool DebugSectionSeen = false;
68 auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
69
70 ExecutionSession ES;
71
72 LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey) {
73 return LegacyRTDyldObjectLinkingLayer::Resources{
74 MM, std::make_shared<NullResolver>()};
75 });
76
77 LLVMContext Context;
78 auto M = llvm::make_unique<Module>("", Context);
79 M->setTargetTriple("x86_64-unknown-linux-gnu");
80 Type *Int32Ty = IntegerType::get(Context, 32);
81 GlobalVariable *GV =
82 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
83 ConstantInt::get(Int32Ty, 42), "foo");
84
85 GV->setSection(".debug_str");
86
87
88 // Initialize the native target in case this is the first unit test
89 // to try to build a TM.
90 OrcNativeTarget::initialize();
91 std::unique_ptr<TargetMachine> TM(
92 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
93 SmallVector<std::string, 1>()));
94 if (!TM)
95 return;
96
97 auto Obj = SimpleCompiler(*TM)(*M);
98
99 {
100 // Test with ProcessAllSections = false (the default).
101 auto K = ES.allocateVModule();
102 cantFail(ObjLayer.addObject(
103 K, MemoryBuffer::getMemBufferCopy(Obj->getBuffer())));
104 cantFail(ObjLayer.emitAndFinalize(K));
105 EXPECT_EQ(DebugSectionSeen, false)
106 << "Unexpected debug info section";
107 cantFail(ObjLayer.removeObject(K));
108 }
109
110 {
111 // Test with ProcessAllSections = true.
112 ObjLayer.setProcessAllSections(true);
113 auto K = ES.allocateVModule();
114 cantFail(ObjLayer.addObject(K, std::move(Obj)));
115 cantFail(ObjLayer.emitAndFinalize(K));
116 EXPECT_EQ(DebugSectionSeen, true)
117 << "Expected debug info section not seen";
118 cantFail(ObjLayer.removeObject(K));
119 }
120}
121
122TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
123 if (!SupportsJIT)
124 return;
125
James Y Knightc0044112019-01-13 16:09:28 +0000126 Type *Int32Ty = IntegerType::get(Context, 32);
127
Lang Hames079df9a2018-10-15 22:56:10 +0000128 ExecutionSession ES;
129
130 auto MM = std::make_shared<SectionMemoryManagerWrapper>();
131
132 std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
133
134 LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&](VModuleKey K) {
135 auto I = Resolvers.find(K);
136 assert(I != Resolvers.end() && "Missing resolver");
137 auto R = std::move(I->second);
138 Resolvers.erase(I);
139 return LegacyRTDyldObjectLinkingLayer::Resources{MM, std::move(R)};
140 });
141 SimpleCompiler Compile(*TM);
142
143 // Create a pair of modules that will trigger recursive finalization:
144 // Module 1:
145 // int bar() { return 42; }
146 // Module 2:
147 // int bar();
148 // int foo() { return bar(); }
149 //
150 // Verify that the memory manager is only finalized once (for Module 2).
151 // Failure suggests that finalize is being called on the inner RTDyld
152 // instance (for Module 1) which is unsafe, as it will prevent relocation of
153 // Module 2.
154
155 ModuleBuilder MB1(Context, "", "dummy");
156 {
157 MB1.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000158 Function *BarImpl =
159 MB1.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "bar");
Lang Hames079df9a2018-10-15 22:56:10 +0000160 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
161 IRBuilder<> Builder(BarEntry);
162 IntegerType *Int32Ty = IntegerType::get(Context, 32);
163 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
164 Builder.CreateRet(FourtyTwo);
165 }
166
167 auto Obj1 = Compile(*MB1.getModule());
168
169 ModuleBuilder MB2(Context, "", "dummy");
170 {
171 MB2.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000172 Function *BarDecl =
173 MB2.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "bar");
174 Function *FooImpl =
175 MB2.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "foo");
Lang Hames079df9a2018-10-15 22:56:10 +0000176 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
177 IRBuilder<> Builder(FooEntry);
178 Builder.CreateRet(Builder.CreateCall(BarDecl));
179 }
180 auto Obj2 = Compile(*MB2.getModule());
181
182 auto K1 = ES.allocateVModule();
183 Resolvers[K1] = std::make_shared<NullResolver>();
184 cantFail(ObjLayer.addObject(K1, std::move(Obj1)));
185
186 auto K2 = ES.allocateVModule();
187 auto LegacyLookup = [&](const std::string &Name) {
188 return ObjLayer.findSymbol(Name, true);
189 };
190
191 Resolvers[K2] = createSymbolResolver(
192 [&](const SymbolNameSet &Symbols) {
193 return cantFail(
194 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup));
195 },
196 [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
197 const SymbolNameSet &Symbols) {
198 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
199 });
200
201 cantFail(ObjLayer.addObject(K2, std::move(Obj2)));
202 cantFail(ObjLayer.emitAndFinalize(K2));
203 cantFail(ObjLayer.removeObject(K2));
204
205 // Finalization of module 2 should trigger finalization of module 1.
206 // Verify that finalize on SMMW is only called once.
207 EXPECT_EQ(MM->FinalizationCount, 1)
208 << "Extra call to finalize";
209}
210
211TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
212 if (!SupportsJIT)
213 return;
214
James Y Knightc0044112019-01-13 16:09:28 +0000215 Type *Int32Ty = IntegerType::get(Context, 32);
216
Lang Hames079df9a2018-10-15 22:56:10 +0000217 ExecutionSession ES;
218
219 auto MM = std::make_shared<SectionMemoryManagerWrapper>();
220
221 LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey K) {
222 return LegacyRTDyldObjectLinkingLayer::Resources{
223 MM, std::make_shared<NullResolver>()};
224 });
225 SimpleCompiler Compile(*TM);
226
227 // Create a pair of unrelated modules:
228 //
229 // Module 1:
230 // int foo() { return 42; }
231 // Module 2:
232 // int bar() { return 7; }
233 //
234 // Both modules will share a memory manager. We want to verify that the
235 // second object is not loaded before the first one is finalized. To do this
236 // in a portable way, we abuse the
237 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
238 // called once per object before any sections are allocated.
239
240 ModuleBuilder MB1(Context, "", "dummy");
241 {
242 MB1.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000243 Function *BarImpl =
244 MB1.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "foo");
Lang Hames079df9a2018-10-15 22:56:10 +0000245 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
246 IRBuilder<> Builder(BarEntry);
247 IntegerType *Int32Ty = IntegerType::get(Context, 32);
248 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
249 Builder.CreateRet(FourtyTwo);
250 }
251
252 auto Obj1 = Compile(*MB1.getModule());
253
254 ModuleBuilder MB2(Context, "", "dummy");
255 {
256 MB2.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000257 Function *BarImpl =
258 MB2.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "bar");
Lang Hames079df9a2018-10-15 22:56:10 +0000259 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
260 IRBuilder<> Builder(BarEntry);
261 IntegerType *Int32Ty = IntegerType::get(Context, 32);
262 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
263 Builder.CreateRet(Seven);
264 }
265 auto Obj2 = Compile(*MB2.getModule());
266
267 auto K = ES.allocateVModule();
268 cantFail(ObjLayer.addObject(K, std::move(Obj1)));
269 cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj2)));
270 cantFail(ObjLayer.emitAndFinalize(K));
271 cantFail(ObjLayer.removeObject(K));
272
273 // Only one call to needsToReserveAllocationSpace should have been made.
274 EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
275 << "More than one call to needsToReserveAllocationSpace "
276 "(multiple unrelated objects loaded prior to finalization)";
277}
278
279TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
280 ExecutionSession ES;
281 LegacyRTDyldObjectLinkingLayer ObjLayer(
282 ES,
283 [](VModuleKey) {
284 return LegacyRTDyldObjectLinkingLayer::Resources{
285 nullptr, std::make_shared<NullResolver>()};
286 },
287 [](VModuleKey, const object::ObjectFile &obj,
288 const RuntimeDyld::LoadedObjectInfo &info) {});
289}
290
291} // end anonymous namespace