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 21753f127fSDimitry Andric #include "EHFrameSupportImpl.h" 22753f127fSDimitry Andric #include "JITLinkGeneric.h" 23753f127fSDimitry Andric 24753f127fSDimitry Andric #define DEBUG_TYPE "jitlink" 25753f127fSDimitry Andric 26753f127fSDimitry Andric #include <list> 27753f127fSDimitry Andric 28753f127fSDimitry Andric namespace llvm { 29753f127fSDimitry Andric namespace jitlink { 30753f127fSDimitry Andric 31753f127fSDimitry Andric class COFFLinkGraphBuilder { 32753f127fSDimitry Andric public: 33753f127fSDimitry Andric virtual ~COFFLinkGraphBuilder(); 34753f127fSDimitry Andric Expected<std::unique_ptr<LinkGraph>> buildGraph(); 35753f127fSDimitry Andric 36753f127fSDimitry Andric protected: 37753f127fSDimitry Andric using COFFSectionIndex = int32_t; 38753f127fSDimitry Andric using COFFSymbolIndex = int32_t; 39753f127fSDimitry Andric 40753f127fSDimitry Andric COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT, 41753f127fSDimitry Andric LinkGraph::GetEdgeKindNameFunction GetEdgeKindName); 42753f127fSDimitry Andric 43753f127fSDimitry Andric LinkGraph &getGraph() const { return *G; } 44753f127fSDimitry Andric 45753f127fSDimitry Andric const object::COFFObjectFile &getObject() const { return Obj; } 46753f127fSDimitry Andric 47753f127fSDimitry Andric virtual Error addRelocations() = 0; 48753f127fSDimitry Andric 49753f127fSDimitry Andric Error graphifySections(); 50753f127fSDimitry Andric Error graphifySymbols(); 51753f127fSDimitry Andric 52753f127fSDimitry Andric void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex, 53753f127fSDimitry Andric Symbol &Sym) { 54753f127fSDimitry Andric assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index"); 55753f127fSDimitry Andric GraphSymbols[SymIndex] = &Sym; 56753f127fSDimitry Andric if (!COFF::isReservedSectionNumber(SecIndex)) 57753f127fSDimitry Andric SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym}); 58753f127fSDimitry Andric } 59753f127fSDimitry Andric 60753f127fSDimitry Andric Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const { 61753f127fSDimitry Andric if (SymIndex < 0 || 62753f127fSDimitry Andric SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size())) 63753f127fSDimitry Andric return nullptr; 64753f127fSDimitry Andric return GraphSymbols[SymIndex]; 65753f127fSDimitry Andric } 66753f127fSDimitry Andric 67753f127fSDimitry Andric void setGraphBlock(COFFSectionIndex SecIndex, Block *B) { 68753f127fSDimitry Andric assert(!GraphBlocks[SecIndex] && "Duplicate section at index"); 69753f127fSDimitry Andric assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index"); 70753f127fSDimitry Andric GraphBlocks[SecIndex] = B; 71753f127fSDimitry Andric } 72753f127fSDimitry Andric 73753f127fSDimitry Andric Block *getGraphBlock(COFFSectionIndex SecIndex) const { 74753f127fSDimitry Andric if (SecIndex <= 0 || 75753f127fSDimitry Andric SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size())) 76753f127fSDimitry Andric return nullptr; 77753f127fSDimitry Andric return GraphBlocks[SecIndex]; 78753f127fSDimitry Andric } 79753f127fSDimitry Andric 80753f127fSDimitry Andric object::COFFObjectFile::section_iterator_range sections() const { 81753f127fSDimitry Andric return Obj.sections(); 82753f127fSDimitry Andric } 83753f127fSDimitry Andric 84753f127fSDimitry Andric /// Traverse all matching relocation records in the given section. The handler 85753f127fSDimitry Andric /// function Func should be callable with this signature: 86753f127fSDimitry Andric /// Error(const object::RelocationRef&, 87753f127fSDimitry Andric /// const object::SectionRef&, Section &) 88753f127fSDimitry Andric /// 89753f127fSDimitry Andric template <typename RelocHandlerFunction> 90753f127fSDimitry Andric Error forEachRelocation(const object::SectionRef &RelSec, 91753f127fSDimitry Andric RelocHandlerFunction &&Func, 92753f127fSDimitry Andric bool ProcessDebugSections = false); 93753f127fSDimitry Andric 94753f127fSDimitry Andric /// Traverse all matching relocation records in the given section. Convenience 95753f127fSDimitry Andric /// wrapper to allow passing a member function for the handler. 96753f127fSDimitry Andric /// 97753f127fSDimitry Andric template <typename ClassT, typename RelocHandlerMethod> 98753f127fSDimitry Andric Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance, 99753f127fSDimitry Andric RelocHandlerMethod &&Method, 100753f127fSDimitry Andric bool ProcessDebugSections = false) { 101753f127fSDimitry Andric return forEachRelocation( 102753f127fSDimitry Andric RelSec, 103753f127fSDimitry Andric [Instance, Method](const auto &Rel, const auto &Target, auto &GS) { 104753f127fSDimitry Andric return (Instance->*Method)(Rel, Target, GS); 105753f127fSDimitry Andric }, 106753f127fSDimitry Andric ProcessDebugSections); 107753f127fSDimitry Andric } 108753f127fSDimitry Andric 109753f127fSDimitry Andric private: 110753f127fSDimitry Andric // Pending comdat symbol export that is initiated by the first symbol of 111753f127fSDimitry Andric // COMDAT sequence. 112753f127fSDimitry Andric struct ComdatExportRequest { 113753f127fSDimitry Andric COFFSymbolIndex SymbolIndex; 114753f127fSDimitry Andric jitlink::Linkage Linkage; 115753f127fSDimitry Andric }; 116*972a253aSDimitry Andric std::vector<Optional<ComdatExportRequest>> PendingComdatExports; 117753f127fSDimitry Andric 118753f127fSDimitry Andric // This represents a pending request to create a weak external symbol with a 119753f127fSDimitry Andric // name. 120*972a253aSDimitry Andric struct WeakExternalRequest { 121753f127fSDimitry Andric COFFSymbolIndex Alias; 122753f127fSDimitry Andric COFFSymbolIndex Target; 123*972a253aSDimitry Andric uint32_t Characteristics; 124753f127fSDimitry Andric StringRef SymbolName; 125753f127fSDimitry Andric }; 126*972a253aSDimitry Andric std::vector<WeakExternalRequest> WeakExternalRequests; 127753f127fSDimitry Andric 128753f127fSDimitry Andric // Per COFF section jitlink symbol set sorted by offset. 129753f127fSDimitry Andric // Used for calculating implicit size of defined symbols. 130753f127fSDimitry Andric using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>; 131753f127fSDimitry Andric std::vector<SymbolSet> SymbolSets; 132753f127fSDimitry Andric 133753f127fSDimitry Andric Section &getCommonSection(); 134753f127fSDimitry Andric 135753f127fSDimitry Andric Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex, 136753f127fSDimitry Andric StringRef SymbolName, 137753f127fSDimitry Andric object::COFFSymbolRef Symbol, 138753f127fSDimitry Andric const object::coff_section *Section); 139753f127fSDimitry Andric Expected<Symbol *> createCOMDATExportRequest( 140753f127fSDimitry Andric COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol, 141753f127fSDimitry Andric const object::coff_aux_section_definition *Definition); 142753f127fSDimitry Andric Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex, 143753f127fSDimitry Andric StringRef SymbolName, 144753f127fSDimitry Andric object::COFFSymbolRef Symbol); 145753f127fSDimitry Andric Error flushWeakAliasRequests(); 146753f127fSDimitry Andric Error calculateImplicitSizeOfSymbols(); 147753f127fSDimitry Andric 148753f127fSDimitry Andric static uint64_t getSectionAddress(const object::COFFObjectFile &Obj, 149753f127fSDimitry Andric const object::coff_section *Section); 150753f127fSDimitry Andric static uint64_t getSectionSize(const object::COFFObjectFile &Obj, 151753f127fSDimitry Andric const object::coff_section *Section); 152753f127fSDimitry Andric static bool isComdatSection(const object::coff_section *Section); 153753f127fSDimitry Andric static unsigned getPointerSize(const object::COFFObjectFile &Obj); 154753f127fSDimitry Andric static support::endianness getEndianness(const object::COFFObjectFile &Obj); 155753f127fSDimitry Andric StringRef getCOFFSectionName(COFFSectionIndex SectionIndex, 156753f127fSDimitry Andric const object::coff_section *Sec, 157753f127fSDimitry Andric object::COFFSymbolRef Sym); 158753f127fSDimitry Andric 159753f127fSDimitry Andric const object::COFFObjectFile &Obj; 160753f127fSDimitry Andric std::unique_ptr<LinkGraph> G; 161753f127fSDimitry Andric 162753f127fSDimitry Andric Section *CommonSection = nullptr; 163753f127fSDimitry Andric std::vector<Block *> GraphBlocks; 164753f127fSDimitry Andric std::vector<Symbol *> GraphSymbols; 165*972a253aSDimitry Andric 166*972a253aSDimitry Andric DenseMap<StringRef, Symbol *> ExternalSymbols; 167753f127fSDimitry Andric }; 168753f127fSDimitry Andric 169753f127fSDimitry Andric template <typename RelocHandlerFunction> 170753f127fSDimitry Andric Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec, 171753f127fSDimitry Andric RelocHandlerFunction &&Func, 172753f127fSDimitry Andric bool ProcessDebugSections) { 173753f127fSDimitry Andric 174753f127fSDimitry Andric auto COFFRelSect = Obj.getCOFFSection(RelSec); 175753f127fSDimitry Andric 176753f127fSDimitry Andric // Target sections have names in valid COFF object files. 177753f127fSDimitry Andric Expected<StringRef> Name = Obj.getSectionName(COFFRelSect); 178753f127fSDimitry Andric if (!Name) 179753f127fSDimitry Andric return Name.takeError(); 180753f127fSDimitry Andric LLVM_DEBUG(dbgs() << " " << *Name << ":\n"); 181753f127fSDimitry Andric 182753f127fSDimitry Andric // Lookup the link-graph node corresponding to the target section name. 183753f127fSDimitry Andric auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1); 184753f127fSDimitry Andric if (!BlockToFix) 185753f127fSDimitry Andric return make_error<StringError>( 186753f127fSDimitry Andric "Referencing a section that wasn't added to the graph: " + *Name, 187753f127fSDimitry Andric inconvertibleErrorCode()); 188753f127fSDimitry Andric 189753f127fSDimitry Andric // Let the callee process relocation entries one by one. 190753f127fSDimitry Andric for (const auto &R : RelSec.relocations()) 191753f127fSDimitry Andric if (Error Err = Func(R, RelSec, *BlockToFix)) 192753f127fSDimitry Andric return Err; 193753f127fSDimitry Andric 194753f127fSDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 195753f127fSDimitry Andric return Error::success(); 196753f127fSDimitry Andric } 197753f127fSDimitry Andric 198753f127fSDimitry Andric } // end namespace jitlink 199753f127fSDimitry Andric } // end namespace llvm 200753f127fSDimitry Andric 201753f127fSDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H 202