brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.7 KiB · 50ba2f8 Raw
239 lines · c
1//===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- C++ -*-===//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// Generic COFF LinkGraph building code.10//11//===----------------------------------------------------------------------===//12 13#ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H14#define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H15 16#include "llvm/ADT/DenseMap.h"17#include "llvm/ExecutionEngine/JITLink/JITLink.h"18#include "llvm/Object/COFF.h"19 20#include "COFFDirectiveParser.h"21#include "EHFrameSupportImpl.h"22#include "JITLinkGeneric.h"23 24#define DEBUG_TYPE "jitlink"25 26namespace llvm {27namespace jitlink {28 29class COFFLinkGraphBuilder {30public:31  virtual ~COFFLinkGraphBuilder();32  Expected<std::unique_ptr<LinkGraph>> buildGraph();33 34protected:35  using COFFSectionIndex = int32_t;36  using COFFSymbolIndex = int32_t;37 38  COFFLinkGraphBuilder(const object::COFFObjectFile &Obj,39                       std::shared_ptr<orc::SymbolStringPool> SSP, Triple TT,40                       SubtargetFeatures Features,41                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);42 43  LinkGraph &getGraph() const { return *G; }44 45  const object::COFFObjectFile &getObject() const { return Obj; }46 47  virtual Error addRelocations() = 0;48 49  Error graphifySections();50  Error graphifySymbols();51 52  void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,53                      Symbol &Sym) {54    assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");55    GraphSymbols[SymIndex] = &Sym;56    if (!COFF::isReservedSectionNumber(SecIndex))57      SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});58  }59 60  Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {61    if (SymIndex < 0 ||62        SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))63      return nullptr;64    return GraphSymbols[SymIndex];65  }66 67  void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {68    assert(!GraphBlocks[SecIndex] && "Duplicate section at index");69    assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");70    GraphBlocks[SecIndex] = B;71  }72 73  Block *getGraphBlock(COFFSectionIndex SecIndex) const {74    if (SecIndex <= 0 ||75        SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))76      return nullptr;77    return GraphBlocks[SecIndex];78  }79 80  Symbol &addImageBaseSymbol(StringRef Name = "__ImageBase") {81    auto &ImageBase = G->addExternalSymbol(G->intern(Name), 0, true);82    ImageBase.setLive(true);83    return ImageBase;84  }85 86  object::COFFObjectFile::section_iterator_range sections() const {87    return Obj.sections();88  }89 90  /// Traverse all matching relocation records in the given section. The handler91  /// function Func should be callable with this signature:92  ///   Error(const object::RelocationRef&,93  ///         const object::SectionRef&, Section &)94  ///95  template <typename RelocHandlerFunction>96  Error forEachRelocation(const object::SectionRef &RelSec,97                          RelocHandlerFunction &&Func,98                          bool ProcessDebugSections = false);99 100  /// Traverse all matching relocation records in the given section. Convenience101  /// wrapper to allow passing a member function for the handler.102  ///103  template <typename ClassT, typename RelocHandlerMethod>104  Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,105                          RelocHandlerMethod &&Method,106                          bool ProcessDebugSections = false) {107    return forEachRelocation(108        RelSec,109        [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {110          return (Instance->*Method)(Rel, Target, GS);111        },112        ProcessDebugSections);113  }114 115private:116  // Pending comdat symbol export that is initiated by the first symbol of117  // COMDAT sequence.118  struct ComdatExportRequest {119    COFFSymbolIndex SymbolIndex;120    jitlink::Linkage Linkage;121    orc::ExecutorAddrDiff Size;122  };123  std::vector<std::optional<ComdatExportRequest>> PendingComdatExports;124 125  // This represents a pending request to create a weak external symbol with a126  // name.127  struct WeakExternalRequest {128    COFFSymbolIndex Alias;129    COFFSymbolIndex Target;130    uint32_t Characteristics;131    StringRef SymbolName;132  };133  std::vector<WeakExternalRequest> WeakExternalRequests;134 135  // Per COFF section jitlink symbol set sorted by offset.136  // Used for calculating implicit size of defined symbols.137  using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;138  std::vector<SymbolSet> SymbolSets;139 140  Section &getCommonSection();141 142  Symbol *createExternalSymbol(COFFSymbolIndex SymIndex,143                               orc::SymbolStringPtr SymbolName,144                               object::COFFSymbolRef Symbol,145                               const object::coff_section *Section);146  Expected<Symbol *> createAliasSymbol(orc::SymbolStringPtr SymbolName,147                                       Linkage L, Scope S, Symbol &Target);148  Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,149                                         orc::SymbolStringPtr SymbolName,150                                         object::COFFSymbolRef Symbol,151                                         const object::coff_section *Section);152  Expected<Symbol *> createCOMDATExportRequest(153      COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,154      const object::coff_aux_section_definition *Definition);155  Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,156                                        orc::SymbolStringPtr SymbolName,157                                        object::COFFSymbolRef Symbol);158 159  Error handleDirectiveSection(StringRef Str);160  Error flushWeakAliasRequests();161  Error handleAlternateNames();162  Error calculateImplicitSizeOfSymbols();163 164  static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,165                                    const object::coff_section *Section);166  static uint64_t getSectionSize(const object::COFFObjectFile &Obj,167                                 const object::coff_section *Section);168  static bool isComdatSection(const object::coff_section *Section);169  static unsigned getPointerSize(const object::COFFObjectFile &Obj);170  static llvm::endianness getEndianness(const object::COFFObjectFile &Obj);171  static StringRef getDLLImportStubPrefix() { return "__imp_"; }172  static StringRef getDirectiveSectionName() { return ".drectve"; }173  StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,174                               const object::coff_section *Sec,175                               object::COFFSymbolRef Sym);176 177  const object::COFFObjectFile &Obj;178  std::unique_ptr<LinkGraph> G;179  COFFDirectiveParser DirectiveParser;180 181  Section *CommonSection = nullptr;182  std::vector<Block *> GraphBlocks;183  std::vector<Symbol *> GraphSymbols;184 185  DenseMap<orc::SymbolStringPtr, orc::SymbolStringPtr> AlternateNames;186  DenseMap<orc::SymbolStringPtr, Symbol *> ExternalSymbols;187  DenseMap<orc::SymbolStringPtr, Symbol *> DefinedSymbols;188};189 190template <typename RelocHandlerFunction>191Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,192                                              RelocHandlerFunction &&Func,193                                              bool ProcessDebugSections) {194 195  auto COFFRelSect = Obj.getCOFFSection(RelSec);196 197  // Target sections have names in valid COFF object files.198  Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);199  if (!Name)200    return Name.takeError();201 202  // Skip the unhandled metadata sections.203  if (*Name == ".voltbl")204    return Error::success();205  LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");206 207  // Lookup the link-graph node corresponding to the target section name.208  auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);209  if (!BlockToFix)210    return make_error<StringError>(211        "Referencing a section that wasn't added to the graph: " + *Name,212        inconvertibleErrorCode());213 214  // Let the callee process relocation entries one by one.215  for (const auto &R : RelSec.relocations())216    if (Error Err = Func(R, RelSec, *BlockToFix))217      return Err;218 219  LLVM_DEBUG(dbgs() << "\n");220  return Error::success();221}222 223class GetImageBaseSymbol {224public:225  GetImageBaseSymbol(StringRef ImageBaseName = "__ImageBase")226      : ImageBaseName(ImageBaseName) {}227  Symbol *operator()(LinkGraph &G);228  void reset() { ImageBase = std::nullopt; }229 230private:231  StringRef ImageBaseName;232  std::optional<Symbol *> ImageBase;233};234 235} // end namespace jitlink236} // end namespace llvm237 238#endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H239