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
21using namespace llvm;
22using namespace llvm::orc;
23
24namespace {
25
26class ObjectLinkingLayerExecutionTest : public testing::Test,
27                                        public OrcExecutionTest {
28
29};
30
31class SectionMemoryManagerWrapper : public SectionMemoryManager {
32public:
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
47TEST(ObjectLinkingLayerTest, 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  ObjectLinkingLayer<> 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  std::unique_ptr<TargetMachine> TM(
79    EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
80                                 SmallVector<std::string, 1>()));
81  if (!TM)
82    return;
83
84  auto OwningObj = SimpleCompiler(*TM)(*M);
85  std::vector<object::ObjectFile*> Objs;
86  Objs.push_back(OwningObj.getBinary());
87
88  bool DebugSectionSeen = false;
89  SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
90  auto Resolver =
91    createLambdaResolver(
92      [](const std::string &Name) {
93        return RuntimeDyld::SymbolInfo(nullptr);
94      },
95      [](const std::string &Name) {
96        return RuntimeDyld::SymbolInfo(nullptr);
97      });
98
99  {
100    // Test with ProcessAllSections = false (the default).
101    auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
102    EXPECT_EQ(DebugSectionSeen, false)
103      << "Unexpected debug info section";
104    ObjLayer.removeObjectSet(H);
105  }
106
107  {
108    // Test with ProcessAllSections = true.
109    ObjLayer.setProcessAllSections(true);
110    auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
111    EXPECT_EQ(DebugSectionSeen, true)
112      << "Expected debug info section not seen";
113    ObjLayer.removeObjectSet(H);
114  }
115}
116
117TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
118  if (!TM)
119    return;
120
121  ObjectLinkingLayer<> ObjLayer;
122  SimpleCompiler Compile(*TM);
123
124  // Create a pair of modules that will trigger recursive finalization:
125  // Module 1:
126  //   int bar() { return 42; }
127  // Module 2:
128  //   int bar();
129  //   int foo() { return bar(); }
130  //
131  // Verify that the memory manager is only finalized once (for Module 2).
132  // Failure suggests that finalize is being called on the inner RTDyld
133  // instance (for Module 1) which is unsafe, as it will prevent relocation of
134  // Module 2.
135
136  ModuleBuilder MB1(Context, "", "dummy");
137  {
138    MB1.getModule()->setDataLayout(TM->createDataLayout());
139    Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
140    BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
141    IRBuilder<> Builder(BarEntry);
142    IntegerType *Int32Ty = IntegerType::get(Context, 32);
143    Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
144    Builder.CreateRet(FourtyTwo);
145  }
146
147  auto Obj1 = Compile(*MB1.getModule());
148  std::vector<object::ObjectFile*> Obj1Set;
149  Obj1Set.push_back(Obj1.getBinary());
150
151  ModuleBuilder MB2(Context, "", "dummy");
152  {
153    MB2.getModule()->setDataLayout(TM->createDataLayout());
154    Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
155    Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
156    BasicBlock *FooEntry = BasicBlock::Create(Context, "entry", 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 Sym.toRuntimeDyldSymbol();
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
186TEST_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(Context, "", "dummy");
207  {
208    MB1.getModule()->setDataLayout(TM->createDataLayout());
209    Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
210    BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
211    IRBuilder<> Builder(BarEntry);
212    IntegerType *Int32Ty = IntegerType::get(Context, 32);
213    Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
214    Builder.CreateRet(FourtyTwo);
215  }
216
217  auto Obj1 = Compile(*MB1.getModule());
218  std::vector<object::ObjectFile*> Obj1Set;
219  Obj1Set.push_back(Obj1.getBinary());
220
221  ModuleBuilder MB2(Context, "", "dummy");
222  {
223    MB2.getModule()->setDataLayout(TM->createDataLayout());
224    Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
225    BasicBlock *BarEntry = BasicBlock::Create(Context, "entry", BarImpl);
226    IRBuilder<> Builder(BarEntry);
227    IntegerType *Int32Ty = IntegerType::get(Context, 32);
228    Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
229    Builder.CreateRet(Seven);
230  }
231  auto Obj2 = Compile(*MB2.getModule());
232  std::vector<object::ObjectFile*> Obj2Set;
233  Obj2Set.push_back(Obj2.getBinary());
234
235  SectionMemoryManagerWrapper SMMW;
236  NullResolver NR;
237  auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
238  ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
239  ObjLayer.emitAndFinalize(H);
240
241  // Only one call to needsToReserveAllocationSpace should have been made.
242  EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
243      << "More than one call to needsToReserveAllocationSpace "
244         "(multiple unrelated objects loaded prior to finalization)";
245}
246
247} // end anonymous namespace
248