brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.1 KiB · 5deebec Raw
385 lines · cpp
1//===-------- ObjectLinkingLayerTest.cpp - ObjectLinkingLayer 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 "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"10#include "llvm/ExecutionEngine/JITLink/JITLink.h"11#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"12#include "llvm/ExecutionEngine/JITLink/x86_64.h"13#include "llvm/ExecutionEngine/JITSymbol.h"14#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"15#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"16#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"17#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"18#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"19#include "llvm/Testing/Support/Error.h"20#include "gtest/gtest.h"21 22#include "OrcTestCommon.h"23 24using namespace llvm;25using namespace llvm::jitlink;26using namespace llvm::orc;27 28namespace {29 30const char BlockContentBytes[] = {0x01, 0x02, 0x03, 0x04,31                                  0x05, 0x06, 0x07, 0x08};32 33ArrayRef<char> BlockContent(BlockContentBytes);34 35class ObjectLinkingLayerTest : public testing::Test {36public:37  ~ObjectLinkingLayerTest() override {38    if (auto Err = ES.endSession())39      ES.reportError(std::move(Err));40  }41 42protected:43  ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};44  JITDylib &JD = ES.createBareJITDylib("main");45  ObjectLinkingLayer ObjLinkingLayer{46      ES, std::make_unique<InProcessMemoryManager>(4096)};47};48 49TEST_F(ObjectLinkingLayerTest, AddLinkGraph) {50  auto G = std::make_unique<LinkGraph>(51      "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"),52      SubtargetFeatures(), x86_64::getEdgeKindName);53 54  auto &Sec1 = G->createSection("__data", MemProt::Read | MemProt::Write);55  auto &B1 =56      G->createContentBlock(Sec1, BlockContent, ExecutorAddr(0x1000), 8, 0);57  G->addDefinedSymbol(B1, 4, "_X", 4, Linkage::Strong, Scope::Default, false,58                      false);59  G->addDefinedSymbol(B1, 4, "_Y", 4, Linkage::Weak, Scope::Default, false,60                      false);61  G->addDefinedSymbol(B1, 4, "_Z", 4, Linkage::Strong, Scope::Hidden, false,62                      false);63  G->addDefinedSymbol(B1, 4, "_W", 4, Linkage::Strong, Scope::Default, true,64                      false);65 66  EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G)), Succeeded());67 68  EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_X"), Succeeded());69}70 71TEST_F(ObjectLinkingLayerTest, ResourceTracker) {72  // This test transfers allocations to previously unknown ResourceTrackers,73  // while increasing the number of trackers in the ObjectLinkingLayer, which74  // may invalidate some iterators internally.75  std::vector<ResourceTrackerSP> Trackers;76  for (unsigned I = 0; I < 64; I++) {77    auto G = std::make_unique<LinkGraph>(78        "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"),79        SubtargetFeatures(), x86_64::getEdgeKindName);80 81    auto &Sec1 = G->createSection("__data", MemProt::Read | MemProt::Write);82    auto &B1 =83        G->createContentBlock(Sec1, BlockContent, ExecutorAddr(0x1000), 8, 0);84    llvm::SmallString<0> SymbolName;85    SymbolName += "_X";86    SymbolName += std::to_string(I);87    G->addDefinedSymbol(B1, 4, SymbolName, 4, Linkage::Strong, Scope::Default,88                        false, false);89 90    auto RT1 = JD.createResourceTracker();91    EXPECT_THAT_ERROR(ObjLinkingLayer.add(RT1, std::move(G)), Succeeded());92    EXPECT_THAT_EXPECTED(ES.lookup(&JD, SymbolName), Succeeded());93 94    auto RT2 = JD.createResourceTracker();95    RT1->transferTo(*RT2);96 97    Trackers.push_back(RT2);98  }99}100 101TEST_F(ObjectLinkingLayerTest, ClaimLateDefinedWeakSymbols) {102  // Check that claiming weak symbols works as expected.103  //104  // To do this we'll need a custom plugin to inject some new symbols during105  // the link.106  class TestPlugin : public ObjectLinkingLayer::Plugin {107  public:108    void modifyPassConfig(MaterializationResponsibility &MR,109                          jitlink::LinkGraph &G,110                          jitlink::PassConfiguration &Config) override {111      Config.PrePrunePasses.insert(112          Config.PrePrunePasses.begin(), [](LinkGraph &G) {113            auto *DataSec = G.findSectionByName("__data");114            auto &DataBlock = G.createContentBlock(*DataSec, BlockContent,115                                                   ExecutorAddr(0x2000), 8, 0);116            G.addDefinedSymbol(DataBlock, 4, "_x", 4, Linkage::Weak,117                               Scope::Default, false, false);118 119            auto &TextSec =120                G.createSection("__text", MemProt::Read | MemProt::Write);121            auto &FuncBlock = G.createContentBlock(TextSec, BlockContent,122                                                   ExecutorAddr(0x3000), 8, 0);123            G.addDefinedSymbol(FuncBlock, 4, "_f", 4, Linkage::Weak,124                               Scope::Default, true, false);125 126            return Error::success();127          });128    }129 130    Error notifyFailed(MaterializationResponsibility &MR) override {131      llvm_unreachable("unexpected error");132    }133 134    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {135      return Error::success();136    }137    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,138                                     ResourceKey SrcKey) override {139      llvm_unreachable("unexpected resource transfer");140    }141  };142 143  ObjLinkingLayer.addPlugin(std::make_unique<TestPlugin>());144  auto G = std::make_unique<LinkGraph>(145      "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"),146      SubtargetFeatures(), getGenericEdgeKindName);147 148  auto &DataSec = G->createSection("__data", MemProt::Read | MemProt::Write);149  auto &DataBlock =150      G->createContentBlock(DataSec, BlockContent, ExecutorAddr(0x1000), 8, 0);151  G->addDefinedSymbol(DataBlock, 4, "_anchor", 4, Linkage::Weak, Scope::Default,152                      false, true);153 154  EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G)), Succeeded());155 156  EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor"), Succeeded());157}158 159TEST_F(ObjectLinkingLayerTest, HandleErrorDuringPostAllocationPass) {160  // We want to confirm that Errors in post allocation passes correctly161  // abandon the in-flight allocation and report an error.162  class TestPlugin : public ObjectLinkingLayer::Plugin {163  public:164    ~TestPlugin() override { EXPECT_TRUE(ErrorReported); }165 166    void modifyPassConfig(MaterializationResponsibility &MR,167                          jitlink::LinkGraph &G,168                          jitlink::PassConfiguration &Config) override {169      Config.PostAllocationPasses.insert(170          Config.PostAllocationPasses.begin(), [](LinkGraph &G) {171            return make_error<StringError>("Kaboom", inconvertibleErrorCode());172          });173    }174 175    Error notifyFailed(MaterializationResponsibility &MR) override {176      ErrorReported = true;177      return Error::success();178    }179 180    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {181      return Error::success();182    }183    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,184                                     ResourceKey SrcKey) override {185      llvm_unreachable("unexpected resource transfer");186    }187 188  private:189    bool ErrorReported = false;190  };191 192  // We expect this test to generate errors. Consume them so that we don't193  // add noise to the test logs.194  ES.setErrorReporter(consumeError);195 196  ObjLinkingLayer.addPlugin(std::make_unique<TestPlugin>());197  auto G = std::make_unique<LinkGraph>(198      "foo", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"),199      SubtargetFeatures(), getGenericEdgeKindName);200 201  auto &DataSec = G->createSection("__data", MemProt::Read | MemProt::Write);202  auto &DataBlock =203      G->createContentBlock(DataSec, BlockContent, ExecutorAddr(0x1000), 8, 0);204  G->addDefinedSymbol(DataBlock, 4, "_anchor", 4, Linkage::Weak, Scope::Default,205                      false, true);206 207  EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G)), Succeeded());208 209  EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor"), Failed());210}211 212TEST_F(ObjectLinkingLayerTest, AddAndRemovePlugins) {213  class TestPlugin : public ObjectLinkingLayer::Plugin {214  public:215    TestPlugin(size_t &ActivationCount, bool &PluginDestroyed)216        : ActivationCount(ActivationCount), PluginDestroyed(PluginDestroyed) {}217 218    ~TestPlugin() override { PluginDestroyed = true; }219 220    void modifyPassConfig(MaterializationResponsibility &MR,221                          jitlink::LinkGraph &G,222                          jitlink::PassConfiguration &Config) override {223      ++ActivationCount;224    }225 226    Error notifyFailed(MaterializationResponsibility &MR) override {227      ADD_FAILURE() << "TestPlugin::notifyFailed called unexpectedly";228      return Error::success();229    }230 231    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {232      return Error::success();233    }234 235    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,236                                     ResourceKey SrcKey) override {}237 238  private:239    size_t &ActivationCount;240    bool &PluginDestroyed;241  };242 243  size_t ActivationCount = 0;244  bool PluginDestroyed = false;245 246  auto P = std::make_shared<TestPlugin>(ActivationCount, PluginDestroyed);247 248  ObjLinkingLayer.addPlugin(P);249 250  {251    auto G1 = std::make_unique<LinkGraph>(252        "G1", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"),253        SubtargetFeatures(), x86_64::getEdgeKindName);254 255    auto &DataSec = G1->createSection("__data", MemProt::Read | MemProt::Write);256    auto &DataBlock = G1->createContentBlock(DataSec, BlockContent,257                                             ExecutorAddr(0x1000), 8, 0);258    G1->addDefinedSymbol(DataBlock, 4, "_anchor1", 4, Linkage::Weak,259                         Scope::Default, false, true);260 261    EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G1)), Succeeded());262    EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor1"), Succeeded());263    EXPECT_EQ(ActivationCount, 1U);264  }265 266  ObjLinkingLayer.removePlugin(*P);267 268  {269    auto G2 = std::make_unique<LinkGraph>(270        "G2", ES.getSymbolStringPool(), Triple("x86_64-apple-darwin"),271        SubtargetFeatures(), x86_64::getEdgeKindName);272 273    auto &DataSec = G2->createSection("__data", MemProt::Read | MemProt::Write);274    auto &DataBlock = G2->createContentBlock(DataSec, BlockContent,275                                             ExecutorAddr(0x1000), 8, 0);276    G2->addDefinedSymbol(DataBlock, 4, "_anchor2", 4, Linkage::Weak,277                         Scope::Default, false, true);278 279    EXPECT_THAT_ERROR(ObjLinkingLayer.add(JD, std::move(G2)), Succeeded());280    EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_anchor2"), Succeeded());281    EXPECT_EQ(ActivationCount, 1U);282  }283 284  P.reset();285  EXPECT_TRUE(PluginDestroyed);286}287 288TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {289  class TestEPC : public UnsupportedExecutorProcessControl,290                  public DylibManager {291  public:292    TestEPC()293        : UnsupportedExecutorProcessControl(nullptr, nullptr,294                                            "x86_64-apple-darwin") {295      this->DylibMgr = this;296    }297 298    Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {299      return ExecutorAddr::fromPtr((void *)nullptr);300    }301 302    void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,303                            SymbolLookupCompleteFn Complete) override {304      std::vector<std::optional<ExecutorSymbolDef>> Result;305      EXPECT_EQ(Request.size(), 1u);306      for (auto &LR : Request) {307        EXPECT_EQ(LR.Symbols.size(), 1u);308        for (auto &Sym : LR.Symbols) {309          if (*Sym.first == "_testFunc") {310            ExecutorSymbolDef Def{ExecutorAddr::fromPtr((void *)0x1000),311                                  JITSymbolFlags::Exported};312            Result.emplace_back(Def);313          } else {314            ADD_FAILURE() << "unexpected symbol request " << *Sym.first;315          }316        }317      }318      Complete(std::vector<tpctypes::LookupResult>{1, Result});319    }320  };321 322  ExecutionSession ES{std::make_unique<TestEPC>()};323  JITDylib &JD = ES.createBareJITDylib("main");324  ObjectLinkingLayer ObjLinkingLayer{325      ES, std::make_unique<InProcessMemoryManager>(4096)};326 327  auto G = EPCDynamicLibrarySearchGenerator::GetForTargetProcess(328      ES, {}, [&](JITDylib &JD, SymbolMap Syms) {329        auto G =330            absoluteSymbolsLinkGraph(Triple("x86_64-apple-darwin"),331                                     ES.getSymbolStringPool(), std::move(Syms));332        return ObjLinkingLayer.add(JD, std::move(G));333      });334  ASSERT_THAT_EXPECTED(G, Succeeded());335  JD.addGenerator(std::move(*G));336 337  class CheckDefs : public ObjectLinkingLayer::Plugin {338  public:339    ~CheckDefs() override { EXPECT_TRUE(SawSymbolDef); }340 341    void modifyPassConfig(MaterializationResponsibility &MR,342                          jitlink::LinkGraph &G,343                          jitlink::PassConfiguration &Config) override {344      Config.PostAllocationPasses.push_back([this](LinkGraph &G) {345        unsigned SymCount = 0;346        for (Symbol *Sym : G.absolute_symbols()) {347          SymCount += 1;348          if (!Sym->hasName()) {349            ADD_FAILURE() << "unexpected unnamed symbol";350            continue;351          }352          if (*Sym->getName() == "_testFunc")353            SawSymbolDef = true;354          else355            ADD_FAILURE() << "unexpected symbol " << Sym->getName();356        }357        EXPECT_EQ(SymCount, 1u);358        return Error::success();359      });360    }361 362    Error notifyFailed(MaterializationResponsibility &MR) override {363      return Error::success();364    }365 366    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {367      return Error::success();368    }369    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,370                                     ResourceKey SrcKey) override {371      llvm_unreachable("unexpected resource transfer");372    }373 374  private:375    bool SawSymbolDef = false;376  };377 378  ObjLinkingLayer.addPlugin(std::make_unique<CheckDefs>());379 380  EXPECT_THAT_EXPECTED(ES.lookup(&JD, "_testFunc"), Succeeded());381  EXPECT_THAT_ERROR(ES.endSession(), Succeeded());382}383 384} // end anonymous namespace385