brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.3 KiB · 29eeecc Raw
425 lines · cpp
1//===----- ELF_systemz.cpp - JIT linker implementation for ELF/systemz ----===//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// ELF/systemz jit-link implementation.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"14#include "llvm/ExecutionEngine/JITLink/systemz.h"15#include "llvm/Object/ELFObjectFile.h"16 17#include "DefineExternalSectionStartAndEndSymbols.h"18#include "EHFrameSupportImpl.h"19#include "ELFLinkGraphBuilder.h"20#include "JITLinkGeneric.h"21 22#define DEBUG_TYPE "jitlink"23 24using namespace llvm;25using namespace llvm::jitlink;26 27namespace {28 29constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";30 31Error buildTables_ELF_systemz(LinkGraph &G) {32  LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");33  systemz::GOTTableManager GOT;34  systemz::PLTTableManager PLT(GOT);35  visitExistingEdges(G, GOT, PLT);36  return Error::success();37}38 39} // namespace40 41namespace llvm {42namespace jitlink {43class ELFJITLinker_systemz : public JITLinker<ELFJITLinker_systemz> {44  friend class JITLinker<ELFJITLinker_systemz>;45 46public:47  ELFJITLinker_systemz(std::unique_ptr<JITLinkContext> Ctx,48                       std::unique_ptr<LinkGraph> G,49                       PassConfiguration PassConfig)50      : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {51    if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple()))52      getPassConfig().PostAllocationPasses.push_back(53          [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });54  }55 56private:57  Symbol *GOTSymbol = nullptr;58 59  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {60    return systemz::applyFixup(G, B, E, GOTSymbol);61  }62 63  Error getOrCreateGOTSymbol(LinkGraph &G) {64    auto DefineExternalGOTSymbolIfPresent =65        createDefineExternalSectionStartAndEndSymbolsPass(66            [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {67              if (Sym.getName() != nullptr &&68                  *Sym.getName() == ELFGOTSymbolName)69                if (auto *GOTSection = G.findSectionByName(70                        systemz::GOTTableManager::getSectionName())) {71                  GOTSymbol = &Sym;72                  return {*GOTSection, true};73                }74              return {};75            });76 77    // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an78    // external.79    if (auto Err = DefineExternalGOTSymbolIfPresent(G))80      return Err;81 82    // If we succeeded then we're done.83    if (GOTSymbol)84      return Error::success();85 86    // Otherwise look for a GOT section: If it already has a start symbol we'll87    // record it, otherwise we'll create our own.88    // If there's a GOT section but we didn't find an external GOT symbol...89    if (auto *GOTSection =90            G.findSectionByName(systemz::GOTTableManager::getSectionName())) {91 92      // Check for an existing defined symbol.93      for (auto *Sym : GOTSection->symbols())94        if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) {95          GOTSymbol = Sym;96          return Error::success();97        }98 99      // If there's no defined symbol then create one.100      SectionRange SR(*GOTSection);101      if (SR.empty())102        GOTSymbol =103            &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0,104                                 Linkage::Strong, Scope::Local, true);105      else106        GOTSymbol =107            &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0,108                                Linkage::Strong, Scope::Local, false, true);109    }110 111    // If we still haven't found a GOT symbol then double check the externals.112    // We may have a GOT-relative reference but no GOT section, in which case113    // we just need to point the GOT symbol at some address in this graph.114    if (!GOTSymbol) {115      for (auto *Sym : G.external_symbols()) {116        if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) {117          auto Blocks = G.blocks();118          if (!Blocks.empty()) {119            G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());120            GOTSymbol = Sym;121            break;122          }123        }124      }125    }126 127    return Error::success();128  }129};130 131class ELFLinkGraphBuilder_systemz132    : public ELFLinkGraphBuilder<object::ELF64BE> {133private:134  using ELFT = object::ELF64BE;135  using Base = ELFLinkGraphBuilder<ELFT>;136  using Base::G; // Use LinkGraph pointer from base class.137 138  Error addRelocations() override {139    LLVM_DEBUG(dbgs() << "Processing relocations:\n");140 141    using Base = ELFLinkGraphBuilder<ELFT>;142    using Self = ELFLinkGraphBuilder_systemz;143    for (const auto &RelSect : Base::Sections) {144      if (RelSect.sh_type == ELF::SHT_REL)145        // Validate the section to read relocation entries from.146        return make_error<StringError>("No SHT_REL in valid " +147                                           G->getTargetTriple().getArchName() +148                                           " ELF object files",149                                       inconvertibleErrorCode());150 151      if (Error Err = Base::forEachRelaRelocation(RelSect, this,152                                                  &Self::addSingleRelocation))153        return Err;154    }155 156    return Error::success();157  }158 159  Error addSingleRelocation(const typename ELFT::Rela &Rel,160                            const typename ELFT::Shdr &FixupSect,161                            Block &BlockToFix) {162    using support::big32_t;163    using Base = ELFLinkGraphBuilder<ELFT>;164    auto ELFReloc = Rel.getType(false);165 166    // No reloc.167    if (LLVM_UNLIKELY(ELFReloc == ELF::R_390_NONE))168      return Error::success();169 170    uint32_t SymbolIndex = Rel.getSymbol(false);171    auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);172    if (!ObjSymbol)173      return ObjSymbol.takeError();174 175    Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);176    if (!GraphSymbol)177      return make_error<StringError>(178          formatv("Could not find symbol at given index, did you add it to "179                  "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",180                  SymbolIndex, (*ObjSymbol)->st_shndx,181                  Base::GraphSymbols.size()),182          inconvertibleErrorCode());183 184    // Validate the relocation kind.185    int64_t Addend = Rel.r_addend;186    Edge::Kind Kind = Edge::Invalid;187 188    switch (ELFReloc) {189    case ELF::R_390_PC64: {190      Kind = systemz::Delta64;191      break;192    }193    case ELF::R_390_PC32: {194      Kind = systemz::Delta32;195      break;196    }197    case ELF::R_390_PC16: {198      Kind = systemz::Delta16;199      break;200    }201    case ELF::R_390_PC32DBL: {202      Kind = systemz::Delta32dbl;203      break;204    }205    case ELF::R_390_PC24DBL: {206      Kind = systemz::Delta24dbl;207      break;208    }209    case ELF::R_390_PC16DBL: {210      Kind = systemz::Delta16dbl;211      break;212    }213    case ELF::R_390_PC12DBL: {214      Kind = systemz::Delta12dbl;215      break;216    }217    case ELF::R_390_64: {218      Kind = systemz::Pointer64;219      break;220    }221    case ELF::R_390_32: {222      Kind = systemz::Pointer32;223      break;224    }225    case ELF::R_390_20: {226      Kind = systemz::Pointer20;227      break;228    }229    case ELF::R_390_16: {230      Kind = systemz::Pointer16;231      break;232    }233    case ELF::R_390_12: {234      Kind = systemz::Pointer12;235      break;236    }237    case ELF::R_390_8: {238      Kind = systemz::Pointer8;239      break;240    }241    // Relocations targeting the PLT associated with the symbol.242    case ELF::R_390_PLT64: {243      Kind = systemz::DeltaPLT64;244      break;245    }246    case ELF::R_390_PLT32: {247      Kind = systemz::DeltaPLT32;248      break;249    }250    case ELF::R_390_PLT32DBL: {251      Kind = systemz::DeltaPLT32dbl;252      break;253    }254    case ELF::R_390_PLT24DBL: {255      Kind = systemz::DeltaPLT24dbl;256      break;257    }258    case ELF::R_390_PLT16DBL: {259      Kind = systemz::DeltaPLT16dbl;260      break;261    }262    case ELF::R_390_PLT12DBL: {263      Kind = systemz::DeltaPLT12dbl;264      break;265    }266    case ELF::R_390_PLTOFF64: {267      Kind = systemz::Delta64PLTFromGOT;268      break;269    }270    case ELF::R_390_PLTOFF32: {271      Kind = systemz::Delta32PLTFromGOT;272      break;273    }274    case ELF::R_390_PLTOFF16: {275      Kind = systemz::Delta16PLTFromGOT;276      break;277    }278    // Relocations targeting the actual symbol (just relative to the GOT).279    case ELF::R_390_GOTOFF64: {280      Kind = systemz::Delta64FromGOT;281      break;282    }283    case ELF::R_390_GOTOFF: {284      Kind = systemz::Delta32FromGOT;285      break;286    }287    case ELF::R_390_GOTOFF16: {288      Kind = systemz::Delta16FromGOT;289      break;290    }291    // Relocations targeting the GOT entry associated with the symbol.292    case ELF::R_390_GOT64:293    case ELF::R_390_GOTPLT64: {294      Kind = systemz::RequestGOTAndTransformToDelta64FromGOT;295      break;296    }297    case ELF::R_390_GOT32:298    case ELF::R_390_GOTPLT32: {299      Kind = systemz::RequestGOTAndTransformToDelta32FromGOT;300      break;301    }302    case ELF::R_390_GOT20:303    case ELF::R_390_GOTPLT20: {304      Kind = systemz::RequestGOTAndTransformToDelta20FromGOT;305      break;306    }307    case ELF::R_390_GOT16:308    case ELF::R_390_GOTPLT16: {309      Kind = systemz::RequestGOTAndTransformToDelta16FromGOT;310      break;311    }312    case ELF::R_390_GOT12:313    case ELF::R_390_GOTPLT12: {314      Kind = systemz::RequestGOTAndTransformToDelta12FromGOT;315      break;316    }317    case ELF::R_390_GOTENT:318    case ELF::R_390_GOTPLTENT: {319      Kind = systemz::RequestGOTAndTransformToDelta32dbl;320      break;321    }322    // R_390_GOTPC and R_390_GOTPCDBL don't create GOT entry, they don't even323    // have symbol.324    case ELF::R_390_GOTPC: {325      Kind = systemz::Delta32GOTBase;326      break;327    }328    case ELF::R_390_GOTPCDBL: {329      Kind = systemz::Delta32dblGOTBase;330      break;331    }332    default:333      return make_error<JITLinkError>(334          "In " + G->getName() + ": Unsupported systemz relocation type " +335          object::getELFRelocationTypeName(ELF::EM_S390, ELFReloc));336    }337    auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;338    Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();339    Edge GE(Kind, Offset, *GraphSymbol, Addend);340    LLVM_DEBUG({341      dbgs() << "    ";342      printEdge(dbgs(), BlockToFix, GE, systemz::getEdgeKindName(Kind));343      dbgs() << "\n";344    });345 346    BlockToFix.addEdge(std::move(GE));347 348    return Error::success();349  }350 351public:352  ELFLinkGraphBuilder_systemz(StringRef FileName,353                              const object::ELFFile<ELFT> &Obj,354                              std::shared_ptr<orc::SymbolStringPool> SSP,355                              Triple TT, SubtargetFeatures Features)356      : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT),357                                  std::move(Features), FileName,358                                  systemz::getEdgeKindName) {}359};360 361Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_systemz(362    MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {363  LLVM_DEBUG({364    dbgs() << "Building jitlink graph for new input "365           << ObjectBuffer.getBufferIdentifier() << "...\n";366  });367 368  auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);369  if (!ELFObj)370    return ELFObj.takeError();371 372  auto Features = (*ELFObj)->getFeatures();373  if (!Features)374    return Features.takeError();375 376  assert((*ELFObj)->getArch() == Triple::systemz &&377         "Only SystemZ is supported");378 379  auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64BE>>(**ELFObj);380  return ELFLinkGraphBuilder_systemz(381             (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP),382             (*ELFObj)->makeTriple(), std::move(*Features))383      .buildGraph();384}385 386void link_ELF_systemz(std::unique_ptr<LinkGraph> G,387                      std::unique_ptr<JITLinkContext> Ctx) {388  PassConfiguration Config;389  const Triple &TT = G->getTargetTriple();390  if (Ctx->shouldAddDefaultTargetPasses(TT)) {391    // Add eh-frame passes.392    Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));393    Config.PrePrunePasses.push_back(394        EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), systemz::Pointer32,395                         systemz::Pointer64, systemz::Delta32, systemz::Delta64,396                         systemz::NegDelta32));397    Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));398 399    // Add a mark-live pass.400    if (auto MarkLive = Ctx->getMarkLivePass(TT))401      Config.PrePrunePasses.push_back(std::move(MarkLive));402    else403      Config.PrePrunePasses.push_back(markAllSymbolsLive);404 405    // Add an in-place GOT/Stubs build pass.406    Config.PostPrunePasses.push_back(buildTables_ELF_systemz);407 408    // Resolve any external section start / end symbols.409    Config.PostAllocationPasses.push_back(410        createDefineExternalSectionStartAndEndSymbolsPass(411            identifyELFSectionStartAndEndSymbols));412 413    // TODO: Add GOT/Stubs optimizer pass.414    // Config.PreFixupPasses.push_back(systemz::optimizeGOTAndStubAccesses);415  }416 417  if (auto Err = Ctx->modifyPassConfig(*G, Config))418    return Ctx->notifyFailed(std::move(Err));419 420  ELFJITLinker_systemz::link(std::move(Ctx), std::move(G), std::move(Config));421}422 423} // namespace jitlink424} // namespace llvm425