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