brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · 30718ba Raw
317 lines · cpp
1//===----- COFF_x86_64.cpp - JIT linker implementation for COFF/x86_64 ----===//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// COFF/x86_64 jit-link implementation.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"14#include "COFFLinkGraphBuilder.h"15#include "JITLinkGeneric.h"16#include "SEHFrameSupport.h"17#include "llvm/BinaryFormat/COFF.h"18#include "llvm/ExecutionEngine/JITLink/x86_64.h"19#include "llvm/Object/COFF.h"20#include "llvm/Support/Endian.h"21 22#define DEBUG_TYPE "jitlink"23 24using namespace llvm;25using namespace llvm::jitlink;26 27namespace {28 29enum EdgeKind_coff_x86_64 : Edge::Kind {30  PCRel32 = x86_64::FirstPlatformRelocation,31  Pointer32NB,32  Pointer64,33  SectionIdx16,34  SecRel32,35};36 37class COFFJITLinker_x86_64 : public JITLinker<COFFJITLinker_x86_64> {38  friend class JITLinker<COFFJITLinker_x86_64>;39 40public:41  COFFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,42                       std::unique_ptr<LinkGraph> G,43                       PassConfiguration PassConfig)44      : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}45 46private:47  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {48    return x86_64::applyFixup(G, B, E, nullptr);49  }50};51 52class COFFLinkGraphBuilder_x86_64 : public COFFLinkGraphBuilder {53private:54  Error addRelocations() override {55    LLVM_DEBUG(dbgs() << "Processing relocations:\n");56 57    for (const auto &RelSect : sections())58      if (Error Err = COFFLinkGraphBuilder::forEachRelocation(59              RelSect, this, &COFFLinkGraphBuilder_x86_64::addSingleRelocation))60        return Err;61 62    return Error::success();63  }64 65  Error addSingleRelocation(const object::RelocationRef &Rel,66                            const object::SectionRef &FixupSect,67                            Block &BlockToFix) {68    const object::coff_relocation *COFFRel = getObject().getCOFFRelocation(Rel);69    auto SymbolIt = Rel.getSymbol();70    if (SymbolIt == getObject().symbol_end()) {71      return make_error<StringError>(72          formatv("Invalid symbol index in relocation entry. "73                  "index: {0}, section: {1}",74                  COFFRel->SymbolTableIndex, FixupSect.getIndex()),75          inconvertibleErrorCode());76    }77 78    object::COFFSymbolRef COFFSymbol = getObject().getCOFFSymbol(*SymbolIt);79    COFFSymbolIndex SymIndex = getObject().getSymbolIndex(COFFSymbol);80 81    Symbol *GraphSymbol = getGraphSymbol(SymIndex);82    if (!GraphSymbol)83      return make_error<StringError>(84          formatv("Could not find symbol at given index, did you add it to "85                  "JITSymbolTable? index: {0}, section: {1}",86                  SymIndex, FixupSect.getIndex()),87          inconvertibleErrorCode());88 89    int64_t Addend = 0;90    orc::ExecutorAddr FixupAddress =91        orc::ExecutorAddr(FixupSect.getAddress()) + Rel.getOffset();92    Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();93 94    Edge::Kind Kind = Edge::Invalid;95    const char *FixupPtr = BlockToFix.getContent().data() + Offset;96    Symbol *ImageBase = GetImageBaseSymbol()(getGraph());97 98    switch (Rel.getType()) {99    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR32NB: {100      if (!ImageBase)101        ImageBase = &addImageBaseSymbol();102      Kind = EdgeKind_coff_x86_64::Pointer32NB;103      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);104      break;105    }106    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32: {107      Kind = EdgeKind_coff_x86_64::PCRel32;108      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);109      break;110    }111    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_1: {112      Kind = EdgeKind_coff_x86_64::PCRel32;113      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);114      Addend -= 1;115      break;116    }117    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_2: {118      Kind = EdgeKind_coff_x86_64::PCRel32;119      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);120      Addend -= 2;121      break;122    }123    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_3: {124      Kind = EdgeKind_coff_x86_64::PCRel32;125      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);126      Addend -= 3;127      break;128    }129    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_4: {130      Kind = EdgeKind_coff_x86_64::PCRel32;131      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);132      Addend -= 4;133      break;134    }135    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_5: {136      Kind = EdgeKind_coff_x86_64::PCRel32;137      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);138      Addend -= 5;139      break;140    }141    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR64: {142      Kind = EdgeKind_coff_x86_64::Pointer64;143      Addend = *reinterpret_cast<const support::little64_t *>(FixupPtr);144      break;145    }146    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_SECTION: {147      Kind = EdgeKind_coff_x86_64::SectionIdx16;148      Addend = *reinterpret_cast<const support::little16_t *>(FixupPtr);149      uint64_t SectionIdx = 0;150      if (COFFSymbol.isAbsolute())151        SectionIdx = getObject().getNumberOfSections() + 1;152      else153        SectionIdx = COFFSymbol.getSectionNumber();154 155      auto *AbsSym = &getGraph().addAbsoluteSymbol(156          "secidx", orc::ExecutorAddr(SectionIdx), 2, Linkage::Strong,157          Scope::Local, false);158      GraphSymbol = AbsSym;159      break;160    }161    case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_SECREL: {162      // FIXME: SECREL to external symbol should be handled163      if (!GraphSymbol->isDefined())164        return Error::success();165      Kind = EdgeKind_coff_x86_64::SecRel32;166      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);167      break;168    }169    default: {170      return make_error<JITLinkError>("Unsupported x86_64 relocation:" +171                                      formatv("{0:d}", Rel.getType()));172    }173    };174 175    Edge GE(Kind, Offset, *GraphSymbol, Addend);176    LLVM_DEBUG({177      dbgs() << "    ";178      printEdge(dbgs(), BlockToFix, GE, getCOFFX86RelocationKindName(Kind));179      dbgs() << "\n";180    });181 182    BlockToFix.addEdge(std::move(GE));183 184    return Error::success();185  }186 187public:188  COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj,189                              std::shared_ptr<orc::SymbolStringPool> SSP,190                              const Triple T, const SubtargetFeatures Features)191      : COFFLinkGraphBuilder(Obj, std::move(SSP), std::move(T),192                             std::move(Features),193                             getCOFFX86RelocationKindName) {}194};195 196class COFFLinkGraphLowering_x86_64 {197public:198  // Lowers COFF x86_64 specific edges to generic x86_64 edges.199  Error operator()(LinkGraph &G) {200    for (auto *B : G.blocks()) {201      for (auto &E : B->edges()) {202        switch (E.getKind()) {203        case EdgeKind_coff_x86_64::Pointer32NB: {204          auto ImageBase = GetImageBase(G);205          assert(ImageBase && "__ImageBase symbol must be defined");206          E.setAddend(E.getAddend() - ImageBase->getAddress().getValue());207          E.setKind(x86_64::Pointer32);208          break;209        }210        case EdgeKind_coff_x86_64::PCRel32: {211          E.setKind(x86_64::PCRel32);212          break;213        }214        case EdgeKind_coff_x86_64::Pointer64: {215          E.setKind(x86_64::Pointer64);216          break;217        }218        case EdgeKind_coff_x86_64::SectionIdx16: {219          E.setKind(x86_64::Pointer16);220          break;221        }222        case EdgeKind_coff_x86_64::SecRel32: {223          E.setAddend(E.getAddend() -224                      getSectionStart(E.getTarget().getSection()).getValue());225          E.setKind(x86_64::Pointer32);226          break;227        }228        default:229          break;230        }231      }232    }233    return Error::success();234  }235 236private:237  orc::ExecutorAddr getSectionStart(Section &Sec) {238    auto [It, Inserted] = SectionStartCache.try_emplace(&Sec);239    if (Inserted) {240      SectionRange Range(Sec);241      It->second = Range.getStart();242    }243    return It->second;244  }245 246  GetImageBaseSymbol GetImageBase;247  DenseMap<Section *, orc::ExecutorAddr> SectionStartCache;248};249} // namespace250 251namespace llvm {252namespace jitlink {253 254/// Return the string name of the given COFF x86_64 edge kind.255const char *getCOFFX86RelocationKindName(Edge::Kind R) {256  switch (R) {257  case PCRel32:258    return "PCRel32";259  case Pointer32NB:260    return "Pointer32NB";261  case Pointer64:262    return "Pointer64";263  case SectionIdx16:264    return "SectionIdx16";265  case SecRel32:266    return "SecRel32";267  default:268    return x86_64::getEdgeKindName(R);269  }270}271 272Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromCOFFObject_x86_64(273    MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {274  LLVM_DEBUG({275    dbgs() << "Building jitlink graph for new input "276           << ObjectBuffer.getBufferIdentifier() << "...\n";277  });278 279  auto COFFObj = object::ObjectFile::createCOFFObjectFile(ObjectBuffer);280  if (!COFFObj)281    return COFFObj.takeError();282 283  auto Features = (*COFFObj)->getFeatures();284  if (!Features)285    return Features.takeError();286 287  return COFFLinkGraphBuilder_x86_64(**COFFObj, std::move(SSP),288                                     (*COFFObj)->makeTriple(),289                                     std::move(*Features))290      .buildGraph();291}292 293void link_COFF_x86_64(std::unique_ptr<LinkGraph> G,294                      std::unique_ptr<JITLinkContext> Ctx) {295  PassConfiguration Config;296  const Triple &TT = G->getTargetTriple();297  if (Ctx->shouldAddDefaultTargetPasses(TT)) {298    // Add a mark-live pass.299    if (auto MarkLive = Ctx->getMarkLivePass(TT)) {300      Config.PrePrunePasses.push_back(std::move(MarkLive));301      Config.PrePrunePasses.push_back(SEHFrameKeepAlivePass(".pdata"));302    } else303      Config.PrePrunePasses.push_back(markAllSymbolsLive);304 305    // Add COFF edge lowering passes.306    Config.PreFixupPasses.push_back(COFFLinkGraphLowering_x86_64());307  }308 309  if (auto Err = Ctx->modifyPassConfig(*G, Config))310    return Ctx->notifyFailed(std::move(Err));311 312  COFFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));313}314 315} // namespace jitlink316} // namespace llvm317