blob: 132681ecc1960a4785fa46b90e59403e8caf4daa [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 Hames5b518162017-07-04 04:42:30 +000048 class MemoryManagerWrapper : public SectionMemoryManager {
Lang Hames5f7fcef2015-10-29 03:53:42 +000049 public:
Lang Hames5b518162017-07-04 04:42:30 +000050 MemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
Lang Hames5f7fcef2015-10-29 03:53:42 +000051 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 Hames5b518162017-07-04 04:42:30 +000066 bool DebugSectionSeen = false;
67 auto MM = std::make_shared<MemoryManagerWrapper>(DebugSectionSeen);
68
69 RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
Lang Hames5f7fcef2015-10-29 03:53:42 +000070
Mehdi Amini03b42e42016-04-14 21:59:01 +000071 LLVMContext Context;
72 auto M = llvm::make_unique<Module>("", Context);
Lang Hames5f7fcef2015-10-29 03:53:42 +000073 M->setTargetTriple("x86_64-unknown-linux-gnu");
Mehdi Amini03b42e42016-04-14 21:59:01 +000074 Type *Int32Ty = IntegerType::get(Context, 32);
Lang Hames5f7fcef2015-10-29 03:53:42 +000075 GlobalVariable *GV =
76 new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
77 ConstantInt::get(Int32Ty, 42), "foo");
78
79 GV->setSection(".debug_str");
80
Lang Hamesd22bade2017-04-04 17:03:49 +000081
82 // Initialize the native target in case this is the first unit test
83 // to try to build a TM.
84 OrcNativeTarget::initialize();
Lang Hames5f7fcef2015-10-29 03:53:42 +000085 std::unique_ptr<TargetMachine> TM(
86 EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
87 SmallVector<std::string, 1>()));
88 if (!TM)
89 return;
90
Lang Hames26620222017-06-22 21:06:54 +000091 auto Obj =
92 std::make_shared<object::OwningBinary<object::ObjectFile>>(
93 SimpleCompiler(*TM)(*M));
Lang Hames5f7fcef2015-10-29 03:53:42 +000094
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 Hames4ce98662017-07-07 02:59:13 +0000106 auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
107 cantFail(ObjLayer.emitAndFinalize(H));
Lang Hames5f7fcef2015-10-29 03:53:42 +0000108 EXPECT_EQ(DebugSectionSeen, false)
109 << "Unexpected debug info section";
Lang Hames4ce98662017-07-07 02:59:13 +0000110 cantFail(ObjLayer.removeObject(H));
Lang Hames5f7fcef2015-10-29 03:53:42 +0000111 }
112
113 {
114 // Test with ProcessAllSections = true.
115 ObjLayer.setProcessAllSections(true);
Lang Hames4ce98662017-07-07 02:59:13 +0000116 auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
117 cantFail(ObjLayer.emitAndFinalize(H));
Lang Hames5f7fcef2015-10-29 03:53:42 +0000118 EXPECT_EQ(DebugSectionSeen, true)
119 << "Expected debug info section not seen";
Lang Hames4ce98662017-07-07 02:59:13 +0000120 cantFail(ObjLayer.removeObject(H));
Lang Hames5f7fcef2015-10-29 03:53:42 +0000121 }
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 Hames5b518162017-07-04 04:42:30 +0000128 auto MM = std::make_shared<SectionMemoryManagerWrapper>();
129
130 RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
Lang Hames859d73c2016-01-09 19:50:40 +0000131 SimpleCompiler Compile(*TM);
132
133 // Create a pair of modules that will trigger recursive finalization:
134 // Module 1:
135 // int bar() { return 42; }
136 // Module 2:
137 // int bar();
138 // int foo() { return bar(); }
Lang Hames133f1532016-01-18 01:00:19 +0000139 //
140 // Verify that the memory manager is only finalized once (for Module 2).
141 // Failure suggests that finalize is being called on the inner RTDyld
142 // instance (for Module 1) which is unsafe, as it will prevent relocation of
143 // Module 2.
Lang Hames859d73c2016-01-09 19:50:40 +0000144
Mehdi Amini03b42e42016-04-14 21:59:01 +0000145 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000146 {
147 MB1.getModule()->setDataLayout(TM->createDataLayout());
148 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000149 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000150 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000151 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames859d73c2016-01-09 19:50:40 +0000152 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
153 Builder.CreateRet(FourtyTwo);
154 }
155
Lang Hames26620222017-06-22 21:06:54 +0000156 auto Obj1 =
157 std::make_shared<object::OwningBinary<object::ObjectFile>>(
158 Compile(*MB1.getModule()));
Lang Hames859d73c2016-01-09 19:50:40 +0000159
Mehdi Amini03b42e42016-04-14 21:59:01 +0000160 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames859d73c2016-01-09 19:50:40 +0000161 {
162 MB2.getModule()->setDataLayout(TM->createDataLayout());
163 Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
164 Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000165 BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
Lang Hames859d73c2016-01-09 19:50:40 +0000166 IRBuilder<> Builder(FooEntry);
167 Builder.CreateRet(Builder.CreateCall(BarDecl));
168 }
Lang Hames26620222017-06-22 21:06:54 +0000169 auto Obj2 =
170 std::make_shared<object::OwningBinary<object::ObjectFile>>(
171 Compile(*MB2.getModule()));
Lang Hames859d73c2016-01-09 19:50:40 +0000172
173 auto Resolver =
174 createLambdaResolver(
175 [&](const std::string &Name) {
176 if (auto Sym = ObjLayer.findSymbol(Name, true))
Lang Hamesad4a9112016-08-01 20:49:11 +0000177 return Sym;
178 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000179 },
180 [](const std::string &Name) {
Lang Hamesad4a9112016-08-01 20:49:11 +0000181 return JITSymbol(nullptr);
Lang Hames859d73c2016-01-09 19:50:40 +0000182 });
183
Lang Hames4ce98662017-07-07 02:59:13 +0000184 cantFail(ObjLayer.addObject(std::move(Obj1), Resolver));
185 auto H = cantFail(ObjLayer.addObject(std::move(Obj2), Resolver));
186 cantFail(ObjLayer.emitAndFinalize(H));
187 cantFail(ObjLayer.removeObject(H));
188
Lang Hames859d73c2016-01-09 19:50:40 +0000189 // Finalization of module 2 should trigger finalization of module 1.
190 // Verify that finalize on SMMW is only called once.
Lang Hames5b518162017-07-04 04:42:30 +0000191 EXPECT_EQ(MM->FinalizationCount, 1)
Lang Hames859d73c2016-01-09 19:50:40 +0000192 << "Extra call to finalize";
193}
194
Lang Hames67de5d22017-02-20 05:45:14 +0000195TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
Lang Hames2fe7acb2016-01-19 21:06:38 +0000196 if (!TM)
197 return;
198
Lang Hames5b518162017-07-04 04:42:30 +0000199 auto MM = std::make_shared<SectionMemoryManagerWrapper>();
200
201 RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
Lang Hames2fe7acb2016-01-19 21:06:38 +0000202 SimpleCompiler Compile(*TM);
203
204 // Create a pair of unrelated modules:
205 //
206 // Module 1:
207 // int foo() { return 42; }
208 // Module 2:
209 // int bar() { return 7; }
210 //
211 // Both modules will share a memory manager. We want to verify that the
212 // second object is not loaded before the first one is finalized. To do this
213 // in a portable way, we abuse the
214 // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
215 // called once per object before any sections are allocated.
216
Mehdi Amini03b42e42016-04-14 21:59:01 +0000217 ModuleBuilder MB1(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000218 {
219 MB1.getModule()->setDataLayout(TM->createDataLayout());
220 Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000221 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000222 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000223 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000224 Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
225 Builder.CreateRet(FourtyTwo);
226 }
227
Lang Hames26620222017-06-22 21:06:54 +0000228 auto Obj1 =
229 std::make_shared<object::OwningBinary<object::ObjectFile>>(
230 Compile(*MB1.getModule()));
Lang Hames2fe7acb2016-01-19 21:06:38 +0000231
Mehdi Amini03b42e42016-04-14 21:59:01 +0000232 ModuleBuilder MB2(Context, "", "dummy");
Lang Hames2fe7acb2016-01-19 21:06:38 +0000233 {
234 MB2.getModule()->setDataLayout(TM->createDataLayout());
235 Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
Mehdi Amini03b42e42016-04-14 21:59:01 +0000236 BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000237 IRBuilder<> Builder(BarEntry);
Mehdi Amini03b42e42016-04-14 21:59:01 +0000238 IntegerType *Int32Ty = IntegerType::get(Context, 32);
Lang Hames2fe7acb2016-01-19 21:06:38 +0000239 Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
240 Builder.CreateRet(Seven);
241 }
Lang Hames26620222017-06-22 21:06:54 +0000242 auto Obj2 =
243 std::make_shared<object::OwningBinary<object::ObjectFile>>(
244 Compile(*MB2.getModule()));
Lang Hames2fe7acb2016-01-19 21:06:38 +0000245
Lang Hames5b518162017-07-04 04:42:30 +0000246 auto NR = std::make_shared<NullResolver>();
Lang Hames4ce98662017-07-07 02:59:13 +0000247 auto H = cantFail(ObjLayer.addObject(std::move(Obj1), NR));
248 cantFail(ObjLayer.addObject(std::move(Obj2), NR));
249 cantFail(ObjLayer.emitAndFinalize(H));
250 cantFail(ObjLayer.removeObject(H));
251
Lang Hames2fe7acb2016-01-19 21:06:38 +0000252 // Only one call to needsToReserveAllocationSpace should have been made.
Lang Hames5b518162017-07-04 04:42:30 +0000253 EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
Lang Hames2fe7acb2016-01-19 21:06:38 +0000254 << "More than one call to needsToReserveAllocationSpace "
255 "(multiple unrelated objects loaded prior to finalization)";
256}
257
Lang Hames705db632017-09-28 17:43:07 +0000258TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
259 RTDyldObjectLinkingLayer ObjLayer([]() { return nullptr; },
260 [this](decltype(ObjLayer)::ObjHandleT,
261 const decltype(ObjLayer)::ObjectPtr &obj,
262 const RuntimeDyld::LoadedObjectInfo &info) {
263 });
264}
265
Eugene Zelenko6ac3f732016-01-26 18:48:36 +0000266} // end anonymous namespace