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