xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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/ExecutionEngine/JITLink/JITLink.h"
18753f127fSDimitry Andric #include "llvm/Object/COFF.h"
19753f127fSDimitry Andric 
20bdd1243dSDimitry Andric #include "COFFDirectiveParser.h"
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,
4106c3fb27SDimitry Andric                        SubtargetFeatures Features,
42753f127fSDimitry Andric                        LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
43753f127fSDimitry Andric 
getGraph()44753f127fSDimitry Andric   LinkGraph &getGraph() const { return *G; }
45753f127fSDimitry Andric 
getObject()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 
setGraphSymbol(COFFSectionIndex SecIndex,COFFSymbolIndex SymIndex,Symbol & Sym)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 
getGraphSymbol(COFFSymbolIndex SymIndex)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 
setGraphBlock(COFFSectionIndex SecIndex,Block * B)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 
getGraphBlock(COFFSectionIndex SecIndex)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 
sections()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;
116bdd1243dSDimitry Andric     orc::ExecutorAddrDiff Size;
117753f127fSDimitry Andric   };
118bdd1243dSDimitry 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 
137bdd1243dSDimitry Andric   Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
138bdd1243dSDimitry Andric                                object::COFFSymbolRef Symbol,
139bdd1243dSDimitry Andric                                const object::coff_section *Section);
140bdd1243dSDimitry Andric   Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
141bdd1243dSDimitry 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);
152bdd1243dSDimitry Andric 
153bdd1243dSDimitry Andric   Error handleDirectiveSection(StringRef Str);
154753f127fSDimitry Andric   Error flushWeakAliasRequests();
155bdd1243dSDimitry 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);
164*5f757f3fSDimitry Andric   static llvm::endianness getEndianness(const object::COFFObjectFile &Obj);
getDLLImportStubPrefix()165bdd1243dSDimitry Andric   static StringRef getDLLImportStubPrefix() { return "__imp_"; }
getDirectiveSectionName()166bdd1243dSDimitry 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;
173bdd1243dSDimitry Andric   COFFDirectiveParser DirectiveParser;
174753f127fSDimitry Andric 
175753f127fSDimitry Andric   Section *CommonSection = nullptr;
176753f127fSDimitry Andric   std::vector<Block *> GraphBlocks;
177753f127fSDimitry Andric   std::vector<Symbol *> GraphSymbols;
178972a253aSDimitry Andric 
179bdd1243dSDimitry Andric   DenseMap<StringRef, StringRef> AlternateNames;
180972a253aSDimitry Andric   DenseMap<StringRef, Symbol *> ExternalSymbols;
181bdd1243dSDimitry Andric   DenseMap<StringRef, Symbol *> DefinedSymbols;
182753f127fSDimitry Andric };
183753f127fSDimitry Andric 
184753f127fSDimitry Andric template <typename RelocHandlerFunction>
forEachRelocation(const object::SectionRef & RelSec,RelocHandlerFunction && Func,bool ProcessDebugSections)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();
19506c3fb27SDimitry Andric 
19606c3fb27SDimitry Andric   // Skip the unhandled metadata sections.
19706c3fb27SDimitry Andric   if (*Name == ".voltbl")
19806c3fb27SDimitry Andric     return Error::success();
199753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
200753f127fSDimitry Andric 
201753f127fSDimitry Andric   // Lookup the link-graph node corresponding to the target section name.
202753f127fSDimitry Andric   auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
203753f127fSDimitry Andric   if (!BlockToFix)
204753f127fSDimitry Andric     return make_error<StringError>(
205753f127fSDimitry Andric         "Referencing a section that wasn't added to the graph: " + *Name,
206753f127fSDimitry Andric         inconvertibleErrorCode());
207753f127fSDimitry Andric 
208753f127fSDimitry Andric   // Let the callee process relocation entries one by one.
209753f127fSDimitry Andric   for (const auto &R : RelSec.relocations())
210753f127fSDimitry Andric     if (Error Err = Func(R, RelSec, *BlockToFix))
211753f127fSDimitry Andric       return Err;
212753f127fSDimitry Andric 
213753f127fSDimitry Andric   LLVM_DEBUG(dbgs() << "\n");
214753f127fSDimitry Andric   return Error::success();
215753f127fSDimitry Andric }
216753f127fSDimitry Andric 
217753f127fSDimitry Andric } // end namespace jitlink
218753f127fSDimitry Andric } // end namespace llvm
219753f127fSDimitry Andric 
220753f127fSDimitry Andric #endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
221