brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.8 KiB · 61b99dd Raw
302 lines · cpp
1//===--- RTDyldObjectLinkingLayerTest.cpp - RTDyld linking layer tests ---===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "OrcTestCommon.h"10#include "llvm/ExecutionEngine/ExecutionEngine.h"11#include "llvm/ExecutionEngine/Orc/CompileUtils.h"12#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"13#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"14#include "llvm/ExecutionEngine/SectionMemoryManager.h"15#include "llvm/IR/Constants.h"16#include "llvm/IR/LLVMContext.h"17#include "gtest/gtest.h"18#include <string>19 20using namespace llvm;21using namespace llvm::orc;22 23namespace {24 25// Returns whether a non-alloc section was passed to the memory manager.26static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,27                                      bool ProcessAllSections) {28  class MemoryManagerWrapper : public SectionMemoryManager {29  public:30    MemoryManagerWrapper(bool &NonAllocSeen) : NonAllocSeen(NonAllocSeen) {}31    uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,32                                 unsigned SectionID, StringRef SectionName,33                                 bool IsReadOnly) override {34      // We check for ".note.GNU-stack" here because it is currently the only35      // non-alloc section seen in the module. If this changes in future any36      // other non-alloc section would do here.37      if (SectionName == ".note.GNU-stack")38        NonAllocSeen = true;39      return SectionMemoryManager::allocateDataSection(40          Size, Alignment, SectionID, SectionName, IsReadOnly);41    }42 43  private:44    bool &NonAllocSeen;45  };46 47  bool NonAllocSectionSeen = false;48 49  ExecutionSession ES(std::make_unique<UnsupportedExecutorProcessControl>());50  auto &JD = ES.createBareJITDylib("main");51  auto Foo = ES.intern("foo");52 53  RTDyldObjectLinkingLayer ObjLayer(54      ES, [&NonAllocSectionSeen](const MemoryBuffer &) {55        return std::make_unique<MemoryManagerWrapper>(NonAllocSectionSeen);56      });57 58  auto OnResolveDoNothing = [](Expected<SymbolMap> R) {59    cantFail(std::move(R));60  };61 62  ObjLayer.setProcessAllSections(ProcessAllSections);63  cantFail(ObjLayer.add(JD, std::move(Obj)));64  ES.lookup(LookupKind::Static, makeJITDylibSearchOrder(&JD),65            SymbolLookupSet(Foo), SymbolState::Resolved, OnResolveDoNothing,66            NoDependenciesToRegister);67 68  if (auto Err = ES.endSession())69    ES.reportError(std::move(Err));70 71  return NonAllocSectionSeen;72}73 74TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {75  LLVMContext Context;76  auto M = std::make_unique<Module>("", Context);77  M->setTargetTriple(Triple("x86_64-unknown-linux-gnu"));78 79  // These values are only here to ensure that the module is non-empty.80  // They are no longer relevant to the test.81  Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two");82  auto *GV =83      new GlobalVariable(*M, StrConstant->getType(), true,84                         GlobalValue::ExternalLinkage, StrConstant, "foo");85  GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);86  GV->setAlignment(Align(1));87 88  // Initialize the native target in case this is the first unit test89  // to try to build a TM.90  OrcNativeTarget::initialize();91  std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget(92      M->getTargetTriple(), "", "", SmallVector<std::string, 1>()));93  if (!TM)94    GTEST_SKIP();95 96  auto Obj = cantFail(SimpleCompiler(*TM)(*M));97 98  EXPECT_FALSE(testSetProcessAllSections(99      MemoryBuffer::getMemBufferCopy(Obj->getBuffer()), false))100      << "Non-alloc section seen despite ProcessAllSections being false";101  EXPECT_TRUE(testSetProcessAllSections(std::move(Obj), true))102      << "Expected to see non-alloc section when ProcessAllSections is true";103}104 105TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {106 107  OrcNativeTarget::initialize();108 109  std::unique_ptr<TargetMachine> TM(110      EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",111                                   SmallVector<std::string, 1>()));112 113  if (!TM)114    GTEST_SKIP();115 116  // Our compiler is going to modify symbol visibility settings without telling117  // ORC. This will test our ability to override the flags later.118  class FunkySimpleCompiler : public SimpleCompiler {119  public:120    FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}121 122    Expected<CompileResult> operator()(Module &M) override {123      auto *Foo = M.getFunction("foo");124      assert(Foo && "Expected function Foo not found");125      Foo->setVisibility(GlobalValue::HiddenVisibility);126      return SimpleCompiler::operator()(M);127    }128  };129 130  // Create a module with two void() functions: foo and bar.131  ThreadSafeModule M;132  {133    auto Ctx = std::make_unique<LLVMContext>();134    ModuleBuilder MB(*Ctx, TM->getTargetTriple().str(), "dummy");135    MB.getModule()->setDataLayout(TM->createDataLayout());136 137    Function *FooImpl = MB.createFunctionDecl(138        FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "foo");139    BasicBlock *FooEntry = BasicBlock::Create(*Ctx, "entry", FooImpl);140    IRBuilder<> B1(FooEntry);141    B1.CreateRetVoid();142 143    Function *BarImpl = MB.createFunctionDecl(144        FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "bar");145    BasicBlock *BarEntry = BasicBlock::Create(*Ctx, "entry", BarImpl);146    IRBuilder<> B2(BarEntry);147    B2.CreateRetVoid();148 149    M = ThreadSafeModule(MB.takeModule(), std::move(Ctx));150  }151 152  // Create a simple stack and set the override flags option.153  ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};154  auto &JD = ES.createBareJITDylib("main");155  auto Foo = ES.intern("foo");156  RTDyldObjectLinkingLayer ObjLayer(ES, [](const MemoryBuffer &) {157    return std::make_unique<SectionMemoryManager>();158  });159  IRCompileLayer CompileLayer(ES, ObjLayer,160                              std::make_unique<FunkySimpleCompiler>(*TM));161 162  ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);163 164  cantFail(CompileLayer.add(JD, std::move(M)));165  ES.lookup(166      LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),167      SymbolState::Resolved,168      [](Expected<SymbolMap> R) { cantFail(std::move(R)); },169      NoDependenciesToRegister);170 171  if (auto Err = ES.endSession())172    ES.reportError(std::move(Err));173}174 175TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {176 177  OrcNativeTarget::initialize();178 179  std::unique_ptr<TargetMachine> TM(180      EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",181                                   SmallVector<std::string, 1>()));182 183  if (!TM)184    GTEST_SKIP();185 186  // Our compiler is going to add a new symbol without telling ORC.187  // This will test our ability to auto-claim responsibility later.188  class FunkySimpleCompiler : public SimpleCompiler {189  public:190    FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {}191 192    Expected<CompileResult> operator()(Module &M) override {193      Function *BarImpl = Function::Create(194          FunctionType::get(Type::getVoidTy(M.getContext()), {}, false),195          GlobalValue::ExternalLinkage, "bar", &M);196      BasicBlock *BarEntry =197          BasicBlock::Create(M.getContext(), "entry", BarImpl);198      IRBuilder<> B(BarEntry);199      B.CreateRetVoid();200 201      return SimpleCompiler::operator()(M);202    }203  };204 205  // Create a module with two void() functions: foo and bar.206  ThreadSafeModule M;207  {208    auto Ctx = std::make_unique<LLVMContext>();209    ModuleBuilder MB(*Ctx, TM->getTargetTriple().str(), "dummy");210    MB.getModule()->setDataLayout(TM->createDataLayout());211 212    Function *FooImpl = MB.createFunctionDecl(213        FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "foo");214    BasicBlock *FooEntry = BasicBlock::Create(*Ctx, "entry", FooImpl);215    IRBuilder<> B(FooEntry);216    B.CreateRetVoid();217 218    M = ThreadSafeModule(MB.takeModule(), std::move(Ctx));219  }220 221  // Create a simple stack and set the override flags option.222  ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};223  auto &JD = ES.createBareJITDylib("main");224  auto Foo = ES.intern("foo");225  RTDyldObjectLinkingLayer ObjLayer(ES, [](const MemoryBuffer &) {226    return std::make_unique<SectionMemoryManager>();227  });228  IRCompileLayer CompileLayer(ES, ObjLayer,229                              std::make_unique<FunkySimpleCompiler>(*TM));230 231  ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);232 233  cantFail(CompileLayer.add(JD, std::move(M)));234  ES.lookup(235      LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),236      SymbolState::Resolved,237      [](Expected<SymbolMap> R) { cantFail(std::move(R)); },238      NoDependenciesToRegister);239 240  if (auto Err = ES.endSession())241    ES.reportError(std::move(Err));242}243 244TEST(RTDyldObjectLinkingLayerTest, TestMemoryBufferNamePropagation) {245  OrcNativeTarget::initialize();246 247  std::unique_ptr<TargetMachine> TM(248      EngineBuilder().selectTarget(Triple("x86_64-unknown-linux-gnu"), "", "",249                                   SmallVector<std::string, 1>()));250 251  if (!TM)252    GTEST_SKIP();253 254  // Create a module with two void() functions: foo and bar.255  ThreadSafeModule M;256  {257    auto Ctx = std::make_unique<LLVMContext>();258    ModuleBuilder MB(*Ctx, TM->getTargetTriple().str(), "dummy");259    MB.getModule()->setDataLayout(TM->createDataLayout());260 261    Function *FooImpl = MB.createFunctionDecl(262        FunctionType::get(Type::getVoidTy(*Ctx), {}, false), "foo");263    BasicBlock *FooEntry = BasicBlock::Create(*Ctx, "entry", FooImpl);264    IRBuilder<> B1(FooEntry);265    B1.CreateRetVoid();266 267    M = ThreadSafeModule(MB.takeModule(), std::move(Ctx));268  }269 270  ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};271  auto &JD = ES.createBareJITDylib("main");272  auto Foo = ES.intern("foo");273  std::string ObjectIdentifer;274 275  RTDyldObjectLinkingLayer ObjLayer(276      ES, [&ObjectIdentifer](const MemoryBuffer &Obj) {277        // Capture the name of the object so that we can confirm that it278        // contains the module name.279        ObjectIdentifer = Obj.getBufferIdentifier().str();280        return std::make_unique<SectionMemoryManager>();281      });282  IRCompileLayer CompileLayer(ES, ObjLayer,283                              std::make_unique<SimpleCompiler>(*TM));284 285  // Capture the module name before we move the module.286  std::string ModuleName = M.getModuleUnlocked()->getName().str();287 288  cantFail(CompileLayer.add(JD, std::move(M)));289  ES.lookup(290      LookupKind::Static, makeJITDylibSearchOrder(&JD), SymbolLookupSet(Foo),291      SymbolState::Resolved,292      [](Expected<SymbolMap> R) { cantFail(std::move(R)); },293      NoDependenciesToRegister);294 295  if (auto Err = ES.endSession())296    ES.reportError(std::move(Err));297 298  EXPECT_TRUE(ObjectIdentifer.find(ModuleName) != std::string::npos);299}300 301} // end anonymous namespace302