brintos

brintos / llvm-project-archived public Read only

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