1 //===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===//
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/ObjectLinkingLayer.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 ObjectLinkingLayerExecutionTest : public testing::Test,
27                                         public OrcExecutionTest {
28 };
29 
30 class SectionMemoryManagerWrapper : public SectionMemoryManager {
31 public:
32   int FinalizationCount = 0;
33   int NeedsToReserveAllocationSpaceCount = 0;
34 
35   bool needsToReserveAllocationSpace() override {
36     ++NeedsToReserveAllocationSpaceCount;
37     return SectionMemoryManager::needsToReserveAllocationSpace();
38   }
39 
40   bool finalizeMemory(std::string *ErrMsg = 0) override {
41     ++FinalizationCount;
42     return SectionMemoryManager::finalizeMemory(ErrMsg);
43   }
44 };
45 
46 TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
47 
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   ObjectLinkingLayer<> ObjLayer;
67 
68   auto M = llvm::make_unique<Module>("", getGlobalContext());
69   M->setTargetTriple("x86_64-unknown-linux-gnu");
70   Type *Int32Ty = IntegerType::get(getGlobalContext(), 32);
71   GlobalVariable *GV =
72     new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
73                          ConstantInt::get(Int32Ty, 42), "foo");
74 
75   GV->setSection(".debug_str");
76 
77   std::unique_ptr<TargetMachine> TM(
78     EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
79                                  SmallVector<std::string, 1>()));
80   if (!TM)
81     return;
82 
83   auto OwningObj = SimpleCompiler(*TM)(*M);
84   std::vector<object::ObjectFile*> Objs;
85   Objs.push_back(OwningObj.getBinary());
86 
87   bool DebugSectionSeen = false;
88   SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
89   auto Resolver =
90     createLambdaResolver(
91       [](const std::string &Name) {
92         return RuntimeDyld::SymbolInfo(nullptr);
93       },
94       [](const std::string &Name) {
95         return RuntimeDyld::SymbolInfo(nullptr);
96       });
97 
98   {
99     // Test with ProcessAllSections = false (the default).
100     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
101     EXPECT_EQ(DebugSectionSeen, false)
102       << "Unexpected debug info section";
103     ObjLayer.removeObjectSet(H);
104   }
105 
106   {
107     // Test with ProcessAllSections = true.
108     ObjLayer.setProcessAllSections(true);
109     auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
110     EXPECT_EQ(DebugSectionSeen, true)
111       << "Expected debug info section not seen";
112     ObjLayer.removeObjectSet(H);
113   }
114 }
115 
116 
117 TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
118 
119   if (!TM)
120     return;
121 
122   ObjectLinkingLayer<> ObjLayer;
123   SimpleCompiler Compile(*TM);
124 
125   // Create a pair of modules that will trigger recursive finalization:
126   // Module 1:
127   //   int bar() { return 42; }
128   // Module 2:
129   //   int bar();
130   //   int foo() { return bar(); }
131   //
132   // Verify that the memory manager is only finalized once (for Module 2).
133   // Failure suggests that finalize is being called on the inner RTDyld
134   // instance (for Module 1) which is unsafe, as it will prevent relocation of
135   // Module 2.
136 
137   ModuleBuilder MB1(getGlobalContext(), "", "dummy");
138   {
139     MB1.getModule()->setDataLayout(TM->createDataLayout());
140     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
141     BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
142                                               BarImpl);
143     IRBuilder<> Builder(BarEntry);
144     IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
145     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
146     Builder.CreateRet(FourtyTwo);
147   }
148 
149   auto Obj1 = Compile(*MB1.getModule());
150   std::vector<object::ObjectFile*> Obj1Set;
151   Obj1Set.push_back(Obj1.getBinary());
152 
153   ModuleBuilder MB2(getGlobalContext(), "", "dummy");
154   {
155     MB2.getModule()->setDataLayout(TM->createDataLayout());
156     Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
157     Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
158     BasicBlock *FooEntry = BasicBlock::Create(getGlobalContext(), "entry",
159                                               FooImpl);
160     IRBuilder<> Builder(FooEntry);
161     Builder.CreateRet(Builder.CreateCall(BarDecl));
162   }
163   auto Obj2 = Compile(*MB2.getModule());
164   std::vector<object::ObjectFile*> Obj2Set;
165   Obj2Set.push_back(Obj2.getBinary());
166 
167   auto Resolver =
168     createLambdaResolver(
169       [&](const std::string &Name) {
170         if (auto Sym = ObjLayer.findSymbol(Name, true))
171           return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
172         return RuntimeDyld::SymbolInfo(nullptr);
173       },
174       [](const std::string &Name) {
175         return RuntimeDyld::SymbolInfo(nullptr);
176       });
177 
178   SectionMemoryManagerWrapper SMMW;
179   ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
180   auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
181   ObjLayer.emitAndFinalize(H);
182 
183   // Finalization of module 2 should trigger finalization of module 1.
184   // Verify that finalize on SMMW is only called once.
185   EXPECT_EQ(SMMW.FinalizationCount, 1)
186       << "Extra call to finalize";
187 }
188 
189 TEST_F(ObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
190 
191   if (!TM)
192     return;
193 
194   ObjectLinkingLayer<> ObjLayer;
195   SimpleCompiler Compile(*TM);
196 
197   // Create a pair of unrelated modules:
198   //
199   // Module 1:
200   //   int foo() { return 42; }
201   // Module 2:
202   //   int bar() { return 7; }
203   //
204   // Both modules will share a memory manager. We want to verify that the
205   // second object is not loaded before the first one is finalized. To do this
206   // in a portable way, we abuse the
207   // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
208   // called once per object before any sections are allocated.
209 
210   ModuleBuilder MB1(getGlobalContext(), "", "dummy");
211   {
212     MB1.getModule()->setDataLayout(TM->createDataLayout());
213     Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
214     BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
215                                               BarImpl);
216     IRBuilder<> Builder(BarEntry);
217     IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
218     Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
219     Builder.CreateRet(FourtyTwo);
220   }
221 
222   auto Obj1 = Compile(*MB1.getModule());
223   std::vector<object::ObjectFile*> Obj1Set;
224   Obj1Set.push_back(Obj1.getBinary());
225 
226   ModuleBuilder MB2(getGlobalContext(), "", "dummy");
227   {
228     MB2.getModule()->setDataLayout(TM->createDataLayout());
229     Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
230     BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
231                                               BarImpl);
232     IRBuilder<> Builder(BarEntry);
233     IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 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 }
254