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