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 "OrcTestCommon.h"
11 #include "llvm/ExecutionEngine/ExecutionEngine.h"
12 #include "llvm/ExecutionEngine/SectionMemoryManager.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/Orc/RTDyldObjectLinkingLayer.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 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:
63     bool &DebugSeen;
64   };
65 
66   RTDyldObjectLinkingLayer<> ObjLayer;
67 
68   LLVMContext Context;
69   auto M = llvm::make_unique<Module>("", Context);
70   M->setTargetTriple("x86_64-unknown-linux-gnu");
71   Type *Int32Ty = IntegerType::get(Context, 32);
72   GlobalVariable *GV =
73     new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
74                          ConstantInt::get(Int32Ty, 42), "foo");
75 
76   GV->setSection(".debug_str");
77 
78 
79   // Initialize the native target in case this is the first unit test
80   // to try to build a TM.
81   OrcNativeTarget::initialize();
82   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;
93   SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
94   auto Resolver =
95     createLambdaResolver(
96       [](const std::string &Name) {
97         return JITSymbol(nullptr);
98       },
99       [](const std::string &Name) {
100         return JITSymbol(nullptr);
101       });
102 
103   {
104     // Test with ProcessAllSections = false (the default).
105     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
106     ObjLayer.emitAndFinalize(H);
107     EXPECT_EQ(DebugSectionSeen, false)
108       << "Unexpected debug info section";
109     ObjLayer.removeObjectSet(H);
110   }
111 
112   {
113     // Test with ProcessAllSections = true.
114     ObjLayer.setProcessAllSections(true);
115     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
116     ObjLayer.emitAndFinalize(H);
117     EXPECT_EQ(DebugSectionSeen, true)
118       << "Expected debug info section not seen";
119     ObjLayer.removeObjectSet(H);
120   }
121 }
122 
123 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
124   if (!TM)
125     return;
126 
127   RTDyldObjectLinkingLayer<> ObjLayer;
128   SimpleCompiler Compile(*TM);
129 
130   // Create a pair of modules that will trigger recursive finalization:
131   // Module 1:
132   //   int bar() { return 42; }
133   // Module 2:
134   //   int bar();
135   //   int foo() { return bar(); }
136   //
137   // Verify that the memory manager is only finalized once (for Module 2).
138   // Failure suggests that finalize is being called on the inner RTDyld
139   // instance (for Module 1) which is unsafe, as it will prevent relocation of
140   // Module 2.
141 
142   ModuleBuilder MB1(Context, "", "dummy");
143   {
144     MB1.getModule()->setDataLayout(TM->createDataLayout());
145     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
146     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
147     IRBuilder<> Builder(BarEntry);
148     IntegerType *Int32Ty = IntegerType::get(Context, 32);
149     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
150     Builder.CreateRet(FourtyTwo);
151   }
152 
153   auto Obj1 = Compile(*MB1.getModule());
154   std::vector<object::ObjectFile*> Obj1Set;
155   Obj1Set.push_back(Obj1.getBinary());
156 
157   ModuleBuilder MB2(Context, "", "dummy");
158   {
159     MB2.getModule()->setDataLayout(TM->createDataLayout());
160     Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
161     Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
162     BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", FooImpl);
163     IRBuilder<> Builder(FooEntry);
164     Builder.CreateRet(Builder.CreateCall(BarDecl));
165   }
166   auto Obj2 = Compile(*MB2.getModule());
167   std::vector<object::ObjectFile*> Obj2Set;
168   Obj2Set.push_back(Obj2.getBinary());
169 
170   auto Resolver =
171     createLambdaResolver(
172       [&](const std::string &Name) {
173         if (auto Sym = ObjLayer.findSymbol(Name, true))
174           return Sym;
175         return JITSymbol(nullptr);
176       },
177       [](const std::string &Name) {
178         return JITSymbol(nullptr);
179       });
180 
181   SectionMemoryManagerWrapper SMMW;
182   ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
183   auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
184   ObjLayer.emitAndFinalize(H);
185 
186   // Finalization of module 2 should trigger finalization of module 1.
187   // Verify that finalize on SMMW is only called once.
188   EXPECT_EQ(SMMW.FinalizationCount, 1)
189       << "Extra call to finalize";
190 }
191 
192 TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
193   if (!TM)
194     return;
195 
196   RTDyldObjectLinkingLayer<> ObjLayer;
197   SimpleCompiler Compile(*TM);
198 
199   // Create a pair of unrelated modules:
200   //
201   // Module 1:
202   //   int foo() { return 42; }
203   // Module 2:
204   //   int bar() { return 7; }
205   //
206   // Both modules will share a memory manager. We want to verify that the
207   // second object is not loaded before the first one is finalized. To do this
208   // in a portable way, we abuse the
209   // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
210   // called once per object before any sections are allocated.
211 
212   ModuleBuilder MB1(Context, "", "dummy");
213   {
214     MB1.getModule()->setDataLayout(TM->createDataLayout());
215     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
216     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
217     IRBuilder<> Builder(BarEntry);
218     IntegerType *Int32Ty = IntegerType::get(Context, 32);
219     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
220     Builder.CreateRet(FourtyTwo);
221   }
222 
223   auto Obj1 = Compile(*MB1.getModule());
224   std::vector<object::ObjectFile*> Obj1Set;
225   Obj1Set.push_back(Obj1.getBinary());
226 
227   ModuleBuilder MB2(Context, "", "dummy");
228   {
229     MB2.getModule()->setDataLayout(TM->createDataLayout());
230     Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
231     BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
232     IRBuilder<> Builder(BarEntry);
233     IntegerType *Int32Ty = IntegerType::get(Context, 32);
234     Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
235     Builder.CreateRet(Seven);
236   }
237   auto Obj2 = Compile(*MB2.getModule());
238   std::vector<object::ObjectFile*> Obj2Set;
239   Obj2Set.push_back(Obj2.getBinary());
240 
241   SectionMemoryManagerWrapper SMMW;
242   NullResolver NR;
243   auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
244   ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
245   ObjLayer.emitAndFinalize(H);
246 
247   // Only one call to needsToReserveAllocationSpace should have been made.
248   EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
249       << "More than one call to needsToReserveAllocationSpace "
250          "(multiple unrelated objects loaded prior to finalization)";
251 }
252 
253 } // end anonymous namespace
254