blob: 04b6f2101b256c81aa16e305aa9079dac3c12635 [file] [log] [blame]
Lang Hames079df9a2018-10-15 22:56:10 +00001//===- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer unit tests -===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Lang Hames079df9a2018-10-15 22:56:10 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
10#include "OrcTestCommon.h"
11#include "llvm/ExecutionEngine/ExecutionEngine.h"
12#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
13#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
14#include "llvm/ExecutionEngine/Orc/Legacy.h"
15#include "llvm/ExecutionEngine/Orc/NullResolver.h"
16#include "llvm/ExecutionEngine/SectionMemoryManager.h"
17#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
26class LegacyRTDyldObjectLinkingLayerExecutionTest : public testing::Test,
27 public OrcExecutionTest {
28
29};
30
31class SectionMemoryManagerWrapper : public SectionMemoryManager {
32public:
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
47TEST(LegacyRTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
48 class MemoryManagerWrapper : public SectionMemoryManager {
49 public:
50 MemoryManagerWrapper(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 bool DebugSectionSeen = false;
67 auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
68
69 ExecutionSession ES;
70
71 LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey) {
72 return LegacyRTDyldObjectLinkingLayer::Resources{
73 MM, std::make_shared<NullResolver>()};
74 });
75
76 LLVMContext Context;
77 auto M = llvm::make_unique<Module>("", Context);
78 M->setTargetTriple("x86_64-unknown-linux-gnu");
79 Type *Int32Ty = IntegerType::get(Context, 32);
80 GlobalVariable *GV =
81 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
82 ConstantInt::get(Int32Ty, 42), "foo");
83
84 GV->setSection(".debug_str");
85
86
87 // Initialize the native target in case this is the first unit test
88 // to try to build a TM.
89 OrcNativeTarget::initialize();
90 std::unique_ptr<TargetMachine> TM(
91 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
92 SmallVector<std::string, 1>()));
93 if (!TM)
94 return;
95
96 auto Obj = SimpleCompiler(*TM)(*M);
97
98 {
99 // Test with ProcessAllSections = false (the default).
100 auto K = ES.allocateVModule();
101 cantFail(ObjLayer.addObject(
102 K, MemoryBuffer::getMemBufferCopy(Obj->getBuffer())));
103 cantFail(ObjLayer.emitAndFinalize(K));
104 EXPECT_EQ(DebugSectionSeen, false)
105 << "Unexpected debug info section";
106 cantFail(ObjLayer.removeObject(K));
107 }
108
109 {
110 // Test with ProcessAllSections = true.
111 ObjLayer.setProcessAllSections(true);
112 auto K = ES.allocateVModule();
113 cantFail(ObjLayer.addObject(K, std::move(Obj)));
114 cantFail(ObjLayer.emitAndFinalize(K));
115 EXPECT_EQ(DebugSectionSeen, true)
116 << "Expected debug info section not seen";
117 cantFail(ObjLayer.removeObject(K));
118 }
119}
120
121TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
122 if (!SupportsJIT)
123 return;
124
James Y Knightc0044112019-01-13 16:09:28 +0000125 Type *Int32Ty = IntegerType::get(Context, 32);
126
Lang Hames079df9a2018-10-15 22:56:10 +0000127 ExecutionSession ES;
128
129 auto MM = std::make_shared<SectionMemoryManagerWrapper>();
130
131 std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>> Resolvers;
132
133 LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&](VModuleKey K) {
134 auto I = Resolvers.find(K);
135 assert(I != Resolvers.end() && "Missing resolver");
136 auto R = std::move(I->second);
137 Resolvers.erase(I);
138 return LegacyRTDyldObjectLinkingLayer::Resources{MM, std::move(R)};
139 });
140 SimpleCompiler Compile(*TM);
141
142 // Create a pair of modules that will trigger recursive finalization:
143 // Module 1:
144 // int bar() { return 42; }
145 // Module 2:
146 // int bar();
147 // int foo() { return bar(); }
148 //
149 // Verify that the memory manager is only finalized once (for Module 2).
150 // Failure suggests that finalize is being called on the inner RTDyld
151 // instance (for Module 1) which is unsafe, as it will prevent relocation of
152 // Module 2.
153
154 ModuleBuilder MB1(Context, "", "dummy");
155 {
156 MB1.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000157 Function *BarImpl =
158 MB1.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "bar");
Lang Hames079df9a2018-10-15 22:56:10 +0000159 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
160 IRBuilder<> Builder(BarEntry);
161 IntegerType *Int32Ty = IntegerType::get(Context, 32);
162 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
163 Builder.CreateRet(FourtyTwo);
164 }
165
166 auto Obj1 = Compile(*MB1.getModule());
167
168 ModuleBuilder MB2(Context, "", "dummy");
169 {
170 MB2.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000171 Function *BarDecl =
172 MB2.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "bar");
173 Function *FooImpl =
174 MB2.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "foo");
Lang Hames079df9a2018-10-15 22:56:10 +0000175 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
176 IRBuilder<> Builder(FooEntry);
177 Builder.CreateRet(Builder.CreateCall(BarDecl));
178 }
179 auto Obj2 = Compile(*MB2.getModule());
180
181 auto K1 = ES.allocateVModule();
182 Resolvers[K1] = std::make_shared<NullResolver>();
183 cantFail(ObjLayer.addObject(K1, std::move(Obj1)));
184
185 auto K2 = ES.allocateVModule();
186 auto LegacyLookup = [&](const std::string &Name) {
187 return ObjLayer.findSymbol(Name, true);
188 };
189
190 Resolvers[K2] = createSymbolResolver(
191 [&](const SymbolNameSet &Symbols) {
192 return cantFail(
193 getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup));
194 },
195 [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
196 const SymbolNameSet &Symbols) {
197 return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
198 });
199
200 cantFail(ObjLayer.addObject(K2, std::move(Obj2)));
201 cantFail(ObjLayer.emitAndFinalize(K2));
202 cantFail(ObjLayer.removeObject(K2));
203
204 // Finalization of module 2 should trigger finalization of module 1.
205 // Verify that finalize on SMMW is only called once.
206 EXPECT_EQ(MM->FinalizationCount, 1)
207 << "Extra call to finalize";
208}
209
210TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
211 if (!SupportsJIT)
212 return;
213
James Y Knightc0044112019-01-13 16:09:28 +0000214 Type *Int32Ty = IntegerType::get(Context, 32);
215
Lang Hames079df9a2018-10-15 22:56:10 +0000216 ExecutionSession ES;
217
218 auto MM = std::make_shared<SectionMemoryManagerWrapper>();
219
220 LegacyRTDyldObjectLinkingLayer ObjLayer(ES, [&MM](VModuleKey K) {
221 return LegacyRTDyldObjectLinkingLayer::Resources{
222 MM, std::make_shared<NullResolver>()};
223 });
224 SimpleCompiler Compile(*TM);
225
226 // Create a pair of unrelated modules:
227 //
228 // Module 1:
229 // int foo() { return 42; }
230 // Module 2:
231 // int bar() { return 7; }
232 //
233 // Both modules will share a memory manager. We want to verify that the
234 // second object is not loaded before the first one is finalized. To do this
235 // in a portable way, we abuse the
236 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
237 // called once per object before any sections are allocated.
238
239 ModuleBuilder MB1(Context, "", "dummy");
240 {
241 MB1.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000242 Function *BarImpl =
243 MB1.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "foo");
Lang Hames079df9a2018-10-15 22:56:10 +0000244 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
245 IRBuilder<> Builder(BarEntry);
246 IntegerType *Int32Ty = IntegerType::get(Context, 32);
247 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
248 Builder.CreateRet(FourtyTwo);
249 }
250
251 auto Obj1 = Compile(*MB1.getModule());
252
253 ModuleBuilder MB2(Context, "", "dummy");
254 {
255 MB2.getModule()->setDataLayout(TM->createDataLayout());
James Y Knightc0044112019-01-13 16:09:28 +0000256 Function *BarImpl =
257 MB2.createFunctionDecl(FunctionType::get(Int32Ty, {}, false), "bar");
Lang Hames079df9a2018-10-15 22:56:10 +0000258 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
259 IRBuilder<> Builder(BarEntry);
260 IntegerType *Int32Ty = IntegerType::get(Context, 32);
261 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
262 Builder.CreateRet(Seven);
263 }
264 auto Obj2 = Compile(*MB2.getModule());
265
266 auto K = ES.allocateVModule();
267 cantFail(ObjLayer.addObject(K, std::move(Obj1)));
268 cantFail(ObjLayer.addObject(ES.allocateVModule(), std::move(Obj2)));
269 cantFail(ObjLayer.emitAndFinalize(K));
270 cantFail(ObjLayer.removeObject(K));
271
272 // Only one call to needsToReserveAllocationSpace should have been made.
273 EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
274 << "More than one call to needsToReserveAllocationSpace "
275 "(multiple unrelated objects loaded prior to finalization)";
276}
277
278TEST_F(LegacyRTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
279 ExecutionSession ES;
280 LegacyRTDyldObjectLinkingLayer ObjLayer(
281 ES,
282 [](VModuleKey) {
283 return LegacyRTDyldObjectLinkingLayer::Resources{
284 nullptr, std::make_shared<NullResolver>()};
285 },
286 [](VModuleKey, const object::ObjectFile &obj,
287 const RuntimeDyld::LoadedObjectInfo &info) {});
288}
289
290} // end anonymous namespace