brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 07d9406 Raw
163 lines · cpp
1//===--- llvm-jitlink-coff.cpp -- COFF parsing support for llvm-jitlink ---===//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 parsing support for llvm-jitlink.10//11//===----------------------------------------------------------------------===//12 13#include "llvm-jitlink.h"14 15#include "llvm/Support/Error.h"16#include "llvm/Support/Path.h"17 18#define DEBUG_TYPE "llvm_jitlink"19 20using namespace llvm;21using namespace llvm::jitlink;22 23static bool isCOFFGOTSection(Section &S) { return S.getName() == "$__GOT"; }24 25static bool isCOFFStubsSection(Section &S) { return S.getName() == "$__STUBS"; }26 27static Expected<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {28  auto EItr =29      llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });30  if (EItr == B.edges().end())31    return make_error<StringError>("GOT entry in " + G.getName() + ", \"" +32                                       B.getSection().getName() +33                                       "\" has no relocations",34                                   inconvertibleErrorCode());35  return *EItr;36}37 38static Expected<Symbol &> getCOFFGOTTarget(LinkGraph &G, Block &B) {39  auto E = getFirstRelocationEdge(G, B);40  if (!E)41    return E.takeError();42  auto &TargetSym = E->getTarget();43  if (!TargetSym.hasName())44    return make_error<StringError>(45        "GOT entry in " + G.getName() + ", \"" +46            TargetSym.getBlock().getSection().getName() +47            "\" points to anonymous "48            "symbol",49        inconvertibleErrorCode());50  return TargetSym;51}52 53static Expected<Symbol &> getCOFFStubTarget(LinkGraph &G, Block &B) {54  auto E = getFirstRelocationEdge(G, B);55  if (!E)56    return E.takeError();57  auto &GOTSym = E->getTarget();58  if (!GOTSym.isDefined() || !isCOFFGOTSection(GOTSym.getBlock().getSection()))59    return make_error<StringError>(60        "Stubs entry in " + G.getName() + ", \"" +61            GOTSym.getBlock().getSection().getName() +62            "\" does not point to GOT entry",63        inconvertibleErrorCode());64  return getCOFFGOTTarget(G, GOTSym.getBlock());65}66 67namespace llvm {68Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {69  std::lock_guard<std::mutex> Lock(S.M);70 71  auto FileName = sys::path::filename(G.getName());72  auto [It, Inserted] = S.FileInfos.try_emplace(FileName);73  if (!Inserted) {74    return make_error<StringError>("When -check is passed, file names must be "75                                   "distinct (duplicate: \"" +76                                       FileName + "\")",77                                   inconvertibleErrorCode());78  }79 80  auto &FileInfo = It->second;81  LLVM_DEBUG(82      { dbgs() << "Registering COFF file info for \"" << FileName << "\"\n"; });83  for (auto &Sec : G.sections()) {84    LLVM_DEBUG({85      dbgs() << "  Section \"" << Sec.getName() << "\": "86             << (Sec.symbols().empty() ? "empty. skipping." : "processing...")87             << "\n";88    });89 90    // Skip empty sections.91    if (Sec.symbols().empty())92      continue;93 94    if (FileInfo.SectionInfos.count(Sec.getName()))95      return make_error<StringError>("Encountered duplicate section name \"" +96                                         Sec.getName() + "\" in \"" + FileName +97                                         "\"",98                                     inconvertibleErrorCode());99 100    bool isGOTSection = isCOFFGOTSection(Sec);101    bool isStubsSection = isCOFFStubsSection(Sec);102 103    bool SectionContainsContent = false;104    bool SectionContainsZeroFill = false;105 106    auto *FirstSym = *Sec.symbols().begin();107    auto *LastSym = FirstSym;108    for (auto *Sym : Sec.symbols()) {109      if (Sym->getAddress() < FirstSym->getAddress())110        FirstSym = Sym;111      if (Sym->getAddress() > LastSym->getAddress())112        LastSym = Sym;113 114      if (isGOTSection || isStubsSection) {115        if (isGOTSection) {116          // Skip the GOT start symbol117          if (Sym->getSize() != 0)118            if (Error E = FileInfo.registerGOTEntry(G, *Sym, getCOFFGOTTarget))119              return E;120        } else {121          if (Error E = FileInfo.registerStubEntry(G, *Sym, getCOFFStubTarget))122            return E;123        }124        SectionContainsContent = true;125      }126 127      if (Sym->hasName()) {128        if (Sym->isSymbolZeroFill()) {129          S.SymbolInfos[Sym->getName()] = {Sym->getSize(),130                                           Sym->getAddress().getValue()};131          SectionContainsZeroFill = true;132        } else {133          S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),134                                           Sym->getAddress().getValue(),135                                           Sym->getTargetFlags()};136          SectionContainsContent = true;137        }138      }139    }140 141    auto SecAddr = FirstSym->getAddress();142    auto SecSize =143        (LastSym->getBlock().getAddress() + LastSym->getBlock().getSize()) -144        SecAddr;145 146    if (SectionContainsZeroFill && SectionContainsContent)147      return make_error<StringError>("Mixed zero-fill and content sections not "148                                     "supported yet",149                                     inconvertibleErrorCode());150 151    if (SectionContainsZeroFill)152      FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr.getValue()};153    else154      FileInfo.SectionInfos[Sec.getName()] = {155          ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),156          SecAddr.getValue(), FirstSym->getTargetFlags()};157  }158 159  return Error::success();160}161 162} // end namespace llvm163