1 //===- 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/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 
21 using namespace llvm;
22 using namespace llvm::orc;
23 
24 namespace {
25 
26 class RTDyldObjectLinkingLayerExecutionTest : 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(RTDyldObjectLinkingLayerTest, 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   RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
70 
71   LLVMContext Context;
72   auto M = llvm::make_unique<Module>("", Context);
73   M->setTargetTriple("x86_64-unknown-linux-gnu");
74   Type *Int32Ty = IntegerType::get(Context, 32);
75   GlobalVariable *GV =
76     new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
77                          ConstantInt::get(Int32Ty, 42), "foo");
78 
79   GV->setSection(".debug_str");
80 
81 
82   // Initialize the native target in case this is the first unit test
83   // to try to build a TM.
84   OrcNativeTarget::initialize();
85   std::unique_ptr<TargetMachine> TM(
86     EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
87                                  SmallVector<std::string, 1>()));
88   if (!TM)
89     return;
90 
91   auto Obj =
92     std::make_shared<object::OwningBinary<object::ObjectFile>>(
93       SimpleCompiler(*TM)(*M));
94 
95   auto Resolver =
96     createLambdaResolver(
97       [](const std::string &Name) {
98         return JITSymbol(nullptr);
99       },
100       [](const std::string &Name) {
101         return JITSymbol(nullptr);
102       });
103 
104   {
105     // Test with ProcessAllSections = false (the default).
106     auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
107     cantFail(ObjLayer.emitAndFinalize(H));
108     EXPECT_EQ(DebugSectionSeen, false)
109       << "Unexpected debug info section";
110     cantFail(ObjLayer.removeObject(H));
111   }
112 
113   {
114     // Test with ProcessAllSections = true.
115     ObjLayer.setProcessAllSections(true);
116     auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
117     cantFail(ObjLayer.emitAndFinalize(H));
118     EXPECT_EQ(DebugSectionSeen, true)
119       << "Expected debug info section not seen";
120     cantFail(ObjLayer.removeObject(H));
121   }
122 }
123 
124 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
125   if (!TM)
126     return;
127 
128   auto MM = std::make_shared<SectionMemoryManagerWrapper>();
129 
130   RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
131   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(); }
139   //
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.
144 
145   ModuleBuilder MB1(Context, "", "dummy");
146   {
147     MB1.getModule()->setDataLayout(TM->createDataLayout());
148     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
149     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
150     IRBuilder<> Builder(BarEntry);
151     IntegerType *Int32Ty = IntegerType::get(Context, 32);
152     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
153     Builder.CreateRet(FourtyTwo);
154   }
155 
156   auto Obj1 =
157     std::make_shared<object::OwningBinary<object::ObjectFile>>(
158       Compile(*MB1.getModule()));
159 
160   ModuleBuilder MB2(Context, "", "dummy");
161   {
162     MB2.getModule()->setDataLayout(TM->createDataLayout());
163     Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
164     Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
165     BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
166     IRBuilder<> Builder(FooEntry);
167     Builder.CreateRet(Builder.CreateCall(BarDecl));
168   }
169   auto Obj2 =
170     std::make_shared<object::OwningBinary<object::ObjectFile>>(
171       Compile(*MB2.getModule()));
172 
173   auto Resolver =
174     createLambdaResolver(
175       [&](const std::string &Name) {
176         if (auto Sym = ObjLayer.findSymbol(Name, true))
177           return Sym;
178         return JITSymbol(nullptr);
179       },
180       [](const std::string &Name) {
181         return JITSymbol(nullptr);
182       });
183 
184   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 
189   // Finalization of module 2 should trigger finalization of module 1.
190   // Verify that finalize on SMMW is only called once.
191   EXPECT_EQ(MM->FinalizationCount, 1)
192       << "Extra call to finalize";
193 }
194 
195 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
196   if (!TM)
197     return;
198 
199   auto MM = std::make_shared<SectionMemoryManagerWrapper>();
200 
201   RTDyldObjectLinkingLayer ObjLayer([&MM]() { return MM; });
202   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 
217   ModuleBuilder MB1(Context, "", "dummy");
218   {
219     MB1.getModule()->setDataLayout(TM->createDataLayout());
220     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
221     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
222     IRBuilder<> Builder(BarEntry);
223     IntegerType *Int32Ty = IntegerType::get(Context, 32);
224     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
225     Builder.CreateRet(FourtyTwo);
226   }
227 
228   auto Obj1 =
229     std::make_shared<object::OwningBinary<object::ObjectFile>>(
230       Compile(*MB1.getModule()));
231 
232   ModuleBuilder MB2(Context, "", "dummy");
233   {
234     MB2.getModule()->setDataLayout(TM->createDataLayout());
235     Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
236     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
237     IRBuilder<> Builder(BarEntry);
238     IntegerType *Int32Ty = IntegerType::get(Context, 32);
239     Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
240     Builder.CreateRet(Seven);
241   }
242   auto Obj2 =
243     std::make_shared<object::OwningBinary<object::ObjectFile>>(
244       Compile(*MB2.getModule()));
245 
246   auto NR = std::make_shared<NullResolver>();
247   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 
252   // Only one call to needsToReserveAllocationSpace should have been made.
253   EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
254       << "More than one call to needsToReserveAllocationSpace "
255          "(multiple unrelated objects loaded prior to finalization)";
256 }
257 
258 TEST_F(RTDyldObjectLinkingLayerExecutionTest, TestNotifyLoadedSignature) {
259   RTDyldObjectLinkingLayer ObjLayer(
260       []() { return nullptr; },
261       [](RTDyldObjectLinkingLayer::ObjHandleT,
262          const RTDyldObjectLinkingLayer::ObjectPtr &obj,
263          const RuntimeDyld::LoadedObjectInfo &info) {});
264 }
265 
266 } // end anonymous namespace
267