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 building code. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "COFFLinkGraphBuilder.h" 13 14 #include <memory> 15 16 #define DEBUG_TYPE "jitlink" 17 18 static const char *CommonSectionName = "__common"; 19 20 namespace llvm { 21 namespace jitlink { 22 23 static Triple createTripleWithCOFFFormat(Triple T) { 24 T.setObjectFormat(Triple::COFF); 25 return T; 26 } 27 28 COFFLinkGraphBuilder::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 44 COFFLinkGraphBuilder::~COFFLinkGraphBuilder() = default; 45 46 uint64_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::getSectionSize 50 if (Obj.getDOSHeader()) 51 return std::min(Sec->VirtualSize, Sec->SizeOfRawData); 52 return Sec->SizeOfRawData; 53 } 54 55 uint64_t 56 COFFLinkGraphBuilder::getSectionAddress(const object::COFFObjectFile &Obj, 57 const object::coff_section *Section) { 58 return Section->VirtualAddress + Obj.getImageBase(); 59 } 60 61 bool COFFLinkGraphBuilder::isComdatSection( 62 const object::coff_section *Section) { 63 return Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT; 64 } 65 66 Section &COFFLinkGraphBuilder::getCommonSection() { 67 if (!CommonSection) 68 CommonSection = &G->createSection(CommonSectionName, 69 orc::MemProt::Read | orc::MemProt::Write); 70 return *CommonSection; 71 } 72 73 Expected<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 89 StringRef 90 COFFLinkGraphBuilder::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 else 98 return "(external)"; 99 } 100 case COFF::IMAGE_SYM_ABSOLUTE: 101 return "(absolute)"; 102 case COFF::IMAGE_SYM_DEBUG: { 103 // Used with .file symbol 104 return "(debug)"; 105 } 106 default: { 107 // Non reserved regular section numbers 108 if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec)) 109 return *SecNameOrErr; 110 } 111 } 112 return ""; 113 } 114 115 Error 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 sections 132 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 194 Error 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 symbol 226 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() << " " << SymIndex 251 << ": 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 symbol 261 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 278 Error 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 313 Error COFFLinkGraphBuilder::flushWeakAliasRequests() { 314 // Export the weak external symbols and alias it 315 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 and 323 // IMAGE_WEAK_EXTERN_SEARCH_LIBRARY are handled in the same way. 324 Scope S = 325 WeakExternal.Characteristics == COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS 326 ? Scope::Default 327 : 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.Alias 337 << ": Creating weak external symbol for COFF symbol \"" 338 << WeakExternal.SymbolName << "\" in section " 339 << AliasSymbol->getSectionNumber() << "\n"; 340 dbgs() << " " << **NewSymbol << "\n"; 341 }); 342 } else 343 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 350 Error 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 365 Symbol *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 (!ExternalSymbols.count(SymbolName)) { 370 Sym = &G->addExternalSymbol(*SymbolName, Symbol.getValue(), false); 371 ExternalSymbols[Sym->getName()] = Sym; 372 } else { 373 Sym = ExternalSymbols[SymbolName]; 374 } 375 376 LLVM_DEBUG({ 377 dbgs() << " " << SymIndex 378 << ": 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 386 Expected<Symbol *> 387 COFFLinkGraphBuilder::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 of 401 // offsets of consecutive symbols within a block. We maintain a balanced tree 402 // set of symbols sorted by offset per each block in order to achieve 403 // logarithmic time complexity of sorted symbol insertion. Symbol is inserted to 404 // the set once it's processed in graphifySymbols. In this function, we iterate 405 // each collected symbol in sorted order and calculate the implicit size. 406 Error 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 happened 422 if (Symbol->getOffset() == LastOffset) 423 CandSize = LastSize; 424 else 425 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 that 442 // could be introduced by disparity between inferred symbol size and 443 // defined symbol size because symbol size information is currently only 444 // used by jitlink-check where we have control to not make overlapping 445 // 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 463 Expected<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 alignment 469 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() << " " << SymIndex 490 << ": 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 is 500 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 symbol 521 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 symbols 547 // in a sequence that specifes the behavior. First symbol is the section 548 // symbol which contains the size and name of the section. It also contains 549 // selection type that specifies how duplicate of the symbol is handled. 550 // Second symbol is COMDAT symbol which usually defines the external name and 551 // data type. 552 // 553 // Since two symbols always come in a specific order, we initiate pending COMDAT 554 // export request when we encounter the first symbol and actually exports it 555 // when we process the second symbol. 556 // 557 // Process the first symbol of COMDAT sequence. 558 Expected<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 to 574 // 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 is 580 // able to handle this. 581 LLVM_DEBUG({ 582 dbgs() << " " << SymIndex 583 << ": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used" 584 " in section " 585 << Symbol.getSectionNumber() << " (size: " << Definition->Length 586 << ")\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. 607 Expected<Symbol *> 608 COFFLinkGraphBuilder::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 symbol 615 // 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() << " " << SymIndex 622 << ": Exporting COMDAT graph symbol for COFF symbol \"" << SymbolName 623 << "\" 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 633 Symbol *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 jitlink 652 } // namespace llvm 653