brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 8bd17eb Raw
204 lines · cpp
1//===---- llvm-jitlink-elf.cpp -- ELF 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// ELF 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 isELFGOTSection(Section &S) { return S.getName() == "$__GOT"; }24 25static bool isELFStubsSection(Section &S) { return S.getName() == "$__STUBS"; }26 27static bool isELFAArch32StubsSection(Section &S) {28  return S.getName().starts_with("__llvm_jitlink_aarch32_STUBS_");29}30 31static Expected<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {32  auto EItr =33      llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });34  if (EItr == B.edges().end())35    return make_error<StringError>("GOT entry in " + G.getName() + ", \"" +36                                       B.getSection().getName() +37                                       "\" has no relocations",38                                   inconvertibleErrorCode());39  return *EItr;40}41 42static Expected<Symbol &> getELFGOTTarget(LinkGraph &G, Block &B) {43  auto E = getFirstRelocationEdge(G, B);44  if (!E)45    return E.takeError();46  auto &TargetSym = E->getTarget();47  if (!TargetSym.hasName())48    return make_error<StringError>(49        "GOT entry in " + G.getName() + ", \"" +50            TargetSym.getBlock().getSection().getName() +51            "\" points to anonymous "52            "symbol",53        inconvertibleErrorCode());54  return TargetSym;55}56 57static Expected<Symbol &> getELFStubTarget(LinkGraph &G, Block &B) {58  auto E = getFirstRelocationEdge(G, B);59  if (!E)60    return E.takeError();61  auto &GOTSym = E->getTarget();62  if (!GOTSym.isDefined())63    return make_error<StringError>("Stubs entry in " + G.getName() +64                                       " does not point to GOT entry",65                                   inconvertibleErrorCode());66  if (!isELFGOTSection(GOTSym.getBlock().getSection()))67    return make_error<StringError>(68        "Stubs entry in " + G.getName() + ", \"" +69            GOTSym.getBlock().getSection().getName() +70            "\" does not point to GOT entry",71        inconvertibleErrorCode());72  return getELFGOTTarget(G, GOTSym.getBlock());73}74 75static Expected<Symbol &> getELFAArch32StubTarget(LinkGraph &G, Block &B) {76  auto E = getFirstRelocationEdge(G, B);77  if (!E)78    return E.takeError();79  return E->getTarget();80}81 82enum SectionType { GOT, Stubs, AArch32Stubs, Other };83 84static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI,85                            SectionType SecType) {86  switch (SecType) {87  case GOT:88    if (Sym.getSize() == 0)89      return Error::success(); // Skip the GOT start symbol90    return FI.registerGOTEntry(G, Sym, getELFGOTTarget);91  case Stubs:92    return FI.registerStubEntry(G, Sym, getELFStubTarget);93  case AArch32Stubs:94    return FI.registerMultiStubEntry(G, Sym, getELFAArch32StubTarget);95  case Other:96    return Error::success();97  }98  llvm_unreachable("Unhandled SectionType enum");99}100 101namespace llvm {102 103Error registerELFGraphInfo(Session &S, LinkGraph &G) {104  std::lock_guard<std::mutex> Lock(S.M);105 106  auto FileName = sys::path::filename(G.getName());107  auto [It, Inserted] = S.FileInfos.try_emplace(FileName);108  if (!Inserted) {109    return make_error<StringError>("When -check is passed, file names must be "110                                   "distinct (duplicate: \"" +111                                       FileName + "\")",112                                   inconvertibleErrorCode());113  }114 115  auto &FileInfo = It->second;116  LLVM_DEBUG({117    dbgs() << "Registering ELF file info for \"" << FileName << "\"\n";118  });119  for (auto &Sec : G.sections()) {120    LLVM_DEBUG({121      dbgs() << "  Section \"" << Sec.getName() << "\": "122             << (Sec.symbols().empty() ? "empty. skipping." : "processing...")123             << "\n";124    });125 126    // Skip empty sections.127    if (Sec.symbols().empty())128      continue;129 130    if (FileInfo.SectionInfos.count(Sec.getName()))131      return make_error<StringError>("Encountered duplicate section name \"" +132                                         Sec.getName() + "\" in \"" + FileName +133                                         "\"",134                                     inconvertibleErrorCode());135 136    SectionType SecType;137    if (isELFGOTSection(Sec)) {138      SecType = GOT;139    } else if (isELFStubsSection(Sec)) {140      SecType = Stubs;141    } else if (isELFAArch32StubsSection(Sec)) {142      SecType = AArch32Stubs;143    } else {144      SecType = Other;145    }146 147    bool SectionContainsContent = false;148    bool SectionContainsZeroFill = false;149 150    auto *FirstSym = *Sec.symbols().begin();151    auto *LastSym = FirstSym;152    for (auto *Sym : Sec.symbols()) {153      if (Sym->getAddress() < FirstSym->getAddress())154        FirstSym = Sym;155      if (Sym->getAddress() > LastSym->getAddress())156        LastSym = Sym;157 158      if (SecType != Other) {159        if (Error Err = registerSymbol(G, *Sym, FileInfo, SecType))160          return Err;161        SectionContainsContent = true;162      }163 164      if (Sym->hasName()) {165        if (Sym->isSymbolZeroFill()) {166          S.SymbolInfos[Sym->getName()] = {Sym->getSize(),167                                           Sym->getAddress().getValue()};168          SectionContainsZeroFill = true;169        } else {170          S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),171                                           Sym->getAddress().getValue(),172                                           Sym->getTargetFlags()};173          SectionContainsContent = true;174        }175      }176    }177 178    // Add symbol info for absolute symbols.179    for (auto *Sym : G.absolute_symbols())180      S.SymbolInfos[Sym->getName()] = {Sym->getSize(),181                                       Sym->getAddress().getValue()};182 183    auto SecAddr = FirstSym->getAddress();184    auto SecSize =185        (LastSym->getBlock().getAddress() + LastSym->getBlock().getSize()) -186        SecAddr;187 188    if (SectionContainsZeroFill && SectionContainsContent)189      return make_error<StringError>("Mixed zero-fill and content sections not "190                                     "supported yet",191                                     inconvertibleErrorCode());192    if (SectionContainsZeroFill)193      FileInfo.SectionInfos[Sec.getName()] = {SecSize, SecAddr.getValue()};194    else195      FileInfo.SectionInfos[Sec.getName()] = {196          ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),197          SecAddr.getValue(), FirstSym->getTargetFlags()};198  }199 200  return Error::success();201}202 203} // end namespace llvm204