COFFLinkGraphBuilder.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. #ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
  13. #define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/StringMap.h"
  16. #include "llvm/ExecutionEngine/JITLink/JITLink.h"
  17. #include "llvm/Object/COFF.h"
  18. #include "COFFDirectiveParser.h"
  19. #include "EHFrameSupportImpl.h"
  20. #include "JITLinkGeneric.h"
  21. #define DEBUG_TYPE "jitlink"
  22. #include <list>
  23. namespace llvm {
  24. namespace jitlink {
  25. class COFFLinkGraphBuilder {
  26. public:
  27. virtual ~COFFLinkGraphBuilder();
  28. Expected<std::unique_ptr<LinkGraph>> buildGraph();
  29. protected:
  30. using COFFSectionIndex = int32_t;
  31. using COFFSymbolIndex = int32_t;
  32. COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
  33. LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
  34. LinkGraph &getGraph() const { return *G; }
  35. const object::COFFObjectFile &getObject() const { return Obj; }
  36. virtual Error addRelocations() = 0;
  37. Error graphifySections();
  38. Error graphifySymbols();
  39. void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,
  40. Symbol &Sym) {
  41. assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
  42. GraphSymbols[SymIndex] = &Sym;
  43. if (!COFF::isReservedSectionNumber(SecIndex))
  44. SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
  45. }
  46. Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {
  47. if (SymIndex < 0 ||
  48. SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
  49. return nullptr;
  50. return GraphSymbols[SymIndex];
  51. }
  52. void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {
  53. assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
  54. assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
  55. GraphBlocks[SecIndex] = B;
  56. }
  57. Block *getGraphBlock(COFFSectionIndex SecIndex) const {
  58. if (SecIndex <= 0 ||
  59. SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
  60. return nullptr;
  61. return GraphBlocks[SecIndex];
  62. }
  63. object::COFFObjectFile::section_iterator_range sections() const {
  64. return Obj.sections();
  65. }
  66. /// Traverse all matching relocation records in the given section. The handler
  67. /// function Func should be callable with this signature:
  68. /// Error(const object::RelocationRef&,
  69. /// const object::SectionRef&, Section &)
  70. ///
  71. template <typename RelocHandlerFunction>
  72. Error forEachRelocation(const object::SectionRef &RelSec,
  73. RelocHandlerFunction &&Func,
  74. bool ProcessDebugSections = false);
  75. /// Traverse all matching relocation records in the given section. Convenience
  76. /// wrapper to allow passing a member function for the handler.
  77. ///
  78. template <typename ClassT, typename RelocHandlerMethod>
  79. Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
  80. RelocHandlerMethod &&Method,
  81. bool ProcessDebugSections = false) {
  82. return forEachRelocation(
  83. RelSec,
  84. [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
  85. return (Instance->*Method)(Rel, Target, GS);
  86. },
  87. ProcessDebugSections);
  88. }
  89. private:
  90. // Pending comdat symbol export that is initiated by the first symbol of
  91. // COMDAT sequence.
  92. struct ComdatExportRequest {
  93. COFFSymbolIndex SymbolIndex;
  94. jitlink::Linkage Linkage;
  95. orc::ExecutorAddrDiff Size;
  96. };
  97. std::vector<std::optional<ComdatExportRequest>> PendingComdatExports;
  98. // This represents a pending request to create a weak external symbol with a
  99. // name.
  100. struct WeakExternalRequest {
  101. COFFSymbolIndex Alias;
  102. COFFSymbolIndex Target;
  103. uint32_t Characteristics;
  104. StringRef SymbolName;
  105. };
  106. std::vector<WeakExternalRequest> WeakExternalRequests;
  107. // Per COFF section jitlink symbol set sorted by offset.
  108. // Used for calculating implicit size of defined symbols.
  109. using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
  110. std::vector<SymbolSet> SymbolSets;
  111. Section &getCommonSection();
  112. Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
  113. object::COFFSymbolRef Symbol,
  114. const object::coff_section *Section);
  115. Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
  116. Symbol &Target);
  117. Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
  118. StringRef SymbolName,
  119. object::COFFSymbolRef Symbol,
  120. const object::coff_section *Section);
  121. Expected<Symbol *> createCOMDATExportRequest(
  122. COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
  123. const object::coff_aux_section_definition *Definition);
  124. Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
  125. StringRef SymbolName,
  126. object::COFFSymbolRef Symbol);
  127. Error handleDirectiveSection(StringRef Str);
  128. Error flushWeakAliasRequests();
  129. Error handleAlternateNames();
  130. Error calculateImplicitSizeOfSymbols();
  131. static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
  132. const object::coff_section *Section);
  133. static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
  134. const object::coff_section *Section);
  135. static bool isComdatSection(const object::coff_section *Section);
  136. static unsigned getPointerSize(const object::COFFObjectFile &Obj);
  137. static support::endianness getEndianness(const object::COFFObjectFile &Obj);
  138. static StringRef getDLLImportStubPrefix() { return "__imp_"; }
  139. static StringRef getDirectiveSectionName() { return ".drectve"; }
  140. StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
  141. const object::coff_section *Sec,
  142. object::COFFSymbolRef Sym);
  143. const object::COFFObjectFile &Obj;
  144. std::unique_ptr<LinkGraph> G;
  145. COFFDirectiveParser DirectiveParser;
  146. Section *CommonSection = nullptr;
  147. std::vector<Block *> GraphBlocks;
  148. std::vector<Symbol *> GraphSymbols;
  149. DenseMap<StringRef, StringRef> AlternateNames;
  150. DenseMap<StringRef, Symbol *> ExternalSymbols;
  151. DenseMap<StringRef, Symbol *> DefinedSymbols;
  152. };
  153. template <typename RelocHandlerFunction>
  154. Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
  155. RelocHandlerFunction &&Func,
  156. bool ProcessDebugSections) {
  157. auto COFFRelSect = Obj.getCOFFSection(RelSec);
  158. // Target sections have names in valid COFF object files.
  159. Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
  160. if (!Name)
  161. return Name.takeError();
  162. LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
  163. // Lookup the link-graph node corresponding to the target section name.
  164. auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
  165. if (!BlockToFix)
  166. return make_error<StringError>(
  167. "Referencing a section that wasn't added to the graph: " + *Name,
  168. inconvertibleErrorCode());
  169. // Let the callee process relocation entries one by one.
  170. for (const auto &R : RelSec.relocations())
  171. if (Error Err = Func(R, RelSec, *BlockToFix))
  172. return Err;
  173. LLVM_DEBUG(dbgs() << "\n");
  174. return Error::success();
  175. }
  176. } // end namespace jitlink
  177. } // end namespace llvm
  178. #endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H