Home | History | Annotate | Download | only in Orc
      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 
     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(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 
    117 TEST_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 
    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(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