LLVM  16.0.0git
COFFLinkGraphBuilder.h
Go to the documentation of this file.
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Generic COFF LinkGraph building code.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringMap.h"
19 #include "llvm/Object/COFF.h"
20 
21 #include "COFFDirectiveParser.h"
22 #include "EHFrameSupportImpl.h"
23 #include "JITLinkGeneric.h"
24 
25 #define DEBUG_TYPE "jitlink"
26 
27 #include <list>
28 
29 namespace llvm {
30 namespace jitlink {
31 
33 public:
34  virtual ~COFFLinkGraphBuilder();
36 
37 protected:
38  using COFFSectionIndex = int32_t;
39  using COFFSymbolIndex = int32_t;
40 
42  LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
43 
44  LinkGraph &getGraph() const { return *G; }
45 
46  const object::COFFObjectFile &getObject() const { return Obj; }
47 
48  virtual Error addRelocations() = 0;
49 
52 
54  Symbol &Sym) {
55  assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
56  GraphSymbols[SymIndex] = &Sym;
57  if (!COFF::isReservedSectionNumber(SecIndex))
58  SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
59  }
60 
62  if (SymIndex < 0 ||
63  SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
64  return nullptr;
65  return GraphSymbols[SymIndex];
66  }
67 
69  assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
70  assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
71  GraphBlocks[SecIndex] = B;
72  }
73 
75  if (SecIndex <= 0 ||
76  SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
77  return nullptr;
78  return GraphBlocks[SecIndex];
79  }
80 
82  return Obj.sections();
83  }
84 
85  /// Traverse all matching relocation records in the given section. The handler
86  /// function Func should be callable with this signature:
87  /// Error(const object::RelocationRef&,
88  /// const object::SectionRef&, Section &)
89  ///
90  template <typename RelocHandlerFunction>
92  RelocHandlerFunction &&Func,
93  bool ProcessDebugSections = false);
94 
95  /// Traverse all matching relocation records in the given section. Convenience
96  /// wrapper to allow passing a member function for the handler.
97  ///
98  template <typename ClassT, typename RelocHandlerMethod>
99  Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
100  RelocHandlerMethod &&Method,
101  bool ProcessDebugSections = false) {
102  return forEachRelocation(
103  RelSec,
104  [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
105  return (Instance->*Method)(Rel, Target, GS);
106  },
107  ProcessDebugSections);
108  }
109 
110 private:
111  // Pending comdat symbol export that is initiated by the first symbol of
112  // COMDAT sequence.
113  struct ComdatExportRequest {
114  COFFSymbolIndex SymbolIndex;
117  };
118  std::vector<Optional<ComdatExportRequest>> PendingComdatExports;
119 
120  // This represents a pending request to create a weak external symbol with a
121  // name.
122  struct WeakExternalRequest {
127  };
128  std::vector<WeakExternalRequest> WeakExternalRequests;
129 
130  // Per COFF section jitlink symbol set sorted by offset.
131  // Used for calculating implicit size of defined symbols.
132  using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
133  std::vector<SymbolSet> SymbolSets;
134 
135  Section &getCommonSection();
136 
137  Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
138  object::COFFSymbolRef Symbol,
139  const object::coff_section *Section);
140  Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
141  Symbol &Target);
142  Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
143  StringRef SymbolName,
144  object::COFFSymbolRef Symbol,
145  const object::coff_section *Section);
146  Expected<Symbol *> createCOMDATExportRequest(
147  COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
148  const object::coff_aux_section_definition *Definition);
149  Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
150  StringRef SymbolName,
151  object::COFFSymbolRef Symbol);
152 
153  Error handleDirectiveSection(StringRef Str);
154  Error flushWeakAliasRequests();
155  Error handleAlternateNames();
156  Error calculateImplicitSizeOfSymbols();
157 
158  static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
159  const object::coff_section *Section);
160  static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
161  const object::coff_section *Section);
162  static bool isComdatSection(const object::coff_section *Section);
163  static unsigned getPointerSize(const object::COFFObjectFile &Obj);
164  static support::endianness getEndianness(const object::COFFObjectFile &Obj);
165  static StringRef getDLLImportStubPrefix() { return "__imp_"; }
166  static StringRef getDirectiveSectionName() { return ".drectve"; }
167  StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
168  const object::coff_section *Sec,
169  object::COFFSymbolRef Sym);
170 
171  const object::COFFObjectFile &Obj;
172  std::unique_ptr<LinkGraph> G;
173  COFFDirectiveParser DirectiveParser;
174 
175  Section *CommonSection = nullptr;
176  std::vector<Block *> GraphBlocks;
177  std::vector<Symbol *> GraphSymbols;
178 
179  DenseMap<StringRef, StringRef> AlternateNames;
180  DenseMap<StringRef, Symbol *> ExternalSymbols;
181  DenseMap<StringRef, Symbol *> DefinedSymbols;
182 };
183 
184 template <typename RelocHandlerFunction>
186  RelocHandlerFunction &&Func,
187  bool ProcessDebugSections) {
188 
189  auto COFFRelSect = Obj.getCOFFSection(RelSec);
190 
191  // Target sections have names in valid COFF object files.
192  Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
193  if (!Name)
194  return Name.takeError();
195  LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
196 
197  // Lookup the link-graph node corresponding to the target section name.
198  auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
199  if (!BlockToFix)
200  return make_error<StringError>(
201  "Referencing a section that wasn't added to the graph: " + *Name,
203 
204  // Let the callee process relocation entries one by one.
205  for (const auto &R : RelSec.relocations())
206  if (Error Err = Func(R, RelSec, *BlockToFix))
207  return Err;
208 
209  LLVM_DEBUG(dbgs() << "\n");
210  return Error::success();
211 }
212 
213 } // end namespace jitlink
214 } // end namespace llvm
215 
216 #endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:149
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::Triple
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
DenseMap.h
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:82
llvm::object::SectionRef::relocations
iterator_range< relocation_iterator > relocations() const
Definition: ObjectFile.h:132
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::object::SectionRef
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
uint64_t
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::X86AS::GS
@ GS
Definition: X86.h:199
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::object::COFFObjectFile::getCOFFSection
const coff_section * getCOFFSection(const SectionRef &Section) const
Definition: COFFObjectFile.cpp:1240
uint32_t
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::AMDGPU::HSAMD::Kernel::Key::SymbolName
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
Definition: AMDGPUMetadata.h:386
llvm::AArch64::Alias
StringRef Alias
Definition: AArch64TargetParser.h:139
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
COFFDirectiveParser.h
EHFrameSupportImpl.h
llvm::object::COFFObjectFile
Definition: COFF.h:788
COFF.h
llvm::COFF::isReservedSectionNumber
bool isReservedSectionNumber(int32_t SectionNumber)
Definition: COFF.h:792
Characteristics
COFFYAML::WeakExternalCharacteristics Characteristics
Definition: COFFYAML.cpp:330
llvm::object::SectionRef::getIndex
uint64_t getIndex() const
Definition: ObjectFile.h:466
llvm::iterator_range
A range adaptor for a pair of iterators.
Definition: iterator_range.h:30
llvm::object::ObjectFile::sections
section_iterator_range sections() const
Definition: ObjectFile.h:327
llvm::support::endianness
endianness
Definition: Endian.h:27
StringMap.h
llvm::object::COFFObjectFile::getSectionName
Expected< StringRef > getSectionName(DataRefImpl Sec) const override
JITLinkGeneric.h