Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
35271 views
//===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Generic COFF LinkGraph building code.9//10//===----------------------------------------------------------------------===//1112#ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H13#define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H1415#include "llvm/ADT/DenseMap.h"16#include "llvm/ExecutionEngine/JITLink/JITLink.h"17#include "llvm/Object/COFF.h"1819#include "COFFDirectiveParser.h"20#include "EHFrameSupportImpl.h"21#include "JITLinkGeneric.h"2223#define DEBUG_TYPE "jitlink"2425#include <list>2627namespace llvm {28namespace jitlink {2930class COFFLinkGraphBuilder {31public:32virtual ~COFFLinkGraphBuilder();33Expected<std::unique_ptr<LinkGraph>> buildGraph();3435protected:36using COFFSectionIndex = int32_t;37using COFFSymbolIndex = int32_t;3839COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,40SubtargetFeatures Features,41LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);4243LinkGraph &getGraph() const { return *G; }4445const object::COFFObjectFile &getObject() const { return Obj; }4647virtual Error addRelocations() = 0;4849Error graphifySections();50Error graphifySymbols();5152void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,53Symbol &Sym) {54assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");55GraphSymbols[SymIndex] = &Sym;56if (!COFF::isReservedSectionNumber(SecIndex))57SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});58}5960Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {61if (SymIndex < 0 ||62SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))63return nullptr;64return GraphSymbols[SymIndex];65}6667void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {68assert(!GraphBlocks[SecIndex] && "Duplicate section at index");69assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");70GraphBlocks[SecIndex] = B;71}7273Block *getGraphBlock(COFFSectionIndex SecIndex) const {74if (SecIndex <= 0 ||75SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))76return nullptr;77return GraphBlocks[SecIndex];78}7980object::COFFObjectFile::section_iterator_range sections() const {81return Obj.sections();82}8384/// Traverse all matching relocation records in the given section. The handler85/// function Func should be callable with this signature:86/// Error(const object::RelocationRef&,87/// const object::SectionRef&, Section &)88///89template <typename RelocHandlerFunction>90Error forEachRelocation(const object::SectionRef &RelSec,91RelocHandlerFunction &&Func,92bool ProcessDebugSections = false);9394/// Traverse all matching relocation records in the given section. Convenience95/// wrapper to allow passing a member function for the handler.96///97template <typename ClassT, typename RelocHandlerMethod>98Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,99RelocHandlerMethod &&Method,100bool ProcessDebugSections = false) {101return forEachRelocation(102RelSec,103[Instance, Method](const auto &Rel, const auto &Target, auto &GS) {104return (Instance->*Method)(Rel, Target, GS);105},106ProcessDebugSections);107}108109private:110// Pending comdat symbol export that is initiated by the first symbol of111// COMDAT sequence.112struct ComdatExportRequest {113COFFSymbolIndex SymbolIndex;114jitlink::Linkage Linkage;115orc::ExecutorAddrDiff Size;116};117std::vector<std::optional<ComdatExportRequest>> PendingComdatExports;118119// This represents a pending request to create a weak external symbol with a120// name.121struct WeakExternalRequest {122COFFSymbolIndex Alias;123COFFSymbolIndex Target;124uint32_t Characteristics;125StringRef SymbolName;126};127std::vector<WeakExternalRequest> WeakExternalRequests;128129// Per COFF section jitlink symbol set sorted by offset.130// Used for calculating implicit size of defined symbols.131using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;132std::vector<SymbolSet> SymbolSets;133134Section &getCommonSection();135136Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,137object::COFFSymbolRef Symbol,138const object::coff_section *Section);139Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,140Symbol &Target);141Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,142StringRef SymbolName,143object::COFFSymbolRef Symbol,144const object::coff_section *Section);145Expected<Symbol *> createCOMDATExportRequest(146COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,147const object::coff_aux_section_definition *Definition);148Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,149StringRef SymbolName,150object::COFFSymbolRef Symbol);151152Error handleDirectiveSection(StringRef Str);153Error flushWeakAliasRequests();154Error handleAlternateNames();155Error calculateImplicitSizeOfSymbols();156157static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,158const object::coff_section *Section);159static uint64_t getSectionSize(const object::COFFObjectFile &Obj,160const object::coff_section *Section);161static bool isComdatSection(const object::coff_section *Section);162static unsigned getPointerSize(const object::COFFObjectFile &Obj);163static llvm::endianness getEndianness(const object::COFFObjectFile &Obj);164static StringRef getDLLImportStubPrefix() { return "__imp_"; }165static StringRef getDirectiveSectionName() { return ".drectve"; }166StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,167const object::coff_section *Sec,168object::COFFSymbolRef Sym);169170const object::COFFObjectFile &Obj;171std::unique_ptr<LinkGraph> G;172COFFDirectiveParser DirectiveParser;173174Section *CommonSection = nullptr;175std::vector<Block *> GraphBlocks;176std::vector<Symbol *> GraphSymbols;177178DenseMap<StringRef, StringRef> AlternateNames;179DenseMap<StringRef, Symbol *> ExternalSymbols;180DenseMap<StringRef, Symbol *> DefinedSymbols;181};182183template <typename RelocHandlerFunction>184Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,185RelocHandlerFunction &&Func,186bool ProcessDebugSections) {187188auto COFFRelSect = Obj.getCOFFSection(RelSec);189190// Target sections have names in valid COFF object files.191Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);192if (!Name)193return Name.takeError();194195// Skip the unhandled metadata sections.196if (*Name == ".voltbl")197return Error::success();198LLVM_DEBUG(dbgs() << " " << *Name << ":\n");199200// Lookup the link-graph node corresponding to the target section name.201auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);202if (!BlockToFix)203return make_error<StringError>(204"Referencing a section that wasn't added to the graph: " + *Name,205inconvertibleErrorCode());206207// Let the callee process relocation entries one by one.208for (const auto &R : RelSec.relocations())209if (Error Err = Func(R, RelSec, *BlockToFix))210return Err;211212LLVM_DEBUG(dbgs() << "\n");213return Error::success();214}215216} // end namespace jitlink217} // end namespace llvm218219#endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H220221222