1753f127fSDimitry Andric //===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- C++ -*-===// 2753f127fSDimitry Andric // 3753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6753f127fSDimitry Andric // 7753f127fSDimitry Andric //===----------------------------------------------------------------------===// 8753f127fSDimitry Andric // 9753f127fSDimitry Andric // Generic COFF LinkGraph building code. 10753f127fSDimitry Andric // 11753f127fSDimitry Andric //===----------------------------------------------------------------------===// 12753f127fSDimitry Andric 13753f127fSDimitry Andric #ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H 14753f127fSDimitry Andric #define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H 15753f127fSDimitry Andric 16753f127fSDimitry Andric #include "llvm/ADT/DenseMap.h" 17753f127fSDimitry Andric #include "llvm/ADT/StringMap.h" 18753f127fSDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 19753f127fSDimitry Andric #include "llvm/Object/COFF.h" 20753f127fSDimitry Andric 21*bdd1243dSDimitry Andric #include "COFFDirectiveParser.h" 22753f127fSDimitry Andric #include "EHFrameSupportImpl.h" 23753f127fSDimitry Andric #include "JITLinkGeneric.h" 24753f127fSDimitry Andric 25753f127fSDimitry Andric #define DEBUG_TYPE "jitlink" 26753f127fSDimitry Andric 27753f127fSDimitry Andric #include <list> 28753f127fSDimitry Andric 29753f127fSDimitry Andric namespace llvm { 30753f127fSDimitry Andric namespace jitlink { 31753f127fSDimitry Andric 32753f127fSDimitry Andric class COFFLinkGraphBuilder { 33753f127fSDimitry Andric public: 34753f127fSDimitry Andric virtual ~COFFLinkGraphBuilder(); 35753f127fSDimitry Andric Expected<std::unique_ptr<LinkGraph>> buildGraph(); 36753f127fSDimitry Andric 37753f127fSDimitry Andric protected: 38753f127fSDimitry Andric using COFFSectionIndex = int32_t; 39753f127fSDimitry Andric using COFFSymbolIndex = int32_t; 40753f127fSDimitry Andric 41753f127fSDimitry Andric COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT, 42753f127fSDimitry Andric LinkGraph::GetEdgeKindNameFunction GetEdgeKindName); 43753f127fSDimitry Andric 44753f127fSDimitry Andric LinkGraph &getGraph() const { return *G; } 45753f127fSDimitry Andric 46753f127fSDimitry Andric const object::COFFObjectFile &getObject() const { return Obj; } 47753f127fSDimitry Andric 48753f127fSDimitry Andric virtual Error addRelocations() = 0; 49753f127fSDimitry Andric 50753f127fSDimitry Andric Error graphifySections(); 51753f127fSDimitry Andric Error graphifySymbols(); 52753f127fSDimitry Andric 53753f127fSDimitry Andric void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex, 54753f127fSDimitry Andric Symbol &Sym) { 55753f127fSDimitry Andric assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index"); 56753f127fSDimitry Andric GraphSymbols[SymIndex] = &Sym; 57753f127fSDimitry Andric if (!COFF::isReservedSectionNumber(SecIndex)) 58753f127fSDimitry Andric SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym}); 59753f127fSDimitry Andric } 60753f127fSDimitry Andric 61753f127fSDimitry Andric Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const { 62753f127fSDimitry Andric if (SymIndex < 0 || 63753f127fSDimitry Andric SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size())) 64753f127fSDimitry Andric return nullptr; 65753f127fSDimitry Andric return GraphSymbols[SymIndex]; 66753f127fSDimitry Andric } 67753f127fSDimitry Andric 68753f127fSDimitry Andric void setGraphBlock(COFFSectionIndex SecIndex, Block *B) { 69753f127fSDimitry Andric assert(!GraphBlocks[SecIndex] && "Duplicate section at index"); 70753f127fSDimitry Andric assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index"); 71753f127fSDimitry Andric GraphBlocks[SecIndex] = B; 72753f127fSDimitry Andric } 73753f127fSDimitry Andric 74753f127fSDimitry Andric Block *getGraphBlock(COFFSectionIndex SecIndex) const { 75753f127fSDimitry Andric if (SecIndex <= 0 || 76753f127fSDimitry Andric SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size())) 77753f127fSDimitry Andric return nullptr; 78753f127fSDimitry Andric return GraphBlocks[SecIndex]; 79753f127fSDimitry Andric } 80753f127fSDimitry Andric 81753f127fSDimitry Andric object::COFFObjectFile::section_iterator_range sections() const { 82753f127fSDimitry Andric return Obj.sections(); 83753f127fSDimitry Andric } 84753f127fSDimitry Andric 85753f127fSDimitry Andric /// Traverse all matching relocation records in the given section. The handler 86753f127fSDimitry Andric /// function Func should be callable with this signature: 87753f127fSDimitry Andric /// Error(const object::RelocationRef&, 88753f127fSDimitry Andric /// const object::SectionRef&, Section &) 89753f127fSDimitry Andric /// 90753f127fSDimitry Andric template <typename RelocHandlerFunction> 91753f127fSDimitry Andric Error forEachRelocation(const object::SectionRef &RelSec, 92753f127fSDimitry Andric RelocHandlerFunction &&Func, 93753f127fSDimitry Andric bool ProcessDebugSections = false); 94753f127fSDimitry Andric 95753f127fSDimitry Andric /// Traverse all matching relocation records in the given section. Convenience 96753f127fSDimitry Andric /// wrapper to allow passing a member function for the handler. 97753f127fSDimitry Andric /// 98753f127fSDimitry Andric template <typename ClassT, typename RelocHandlerMethod> 99753f127fSDimitry Andric Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance, 100753f127fSDimitry Andric RelocHandlerMethod &&Method, 101753f127fSDimitry Andric bool ProcessDebugSections = false) { 102753f127fSDimitry Andric return forEachRelocation( 103753f127fSDimitry Andric RelSec, 104753f127fSDimitry Andric [Instance, Method](const auto &Rel, const auto &Target, auto &GS) { 105753f127fSDimitry Andric return (Instance->*Method)(Rel, Target, GS); 106753f127fSDimitry Andric }, 107753f127fSDimitry Andric ProcessDebugSections); 108753f127fSDimitry Andric } 109753f127fSDimitry Andric 110753f127fSDimitry Andric private: 111753f127fSDimitry Andric // Pending comdat symbol export that is initiated by the first symbol of 112753f127fSDimitry Andric // COMDAT sequence. 113753f127fSDimitry Andric struct ComdatExportRequest { 114753f127fSDimitry Andric COFFSymbolIndex SymbolIndex; 115753f127fSDimitry Andric jitlink::Linkage Linkage; 116*bdd1243dSDimitry Andric orc::ExecutorAddrDiff Size; 117753f127fSDimitry Andric }; 118*bdd1243dSDimitry Andric std::vector<std::optional<ComdatExportRequest>> PendingComdatExports; 119753f127fSDimitry Andric 120753f127fSDimitry Andric // This represents a pending request to create a weak external symbol with a 121753f127fSDimitry Andric // name. 122972a253aSDimitry Andric struct WeakExternalRequest { 123753f127fSDimitry Andric COFFSymbolIndex Alias; 124753f127fSDimitry Andric COFFSymbolIndex Target; 125972a253aSDimitry Andric uint32_t Characteristics; 126753f127fSDimitry Andric StringRef SymbolName; 127753f127fSDimitry Andric }; 128972a253aSDimitry Andric std::vector<WeakExternalRequest> WeakExternalRequests; 129753f127fSDimitry Andric 130753f127fSDimitry Andric // Per COFF section jitlink symbol set sorted by offset. 131753f127fSDimitry Andric // Used for calculating implicit size of defined symbols. 132753f127fSDimitry Andric using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>; 133753f127fSDimitry Andric std::vector<SymbolSet> SymbolSets; 134753f127fSDimitry Andric 135753f127fSDimitry Andric Section &getCommonSection(); 136753f127fSDimitry Andric 137*bdd1243dSDimitry Andric Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName, 138*bdd1243dSDimitry Andric object::COFFSymbolRef Symbol, 139*bdd1243dSDimitry Andric const object::coff_section *Section); 140*bdd1243dSDimitry Andric Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S, 141*bdd1243dSDimitry Andric Symbol &Target); 142753f127fSDimitry Andric Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex, 143753f127fSDimitry Andric StringRef SymbolName, 144753f127fSDimitry Andric object::COFFSymbolRef Symbol, 145753f127fSDimitry Andric const object::coff_section *Section); 146753f127fSDimitry Andric Expected<Symbol *> createCOMDATExportRequest( 147753f127fSDimitry Andric COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol, 148753f127fSDimitry Andric const object::coff_aux_section_definition *Definition); 149753f127fSDimitry Andric Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex, 150753f127fSDimitry Andric StringRef SymbolName, 151753f127fSDimitry Andric object::COFFSymbolRef Symbol); 152*bdd1243dSDimitry Andric 153*bdd1243dSDimitry Andric Error handleDirectiveSection(StringRef Str); 154753f127fSDimitry Andric Error flushWeakAliasRequests(); 155*bdd1243dSDimitry Andric Error handleAlternateNames(); 156753f127fSDimitry Andric Error calculateImplicitSizeOfSymbols(); 157753f127fSDimitry Andric 158753f127fSDimitry Andric static uint64_t getSectionAddress(const object::COFFObjectFile &Obj, 159753f127fSDimitry Andric const object::coff_section *Section); 160753f127fSDimitry Andric static uint64_t getSectionSize(const object::COFFObjectFile &Obj, 161753f127fSDimitry Andric const object::coff_section *Section); 162753f127fSDimitry Andric static bool isComdatSection(const object::coff_section *Section); 163753f127fSDimitry Andric static unsigned getPointerSize(const object::COFFObjectFile &Obj); 164753f127fSDimitry Andric static support::endianness getEndianness(const object::COFFObjectFile &Obj); 165*bdd1243dSDimitry Andric static StringRef getDLLImportStubPrefix() { return "__imp_"; } 166*bdd1243dSDimitry Andric static StringRef getDirectiveSectionName() { return ".drectve"; } 167753f127fSDimitry Andric StringRef getCOFFSectionName(COFFSectionIndex SectionIndex, 168753f127fSDimitry Andric const object::coff_section *Sec, 169753f127fSDimitry Andric object::COFFSymbolRef Sym); 170753f127fSDimitry Andric 171753f127fSDimitry Andric const object::COFFObjectFile &Obj; 172753f127fSDimitry Andric std::unique_ptr<LinkGraph> G; 173*bdd1243dSDimitry Andric COFFDirectiveParser DirectiveParser; 174753f127fSDimitry Andric 175753f127fSDimitry Andric Section *CommonSection = nullptr; 176753f127fSDimitry Andric std::vector<Block *> GraphBlocks; 177753f127fSDimitry Andric std::vector<Symbol *> GraphSymbols; 178972a253aSDimitry Andric 179*bdd1243dSDimitry Andric DenseMap<StringRef, StringRef> AlternateNames; 180972a253aSDimitry Andric DenseMap<StringRef, Symbol *> ExternalSymbols; 181*bdd1243dSDimitry Andric DenseMap<StringRef, Symbol *> DefinedSymbols; 182753f127fSDimitry Andric }; 183753f127fSDimitry Andric 184753f127fSDimitry Andric template <typename RelocHandlerFunction> 185753f127fSDimitry Andric Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec, 186753f127fSDimitry Andric RelocHandlerFunction &&Func, 187753f127fSDimitry Andric bool ProcessDebugSections) { 188753f127fSDimitry Andric 189753f127fSDimitry Andric auto COFFRelSect = Obj.getCOFFSection(RelSec); 190753f127fSDimitry Andric 191753f127fSDimitry Andric // Target sections have names in valid COFF object files. 192753f127fSDimitry Andric Expected<StringRef> Name = Obj.getSectionName(COFFRelSect); 193753f127fSDimitry Andric if (!Name) 194753f127fSDimitry Andric return Name.takeError(); 195753f127fSDimitry Andric LLVM_DEBUG(dbgs() << " " << *Name << ":\n"); 196753f127fSDimitry Andric 197753f127fSDimitry Andric // Lookup the link-graph node corresponding to the target section name. 198753f127fSDimitry Andric auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1); 199753f127fSDimitry Andric if (!BlockToFix) 200753f127fSDimitry Andric return make_error<StringError>( 201753f127fSDimitry Andric "Referencing a section that wasn't added to the graph: " + *Name, 202753f127fSDimitry Andric inconvertibleErrorCode()); 203753f127fSDimitry Andric 204753f127fSDimitry Andric // Let the callee process relocation entries one by one. 205753f127fSDimitry Andric for (const auto &R : RelSec.relocations()) 206753f127fSDimitry Andric if (Error Err = Func(R, RelSec, *BlockToFix)) 207753f127fSDimitry Andric return Err; 208753f127fSDimitry Andric 209753f127fSDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 210753f127fSDimitry Andric return Error::success(); 211753f127fSDimitry Andric } 212753f127fSDimitry Andric 213753f127fSDimitry Andric } // end namespace jitlink 214753f127fSDimitry Andric } // end namespace llvm 215753f127fSDimitry Andric 216753f127fSDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H 217