COFFLinkGraphBuilder.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. //=--------- COFFLinkGraphBuilder.cpp - COFF LinkGraph builder ----------===//
  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 buliding code.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "COFFLinkGraphBuilder.h"
  13. #define DEBUG_TYPE "jitlink"
  14. static const char *CommonSectionName = "__common";
  15. namespace llvm {
  16. namespace jitlink {
  17. static Triple createTripleWithCOFFFormat(Triple T) {
  18. T.setObjectFormat(Triple::COFF);
  19. return T;
  20. }
  21. COFFLinkGraphBuilder::COFFLinkGraphBuilder(
  22. const object::COFFObjectFile &Obj, Triple TT,
  23. LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
  24. : Obj(Obj),
  25. G(std::make_unique<LinkGraph>(Obj.getFileName().str(),
  26. createTripleWithCOFFFormat(TT),
  27. getPointerSize(Obj), getEndianness(Obj),
  28. std::move(GetEdgeKindName))) {
  29. LLVM_DEBUG({
  30. dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()
  31. << "\"\n";
  32. });
  33. }
  34. COFFLinkGraphBuilder::~COFFLinkGraphBuilder() = default;
  35. unsigned
  36. COFFLinkGraphBuilder::getPointerSize(const object::COFFObjectFile &Obj) {
  37. return Obj.getBytesInAddress();
  38. }
  39. support::endianness
  40. COFFLinkGraphBuilder::getEndianness(const object::COFFObjectFile &Obj) {
  41. return Obj.isLittleEndian() ? support::little : support::big;
  42. }
  43. uint64_t COFFLinkGraphBuilder::getSectionSize(const object::COFFObjectFile &Obj,
  44. const object::coff_section *Sec) {
  45. // Consider the difference between executable form and object form.
  46. // More information is inside COFFObjectFile::getSectionSize
  47. if (Obj.getDOSHeader())
  48. return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
  49. return Sec->SizeOfRawData;
  50. }
  51. uint64_t
  52. COFFLinkGraphBuilder::getSectionAddress(const object::COFFObjectFile &Obj,
  53. const object::coff_section *Section) {
  54. return Section->VirtualAddress + Obj.getImageBase();
  55. }
  56. bool COFFLinkGraphBuilder::isComdatSection(
  57. const object::coff_section *Section) {
  58. return Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT;
  59. }
  60. Section &COFFLinkGraphBuilder::getCommonSection() {
  61. if (!CommonSection)
  62. CommonSection = &G->createSection(CommonSectionName,
  63. orc::MemProt::Read | orc::MemProt::Write);
  64. return *CommonSection;
  65. }
  66. Expected<std::unique_ptr<LinkGraph>> COFFLinkGraphBuilder::buildGraph() {
  67. if (!Obj.isRelocatableObject())
  68. return make_error<JITLinkError>("Object is not a relocatable COFF file");
  69. if (auto Err = graphifySections())
  70. return std::move(Err);
  71. if (auto Err = graphifySymbols())
  72. return std::move(Err);
  73. if (auto Err = addRelocations())
  74. return std::move(Err);
  75. return std::move(G);
  76. }
  77. StringRef
  78. COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
  79. const object::coff_section *Sec,
  80. object::COFFSymbolRef Sym) {
  81. switch (SectionIndex) {
  82. case COFF::IMAGE_SYM_UNDEFINED: {
  83. if (Sym.getValue())
  84. return "(common)";
  85. else
  86. return "(external)";
  87. }
  88. case COFF::IMAGE_SYM_ABSOLUTE:
  89. return "(absolute)";
  90. case COFF::IMAGE_SYM_DEBUG: {
  91. // Used with .file symbol
  92. return "(debug)";
  93. }
  94. default: {
  95. // Non reserved regular section numbers
  96. if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
  97. return *SecNameOrErr;
  98. }
  99. }
  100. return "";
  101. }
  102. Error COFFLinkGraphBuilder::graphifySections() {
  103. LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
  104. GraphBlocks.resize(Obj.getNumberOfSections() + 1);
  105. // For each section...
  106. for (COFFSectionIndex SecIndex = 1;
  107. SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
  108. SecIndex++) {
  109. Expected<const object::coff_section *> Sec = Obj.getSection(SecIndex);
  110. if (!Sec)
  111. return Sec.takeError();
  112. StringRef SectionName;
  113. if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(*Sec))
  114. SectionName = *SecNameOrErr;
  115. // FIXME: Skip debug info sections
  116. LLVM_DEBUG({
  117. dbgs() << " "
  118. << "Creating section for \"" << SectionName << "\"\n";
  119. });
  120. // Get the section's memory protection flags.
  121. orc::MemProt Prot = orc::MemProt::Read;
  122. if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
  123. Prot |= orc::MemProt::Exec;
  124. if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_READ)
  125. Prot |= orc::MemProt::Read;
  126. if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
  127. Prot |= orc::MemProt::Write;
  128. // Look for existing sections first.
  129. auto *GraphSec = G->findSectionByName(SectionName);
  130. if (!GraphSec)
  131. GraphSec = &G->createSection(SectionName, Prot);
  132. if (GraphSec->getMemProt() != Prot)
  133. return make_error<JITLinkError>("MemProt should match");
  134. Block *B = nullptr;
  135. if ((*Sec)->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
  136. B = &G->createZeroFillBlock(
  137. *GraphSec, getSectionSize(Obj, *Sec),
  138. orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
  139. (*Sec)->getAlignment(), 0);
  140. else {
  141. ArrayRef<uint8_t> Data;
  142. if (auto Err = Obj.getSectionContents(*Sec, Data))
  143. return Err;
  144. auto CharData = ArrayRef<char>(
  145. reinterpret_cast<const char *>(Data.data()), Data.size());
  146. if (SectionName == getDirectiveSectionName())
  147. if (auto Err = handleDirectiveSection(
  148. StringRef(CharData.data(), CharData.size())))
  149. return Err;
  150. B = &G->createContentBlock(
  151. *GraphSec, CharData, orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
  152. (*Sec)->getAlignment(), 0);
  153. }
  154. setGraphBlock(SecIndex, B);
  155. }
  156. return Error::success();
  157. }
  158. Error COFFLinkGraphBuilder::graphifySymbols() {
  159. LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
  160. SymbolSets.resize(Obj.getNumberOfSections() + 1);
  161. PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
  162. GraphSymbols.resize(Obj.getNumberOfSymbols());
  163. for (COFFSymbolIndex SymIndex = 0;
  164. SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
  165. SymIndex++) {
  166. Expected<object::COFFSymbolRef> Sym = Obj.getSymbol(SymIndex);
  167. if (!Sym)
  168. return Sym.takeError();
  169. StringRef SymbolName;
  170. if (Expected<StringRef> SymNameOrErr = Obj.getSymbolName(*Sym))
  171. SymbolName = *SymNameOrErr;
  172. COFFSectionIndex SectionIndex = Sym->getSectionNumber();
  173. const object::coff_section *Sec = nullptr;
  174. if (!COFF::isReservedSectionNumber(SectionIndex)) {
  175. auto SecOrErr = Obj.getSection(SectionIndex);
  176. if (!SecOrErr)
  177. return make_error<JITLinkError>(
  178. "Invalid COFF section number:" + formatv("{0:d}: ", SectionIndex) +
  179. " (" + toString(SecOrErr.takeError()) + ")");
  180. Sec = *SecOrErr;
  181. }
  182. // Create jitlink symbol
  183. jitlink::Symbol *GSym = nullptr;
  184. if (Sym->isFileRecord())
  185. LLVM_DEBUG({
  186. dbgs() << " " << SymIndex << ": Skipping FileRecord symbol \""
  187. << SymbolName << "\" in "
  188. << getCOFFSectionName(SectionIndex, Sec, *Sym)
  189. << " (index: " << SectionIndex << ") \n";
  190. });
  191. else if (Sym->isUndefined()) {
  192. GSym = createExternalSymbol(SymIndex, SymbolName, *Sym, Sec);
  193. } else if (Sym->isWeakExternal()) {
  194. auto *WeakExternal = Sym->getAux<object::coff_aux_weak_external>();
  195. COFFSymbolIndex TagIndex = WeakExternal->TagIndex;
  196. uint32_t Characteristics = WeakExternal->Characteristics;
  197. WeakExternalRequests.push_back(
  198. {SymIndex, TagIndex, Characteristics, SymbolName});
  199. } else {
  200. Expected<jitlink::Symbol *> NewGSym =
  201. createDefinedSymbol(SymIndex, SymbolName, *Sym, Sec);
  202. if (!NewGSym)
  203. return NewGSym.takeError();
  204. GSym = *NewGSym;
  205. if (GSym) {
  206. LLVM_DEBUG({
  207. dbgs() << " " << SymIndex
  208. << ": Creating defined graph symbol for COFF symbol \""
  209. << SymbolName << "\" in "
  210. << getCOFFSectionName(SectionIndex, Sec, *Sym)
  211. << " (index: " << SectionIndex << ") \n";
  212. dbgs() << " " << *GSym << "\n";
  213. });
  214. }
  215. }
  216. // Register the symbol
  217. if (GSym)
  218. setGraphSymbol(SectionIndex, SymIndex, *GSym);
  219. SymIndex += Sym->getNumberOfAuxSymbols();
  220. }
  221. if (auto Err = flushWeakAliasRequests())
  222. return Err;
  223. if (auto Err = handleAlternateNames())
  224. return Err;
  225. if (auto Err = calculateImplicitSizeOfSymbols())
  226. return Err;
  227. return Error::success();
  228. }
  229. Error COFFLinkGraphBuilder::handleDirectiveSection(StringRef Str) {
  230. auto Parsed = DirectiveParser.parse(Str);
  231. if (!Parsed)
  232. return Parsed.takeError();
  233. for (auto *Arg : *Parsed) {
  234. StringRef S = Arg->getValue();
  235. switch (Arg->getOption().getID()) {
  236. case COFF_OPT_alternatename: {
  237. StringRef From, To;
  238. std::tie(From, To) = S.split('=');
  239. if (From.empty() || To.empty())
  240. return make_error<JITLinkError>(
  241. "Invalid COFF /alternatename directive");
  242. AlternateNames[From] = To;
  243. break;
  244. }
  245. case COFF_OPT_incl: {
  246. auto DataCopy = G->allocateString(S);
  247. StringRef StrCopy(DataCopy.data(), DataCopy.size());
  248. ExternalSymbols[StrCopy] = &G->addExternalSymbol(StrCopy, 0, false);
  249. ExternalSymbols[StrCopy]->setLive(true);
  250. break;
  251. }
  252. case COFF_OPT_export:
  253. break;
  254. default: {
  255. LLVM_DEBUG({
  256. dbgs() << "Unknown coff directive: " << Arg->getSpelling() << "\n";
  257. });
  258. break;
  259. }
  260. }
  261. }
  262. return Error::success();
  263. }
  264. Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
  265. // Export the weak external symbols and alias it
  266. for (auto &WeakExternal : WeakExternalRequests) {
  267. if (auto *Target = getGraphSymbol(WeakExternal.Target)) {
  268. Expected<object::COFFSymbolRef> AliasSymbol =
  269. Obj.getSymbol(WeakExternal.Alias);
  270. if (!AliasSymbol)
  271. return AliasSymbol.takeError();
  272. // FIXME: IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY and
  273. // IMAGE_WEAK_EXTERN_SEARCH_LIBRARY are handled in the same way.
  274. Scope S =
  275. WeakExternal.Characteristics == COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
  276. ? Scope::Default
  277. : Scope::Local;
  278. auto NewSymbol =
  279. createAliasSymbol(WeakExternal.SymbolName, Linkage::Weak, S, *Target);
  280. if (!NewSymbol)
  281. return NewSymbol.takeError();
  282. setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
  283. **NewSymbol);
  284. LLVM_DEBUG({
  285. dbgs() << " " << WeakExternal.Alias
  286. << ": Creating weak external symbol for COFF symbol \""
  287. << WeakExternal.SymbolName << "\" in section "
  288. << AliasSymbol->getSectionNumber() << "\n";
  289. dbgs() << " " << **NewSymbol << "\n";
  290. });
  291. } else
  292. return make_error<JITLinkError>("Weak symbol alias requested but actual "
  293. "symbol not found for symbol " +
  294. formatv("{0:d}", WeakExternal.Alias));
  295. }
  296. return Error::success();
  297. }
  298. Error COFFLinkGraphBuilder::handleAlternateNames() {
  299. for (auto &KeyValue : AlternateNames)
  300. if (DefinedSymbols.count(KeyValue.second) &&
  301. ExternalSymbols.count(KeyValue.first)) {
  302. auto *Target = DefinedSymbols[KeyValue.second];
  303. auto *Alias = ExternalSymbols[KeyValue.first];
  304. G->makeDefined(*Alias, Target->getBlock(), Target->getOffset(),
  305. Target->getSize(), Linkage::Weak, Scope::Local, false);
  306. }
  307. return Error::success();
  308. }
  309. Symbol *COFFLinkGraphBuilder::createExternalSymbol(
  310. COFFSymbolIndex SymIndex, StringRef SymbolName,
  311. object::COFFSymbolRef Symbol, const object::coff_section *Section) {
  312. if (!ExternalSymbols.count(SymbolName))
  313. ExternalSymbols[SymbolName] =
  314. &G->addExternalSymbol(SymbolName, Symbol.getValue(), false);
  315. LLVM_DEBUG({
  316. dbgs() << " " << SymIndex
  317. << ": Creating external graph symbol for COFF symbol \""
  318. << SymbolName << "\" in "
  319. << getCOFFSectionName(Symbol.getSectionNumber(), Section, Symbol)
  320. << " (index: " << Symbol.getSectionNumber() << ") \n";
  321. });
  322. return ExternalSymbols[SymbolName];
  323. }
  324. Expected<Symbol *> COFFLinkGraphBuilder::createAliasSymbol(StringRef SymbolName,
  325. Linkage L, Scope S,
  326. Symbol &Target) {
  327. if (!Target.isDefined()) {
  328. // FIXME: Support this when there's a way to handle this.
  329. return make_error<JITLinkError>("Weak external symbol with external "
  330. "symbol as alternative not supported.");
  331. }
  332. return &G->addDefinedSymbol(Target.getBlock(), Target.getOffset(), SymbolName,
  333. Target.getSize(), L, S, Target.isCallable(),
  334. false);
  335. }
  336. // In COFF, most of the defined symbols don't contain the size information.
  337. // Hence, we calculate the "implicit" size of symbol by taking the delta of
  338. // offsets of consecutive symbols within a block. We maintain a balanced tree
  339. // set of symbols sorted by offset per each block in order to achieve
  340. // logarithmic time complexity of sorted symbol insertion. Symbol is inserted to
  341. // the set once it's processed in graphifySymbols. In this function, we iterate
  342. // each collected symbol in sorted order and calculate the implicit size.
  343. Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
  344. for (COFFSectionIndex SecIndex = 1;
  345. SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
  346. SecIndex++) {
  347. auto &SymbolSet = SymbolSets[SecIndex];
  348. if (SymbolSet.empty())
  349. continue;
  350. jitlink::Block *B = getGraphBlock(SecIndex);
  351. orc::ExecutorAddrDiff LastOffset = B->getSize();
  352. orc::ExecutorAddrDiff LastDifferentOffset = B->getSize();
  353. orc::ExecutorAddrDiff LastSize = 0;
  354. for (auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
  355. orc::ExecutorAddrDiff Offset = It->first;
  356. jitlink::Symbol *Symbol = It->second;
  357. orc::ExecutorAddrDiff CandSize;
  358. // Last offset can be same when aliasing happened
  359. if (Symbol->getOffset() == LastOffset)
  360. CandSize = LastSize;
  361. else
  362. CandSize = LastOffset - Offset;
  363. LLVM_DEBUG({
  364. if (Offset + Symbol->getSize() > LastDifferentOffset)
  365. dbgs() << " Overlapping symbol range generated for the following "
  366. "symbol:"
  367. << "\n"
  368. << " " << *Symbol << "\n";
  369. });
  370. (void)LastDifferentOffset;
  371. if (LastOffset != Offset)
  372. LastDifferentOffset = Offset;
  373. LastSize = CandSize;
  374. LastOffset = Offset;
  375. if (Symbol->getSize()) {
  376. // Non empty symbol can happen in COMDAT symbol.
  377. // We don't consider the possibility of overlapping symbol range that
  378. // could be introduced by disparity between inferred symbol size and
  379. // defined symbol size because symbol size information is currently only
  380. // used by jitlink-check where we have control to not make overlapping
  381. // ranges.
  382. continue;
  383. }
  384. LLVM_DEBUG({
  385. if (!CandSize)
  386. dbgs() << " Empty implicit symbol size generated for the following "
  387. "symbol:"
  388. << "\n"
  389. << " " << *Symbol << "\n";
  390. });
  391. Symbol->setSize(CandSize);
  392. }
  393. }
  394. return Error::success();
  395. }
  396. Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
  397. COFFSymbolIndex SymIndex, StringRef SymbolName,
  398. object::COFFSymbolRef Symbol, const object::coff_section *Section) {
  399. if (Symbol.isCommon()) {
  400. // FIXME: correct alignment
  401. return &G->addDefinedSymbol(
  402. G->createZeroFillBlock(getCommonSection(), Symbol.getValue(),
  403. orc::ExecutorAddr(), Symbol.getValue(), 0),
  404. 0, SymbolName, Symbol.getValue(), Linkage::Strong, Scope::Default,
  405. false, false);
  406. }
  407. if (Symbol.isAbsolute())
  408. return &G->addAbsoluteSymbol(SymbolName,
  409. orc::ExecutorAddr(Symbol.getValue()), 0,
  410. Linkage::Strong, Scope::Local, false);
  411. if (llvm::COFF::isReservedSectionNumber(Symbol.getSectionNumber()))
  412. return make_error<JITLinkError>(
  413. "Reserved section number used in regular symbol " +
  414. formatv("{0:d}", SymIndex));
  415. Block *B = getGraphBlock(Symbol.getSectionNumber());
  416. if (!B) {
  417. LLVM_DEBUG({
  418. dbgs() << " " << SymIndex
  419. << ": Skipping graph symbol since section was not created for "
  420. "COFF symbol \""
  421. << SymbolName << "\" in section " << Symbol.getSectionNumber()
  422. << "\n";
  423. });
  424. return nullptr;
  425. }
  426. if (Symbol.isExternal()) {
  427. // This is not a comdat sequence, export the symbol as it is
  428. if (!isComdatSection(Section)) {
  429. auto GSym = &G->addDefinedSymbol(
  430. *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Default,
  431. Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
  432. DefinedSymbols[SymbolName] = GSym;
  433. return GSym;
  434. } else {
  435. if (!PendingComdatExports[Symbol.getSectionNumber()])
  436. return make_error<JITLinkError>("No pending COMDAT export for symbol " +
  437. formatv("{0:d}", SymIndex));
  438. return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
  439. }
  440. }
  441. if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC ||
  442. Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_LABEL) {
  443. const object::coff_aux_section_definition *Definition =
  444. Symbol.getSectionDefinition();
  445. if (!Definition || !isComdatSection(Section)) {
  446. // Handle typical static symbol
  447. return &G->addDefinedSymbol(
  448. *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
  449. Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
  450. }
  451. if (Definition->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
  452. auto Target = Definition->getNumber(Symbol.isBigObj());
  453. auto GSym = &G->addDefinedSymbol(
  454. *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
  455. Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
  456. getGraphBlock(Target)->addEdge(Edge::KeepAlive, 0, *GSym, 0);
  457. return GSym;
  458. }
  459. if (PendingComdatExports[Symbol.getSectionNumber()])
  460. return make_error<JITLinkError>(
  461. "COMDAT export request already exists before symbol " +
  462. formatv("{0:d}", SymIndex));
  463. return createCOMDATExportRequest(SymIndex, Symbol, Definition);
  464. }
  465. return make_error<JITLinkError>("Unsupported storage class " +
  466. formatv("{0:d}", Symbol.getStorageClass()) +
  467. " in symbol " + formatv("{0:d}", SymIndex));
  468. }
  469. // COMDAT handling:
  470. // When IMAGE_SCN_LNK_COMDAT flag is set in the flags of a section,
  471. // the section is called a COMDAT section. It contains two symbols
  472. // in a sequence that specifes the behavior. First symbol is the section
  473. // symbol which contains the size and name of the section. It also contains
  474. // selection type that specifies how duplicate of the symbol is handled.
  475. // Second symbol is COMDAT symbol which usually defines the external name and
  476. // data type.
  477. //
  478. // Since two symbols always come in a specific order, we initiate pending COMDAT
  479. // export request when we encounter the first symbol and actually exports it
  480. // when we process the second symbol.
  481. //
  482. // Process the first symbol of COMDAT sequence.
  483. Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
  484. COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
  485. const object::coff_aux_section_definition *Definition) {
  486. Linkage L = Linkage::Strong;
  487. switch (Definition->Selection) {
  488. case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: {
  489. L = Linkage::Strong;
  490. break;
  491. }
  492. case COFF::IMAGE_COMDAT_SELECT_ANY: {
  493. L = Linkage::Weak;
  494. break;
  495. }
  496. case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
  497. case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: {
  498. // FIXME: Implement size/content validation when LinkGraph is able to
  499. // handle this.
  500. L = Linkage::Weak;
  501. break;
  502. }
  503. case COFF::IMAGE_COMDAT_SELECT_LARGEST: {
  504. // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST properly when LinkGraph is
  505. // able to handle this.
  506. LLVM_DEBUG({
  507. dbgs() << " " << SymIndex
  508. << ": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
  509. " in section "
  510. << Symbol.getSectionNumber() << " (size: " << Definition->Length
  511. << ")\n";
  512. });
  513. L = Linkage::Weak;
  514. break;
  515. }
  516. case COFF::IMAGE_COMDAT_SELECT_NEWEST: {
  517. // Even link.exe doesn't support this selection properly.
  518. return make_error<JITLinkError>(
  519. "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
  520. }
  521. default: {
  522. return make_error<JITLinkError>("Invalid comdat selection type: " +
  523. formatv("{0:d}", Definition->Selection));
  524. }
  525. }
  526. PendingComdatExports[Symbol.getSectionNumber()] = {SymIndex, L,
  527. Definition->Length};
  528. return nullptr;
  529. }
  530. // Process the second symbol of COMDAT sequence.
  531. Expected<Symbol *>
  532. COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
  533. StringRef SymbolName,
  534. object::COFFSymbolRef Symbol) {
  535. Block *B = getGraphBlock(Symbol.getSectionNumber());
  536. auto &PendingComdatExport = PendingComdatExports[Symbol.getSectionNumber()];
  537. // NOTE: ComdatDef->Legnth is the size of "section" not size of symbol.
  538. // We use zero symbol size to not reach out of bound of block when symbol
  539. // offset is non-zero.
  540. auto GSym = &G->addDefinedSymbol(
  541. *B, Symbol.getValue(), SymbolName, 0, PendingComdatExport->Linkage,
  542. Scope::Default, Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION,
  543. false);
  544. LLVM_DEBUG({
  545. dbgs() << " " << SymIndex
  546. << ": Exporting COMDAT graph symbol for COFF symbol \"" << SymbolName
  547. << "\" in section " << Symbol.getSectionNumber() << "\n";
  548. dbgs() << " " << *GSym << "\n";
  549. });
  550. setGraphSymbol(Symbol.getSectionNumber(), PendingComdatExport->SymbolIndex,
  551. *GSym);
  552. DefinedSymbols[SymbolName] = GSym;
  553. PendingComdatExport = std::nullopt;
  554. return GSym;
  555. }
  556. } // namespace jitlink
  557. } // namespace llvm