1 //=== DWARFLinkerImpl.cpp -------------------------------------------------===// 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 #include "DWARFLinkerImpl.h" 10 #include "DependencyTracker.h" 11 #include "llvm/DWARFLinker/Utils.h" 12 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 13 #include "llvm/Support/FormatVariadic.h" 14 #include "llvm/Support/Parallel.h" 15 #include "llvm/Support/ThreadPool.h" 16 17 using namespace llvm; 18 using namespace dwarf_linker; 19 using namespace dwarf_linker::parallel; 20 21 DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler, 22 MessageHandlerTy WarningHandler) 23 : UniqueUnitID(0), DebugStrStrings(GlobalData), 24 DebugLineStrStrings(GlobalData), CommonSections(GlobalData) { 25 GlobalData.setErrorHandler(ErrorHandler); 26 GlobalData.setWarningHandler(WarningHandler); 27 } 28 29 DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData, 30 DWARFFile &File, 31 StringMap<uint64_t> &ClangModules, 32 std::atomic<size_t> &UniqueUnitID) 33 : OutputSections(GlobalData), InputDWARFFile(File), 34 ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) { 35 36 if (File.Dwarf) { 37 if (!File.Dwarf->compile_units().empty()) 38 CompileUnits.reserve(File.Dwarf->getNumCompileUnits()); 39 40 // Set context format&endianness based on the input file. 41 Format.Version = File.Dwarf->getMaxVersion(); 42 Format.AddrSize = File.Dwarf->getCUAddrSize(); 43 Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little 44 : llvm::endianness::big; 45 } 46 } 47 48 DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit( 49 DWARFFile &File, std::unique_ptr<CompileUnit> Unit) 50 : File(File), Unit(std::move(Unit)) {} 51 52 DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit( 53 LinkContext::RefModuleUnit &&Other) 54 : File(Other.File), Unit(std::move(Other.Unit)) {} 55 56 void DWARFLinkerImpl::LinkContext::addModulesCompileUnit( 57 LinkContext::RefModuleUnit &&Unit) { 58 ModulesCompileUnits.emplace_back(std::move(Unit)); 59 } 60 61 void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader, 62 CompileUnitHandlerTy OnCUDieLoaded) { 63 ObjectContexts.emplace_back(std::make_unique<LinkContext>( 64 GlobalData, File, ClangModules, UniqueUnitID)); 65 66 if (ObjectContexts.back()->InputDWARFFile.Dwarf) { 67 for (const std::unique_ptr<DWARFUnit> &CU : 68 ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) { 69 DWARFDie CUDie = CU->getUnitDIE(); 70 OverallNumberOfCU++; 71 72 if (!CUDie) 73 continue; 74 75 OnCUDieLoaded(*CU); 76 77 // Register mofule reference. 78 if (!GlobalData.getOptions().UpdateIndexTablesOnly) 79 ObjectContexts.back()->registerModuleReference(CUDie, Loader, 80 OnCUDieLoaded); 81 } 82 } 83 } 84 85 void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) { 86 ObjectContexts.reserve(ObjFilesNum); 87 } 88 89 Error DWARFLinkerImpl::link() { 90 // reset compile unit unique ID counter. 91 UniqueUnitID = 0; 92 93 if (Error Err = validateAndUpdateOptions()) 94 return Err; 95 96 dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion, 97 0, dwarf::DwarfFormat::DWARF32}; 98 llvm::endianness GlobalEndianness = llvm::endianness::native; 99 100 if (std::optional<std::reference_wrapper<const Triple>> CurTriple = 101 GlobalData.getTargetTriple()) { 102 GlobalEndianness = (*CurTriple).get().isLittleEndian() 103 ? llvm::endianness::little 104 : llvm::endianness::big; 105 } 106 std::optional<uint16_t> Language; 107 108 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) { 109 if (Context->InputDWARFFile.Dwarf == nullptr) { 110 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness); 111 continue; 112 } 113 114 if (GlobalData.getOptions().Verbose) { 115 outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName 116 << "\n"; 117 118 for (const std::unique_ptr<DWARFUnit> &OrigCU : 119 Context->InputDWARFFile.Dwarf->compile_units()) { 120 outs() << "Input compilation unit:"; 121 DIDumpOptions DumpOpts; 122 DumpOpts.ChildRecurseDepth = 0; 123 DumpOpts.Verbose = GlobalData.getOptions().Verbose; 124 OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts); 125 } 126 } 127 128 // Verify input DWARF if requested. 129 if (GlobalData.getOptions().VerifyInputDWARF) 130 verifyInput(Context->InputDWARFFile); 131 132 if (!GlobalData.getTargetTriple()) 133 GlobalEndianness = Context->getEndianness(); 134 GlobalFormat.AddrSize = 135 std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize); 136 137 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness); 138 139 // FIXME: move creation of CompileUnits into the addObjectFile. 140 // This would allow to not scan for context Language and Modules state 141 // twice. And then following handling might be removed. 142 for (const std::unique_ptr<DWARFUnit> &OrigCU : 143 Context->InputDWARFFile.Dwarf->compile_units()) { 144 DWARFDie UnitDie = OrigCU->getUnitDIE(); 145 146 if (!Language) { 147 if (std::optional<DWARFFormValue> Val = 148 UnitDie.find(dwarf::DW_AT_language)) { 149 uint16_t LangVal = dwarf::toUnsigned(Val, 0); 150 if (isODRLanguage(LangVal)) 151 Language = LangVal; 152 } 153 } 154 } 155 } 156 157 if (GlobalFormat.AddrSize == 0) { 158 if (std::optional<std::reference_wrapper<const Triple>> TargetTriple = 159 GlobalData.getTargetTriple()) 160 GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8; 161 else 162 GlobalFormat.AddrSize = 8; 163 } 164 165 CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness); 166 167 if (!GlobalData.Options.NoODR && Language.has_value()) { 168 llvm::parallel::TaskGroup TGroup; 169 TGroup.spawn([&]() { 170 ArtificialTypeUnit = std::make_unique<TypeUnit>( 171 GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness); 172 }); 173 } 174 175 // Set parallel options. 176 if (GlobalData.getOptions().Threads == 0) 177 llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU); 178 else 179 llvm::parallel::strategy = 180 hardware_concurrency(GlobalData.getOptions().Threads); 181 182 // Link object files. 183 if (GlobalData.getOptions().Threads == 1) { 184 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) { 185 // Link object file. 186 if (Error Err = Context->link(ArtificialTypeUnit.get())) 187 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName); 188 189 Context->InputDWARFFile.unload(); 190 } 191 } else { 192 DefaultThreadPool Pool(llvm::parallel::strategy); 193 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) 194 Pool.async([&]() { 195 // Link object file. 196 if (Error Err = Context->link(ArtificialTypeUnit.get())) 197 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName); 198 199 Context->InputDWARFFile.unload(); 200 }); 201 202 Pool.wait(); 203 } 204 205 if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool() 206 .getRoot() 207 ->getValue() 208 .load() 209 ->Children.empty()) { 210 if (GlobalData.getTargetTriple().has_value()) 211 if (Error Err = ArtificialTypeUnit->finishCloningAndEmit( 212 (*GlobalData.getTargetTriple()).get())) 213 return Err; 214 } 215 216 // At this stage each compile units are cloned to their own set of debug 217 // sections. Now, update patches, assign offsets and assemble final file 218 // glueing debug tables from each compile unit. 219 glueCompileUnitsAndWriteToTheOutput(); 220 221 return Error::success(); 222 } 223 224 void DWARFLinkerImpl::verifyInput(const DWARFFile &File) { 225 assert(File.Dwarf); 226 227 std::string Buffer; 228 raw_string_ostream OS(Buffer); 229 DIDumpOptions DumpOpts; 230 if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) { 231 if (GlobalData.getOptions().InputVerificationHandler) 232 GlobalData.getOptions().InputVerificationHandler(File, OS.str()); 233 } 234 } 235 236 Error DWARFLinkerImpl::validateAndUpdateOptions() { 237 if (GlobalData.getOptions().TargetDWARFVersion == 0) 238 return createStringError(std::errc::invalid_argument, 239 "target DWARF version is not set"); 240 241 if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) { 242 GlobalData.Options.Threads = 1; 243 GlobalData.warn( 244 "set number of threads to 1 to make --verbose to work properly.", ""); 245 } 246 247 // Do not do types deduplication in case --update. 248 if (GlobalData.getOptions().UpdateIndexTablesOnly && 249 !GlobalData.Options.NoODR) 250 GlobalData.Options.NoODR = true; 251 252 return Error::success(); 253 } 254 255 /// Resolve the relative path to a build artifact referenced by DWARF by 256 /// applying DW_AT_comp_dir. 257 static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { 258 sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), "")); 259 } 260 261 static uint64_t getDwoId(const DWARFDie &CUDie) { 262 auto DwoId = dwarf::toUnsigned( 263 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id})); 264 if (DwoId) 265 return *DwoId; 266 return 0; 267 } 268 269 static std::string 270 remapPath(StringRef Path, 271 const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) { 272 if (ObjectPrefixMap.empty()) 273 return Path.str(); 274 275 SmallString<256> p = Path; 276 for (const auto &Entry : ObjectPrefixMap) 277 if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second)) 278 break; 279 return p.str().str(); 280 } 281 282 static std::string getPCMFile(const DWARFDie &CUDie, 283 DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) { 284 std::string PCMFile = dwarf::toString( 285 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); 286 287 if (PCMFile.empty()) 288 return PCMFile; 289 290 if (ObjectPrefixMap) 291 PCMFile = remapPath(PCMFile, *ObjectPrefixMap); 292 293 return PCMFile; 294 } 295 296 std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef( 297 const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) { 298 if (PCMFile.empty()) 299 return std::make_pair(false, false); 300 301 // Clang module DWARF skeleton CUs abuse this for the path to the module. 302 uint64_t DwoId = getDwoId(CUDie); 303 304 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 305 if (Name.empty()) { 306 if (!Quiet) 307 GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".", 308 InputDWARFFile.FileName); 309 return std::make_pair(true, true); 310 } 311 312 if (!Quiet && GlobalData.getOptions().Verbose) { 313 outs().indent(Indent); 314 outs() << "Found clang module reference " << PCMFile; 315 } 316 317 auto Cached = ClangModules.find(PCMFile); 318 if (Cached != ClangModules.end()) { 319 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 320 // fixed in clang, only warn about DWO_id mismatches in verbose mode. 321 // ASTFileSignatures will change randomly when a module is rebuilt. 322 if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId)) 323 GlobalData.warn( 324 Twine("hash mismatch: this object file was built against a " 325 "different version of the module ") + 326 PCMFile + ".", 327 InputDWARFFile.FileName); 328 if (!Quiet && GlobalData.getOptions().Verbose) 329 outs() << " [cached].\n"; 330 return std::make_pair(true, true); 331 } 332 333 return std::make_pair(true, false); 334 } 335 336 /// If this compile unit is really a skeleton CU that points to a 337 /// clang module, register it in ClangModules and return true. 338 /// 339 /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name 340 /// pointing to the module, and a DW_AT_gnu_dwo_id with the module 341 /// hash. 342 bool DWARFLinkerImpl::LinkContext::registerModuleReference( 343 const DWARFDie &CUDie, ObjFileLoaderTy Loader, 344 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 345 std::string PCMFile = 346 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap); 347 std::pair<bool, bool> IsClangModuleRef = 348 isClangModuleRef(CUDie, PCMFile, Indent, false); 349 350 if (!IsClangModuleRef.first) 351 return false; 352 353 if (IsClangModuleRef.second) 354 return true; 355 356 if (GlobalData.getOptions().Verbose) 357 outs() << " ...\n"; 358 359 // Cyclic dependencies are disallowed by Clang, but we still 360 // shouldn't run into an infinite loop, so mark it as processed now. 361 ClangModules.insert({PCMFile, getDwoId(CUDie)}); 362 363 if (Error E = 364 loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) { 365 consumeError(std::move(E)); 366 return false; 367 } 368 return true; 369 } 370 371 Error DWARFLinkerImpl::LinkContext::loadClangModule( 372 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile, 373 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 374 375 uint64_t DwoId = getDwoId(CUDie); 376 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 377 378 /// Using a SmallString<0> because loadClangModule() is recursive. 379 SmallString<0> Path(GlobalData.getOptions().PrependPath); 380 if (sys::path::is_relative(PCMFile)) 381 resolveRelativeObjectPath(Path, CUDie); 382 sys::path::append(Path, PCMFile); 383 // Don't use the cached binary holder because we have no thread-safety 384 // guarantee and the lifetime is limited. 385 386 if (Loader == nullptr) { 387 GlobalData.error("cann't load clang module: loader is not specified.", 388 InputDWARFFile.FileName); 389 return Error::success(); 390 } 391 392 auto ErrOrObj = Loader(InputDWARFFile.FileName, Path); 393 if (!ErrOrObj) 394 return Error::success(); 395 396 std::unique_ptr<CompileUnit> Unit; 397 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { 398 OnCUDieLoaded(*CU); 399 // Recursively get all modules imported by this one. 400 auto ChildCUDie = CU->getUnitDIE(); 401 if (!ChildCUDie) 402 continue; 403 if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) { 404 if (Unit) { 405 std::string Err = 406 (PCMFile + 407 ": Clang modules are expected to have exactly 1 compile unit.\n"); 408 GlobalData.error(Err, InputDWARFFile.FileName); 409 return make_error<StringError>(Err, inconvertibleErrorCode()); 410 } 411 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 412 // fixed in clang, only warn about DWO_id mismatches in verbose mode. 413 // ASTFileSignatures will change randomly when a module is rebuilt. 414 uint64_t PCMDwoId = getDwoId(ChildCUDie); 415 if (PCMDwoId != DwoId) { 416 if (GlobalData.getOptions().Verbose) 417 GlobalData.warn( 418 Twine("hash mismatch: this object file was built against a " 419 "different version of the module ") + 420 PCMFile + ".", 421 InputDWARFFile.FileName); 422 // Update the cache entry with the DwoId of the module loaded from disk. 423 ClangModules[PCMFile] = PCMDwoId; 424 } 425 426 // Empty modules units should not be cloned. 427 if (!ChildCUDie.hasChildren()) 428 continue; 429 430 // Add this module. 431 Unit = std::make_unique<CompileUnit>( 432 GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj, 433 getUnitForOffset, CU->getFormParams(), getEndianness()); 434 } 435 } 436 437 if (Unit) { 438 ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)}); 439 // Preload line table, as it can't be loaded asynchronously. 440 ModulesCompileUnits.back().Unit->loadLineTable(); 441 } 442 443 return Error::success(); 444 } 445 446 Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) { 447 InterCUProcessingStarted = false; 448 if (!InputDWARFFile.Dwarf) 449 return Error::success(); 450 451 // Preload macro tables, as they can't be loaded asynchronously. 452 InputDWARFFile.Dwarf->getDebugMacinfo(); 453 InputDWARFFile.Dwarf->getDebugMacro(); 454 455 // Link modules compile units first. 456 parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) { 457 linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit); 458 }); 459 460 // Check for live relocations. If there is no any live relocation then we 461 // can skip entire object file. 462 if (!GlobalData.getOptions().UpdateIndexTablesOnly && 463 !InputDWARFFile.Addresses->hasValidRelocs()) { 464 if (GlobalData.getOptions().Verbose) 465 outs() << "No valid relocations found. Skipping.\n"; 466 return Error::success(); 467 } 468 469 OriginalDebugInfoSize = getInputDebugInfoSize(); 470 471 // Create CompileUnit structures to keep information about source 472 // DWARFUnit`s, load line tables. 473 for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) { 474 // Load only unit DIE at this stage. 475 auto CUDie = OrigCU->getUnitDIE(); 476 std::string PCMFile = 477 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap); 478 479 // The !isClangModuleRef condition effectively skips over fully resolved 480 // skeleton units. 481 if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly || 482 !isClangModuleRef(CUDie, PCMFile, 0, true).first) { 483 CompileUnits.emplace_back(std::make_unique<CompileUnit>( 484 GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile, 485 getUnitForOffset, OrigCU->getFormParams(), getEndianness())); 486 487 // Preload line table, as it can't be loaded asynchronously. 488 CompileUnits.back()->loadLineTable(); 489 } 490 }; 491 492 HasNewInterconnectedCUs = false; 493 494 // Link self-sufficient compile units and discover inter-connected compile 495 // units. 496 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 497 linkSingleCompileUnit(*CU, ArtificialTypeUnit); 498 }); 499 500 // Link all inter-connected units. 501 if (HasNewInterconnectedCUs) { 502 InterCUProcessingStarted = true; 503 504 if (Error Err = finiteLoop([&]() -> Expected<bool> { 505 HasNewInterconnectedCUs = false; 506 507 // Load inter-connected units. 508 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 509 if (CU->isInterconnectedCU()) { 510 CU->maybeResetToLoadedStage(); 511 linkSingleCompileUnit(*CU, ArtificialTypeUnit, 512 CompileUnit::Stage::Loaded); 513 } 514 }); 515 516 // Do liveness analysis for inter-connected units. 517 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 518 linkSingleCompileUnit(*CU, ArtificialTypeUnit, 519 CompileUnit::Stage::LivenessAnalysisDone); 520 }); 521 522 return HasNewInterconnectedCUs.load(); 523 })) 524 return Err; 525 526 // Update dependencies. 527 if (Error Err = finiteLoop([&]() -> Expected<bool> { 528 HasNewGlobalDependency = false; 529 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 530 linkSingleCompileUnit( 531 *CU, ArtificialTypeUnit, 532 CompileUnit::Stage::UpdateDependenciesCompleteness); 533 }); 534 return HasNewGlobalDependency.load(); 535 })) 536 return Err; 537 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 538 if (CU->isInterconnectedCU() && 539 CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone) 540 CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness); 541 }); 542 543 // Assign type names. 544 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 545 linkSingleCompileUnit(*CU, ArtificialTypeUnit, 546 CompileUnit::Stage::TypeNamesAssigned); 547 }); 548 549 // Clone inter-connected units. 550 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 551 linkSingleCompileUnit(*CU, ArtificialTypeUnit, 552 CompileUnit::Stage::Cloned); 553 }); 554 555 // Update patches for inter-connected units. 556 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 557 linkSingleCompileUnit(*CU, ArtificialTypeUnit, 558 CompileUnit::Stage::PatchesUpdated); 559 }); 560 561 // Release data. 562 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 563 linkSingleCompileUnit(*CU, ArtificialTypeUnit, 564 CompileUnit::Stage::Cleaned); 565 }); 566 } 567 568 if (GlobalData.getOptions().UpdateIndexTablesOnly) { 569 // Emit Invariant sections. 570 571 if (Error Err = emitInvariantSections()) 572 return Err; 573 } else if (!CompileUnits.empty()) { 574 // Emit .debug_frame section. 575 576 Error ResultErr = Error::success(); 577 llvm::parallel::TaskGroup TGroup; 578 // We use task group here as PerThreadBumpPtrAllocator should be called from 579 // the threads created by ThreadPoolExecutor. 580 TGroup.spawn([&]() { 581 if (Error Err = cloneAndEmitDebugFrame()) 582 ResultErr = std::move(Err); 583 }); 584 return ResultErr; 585 } 586 587 return Error::success(); 588 } 589 590 void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit( 591 CompileUnit &CU, TypeUnit *ArtificialTypeUnit, 592 enum CompileUnit::Stage DoUntilStage) { 593 if (InterCUProcessingStarted != CU.isInterconnectedCU()) 594 return; 595 596 if (Error Err = finiteLoop([&]() -> Expected<bool> { 597 if (CU.getStage() >= DoUntilStage) 598 return false; 599 600 switch (CU.getStage()) { 601 case CompileUnit::Stage::CreatedNotLoaded: { 602 // Load input compilation unit DIEs. 603 // Analyze properties of DIEs. 604 if (!CU.loadInputDIEs()) { 605 // We do not need to do liveness analysis for invalid compilation 606 // unit. 607 CU.setStage(CompileUnit::Stage::Skipped); 608 } else { 609 CU.analyzeDWARFStructure(); 610 611 // The registerModuleReference() condition effectively skips 612 // over fully resolved skeleton units. This second pass of 613 // registerModuleReferences doesn't do any new work, but it 614 // will collect top-level errors, which are suppressed. Module 615 // warnings were already displayed in the first iteration. 616 if (registerModuleReference( 617 CU.getOrigUnit().getUnitDIE(), nullptr, 618 [](const DWARFUnit &) {}, 0)) 619 CU.setStage(CompileUnit::Stage::PatchesUpdated); 620 else 621 CU.setStage(CompileUnit::Stage::Loaded); 622 } 623 } break; 624 625 case CompileUnit::Stage::Loaded: { 626 // Mark all the DIEs that need to be present in the generated output. 627 // If ODR requested, build type names. 628 if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted, 629 HasNewInterconnectedCUs)) { 630 assert(HasNewInterconnectedCUs && 631 "Flag indicating new inter-connections is not set"); 632 return false; 633 } 634 635 CU.setStage(CompileUnit::Stage::LivenessAnalysisDone); 636 } break; 637 638 case CompileUnit::Stage::LivenessAnalysisDone: { 639 if (InterCUProcessingStarted) { 640 if (CU.updateDependenciesCompleteness()) 641 HasNewGlobalDependency = true; 642 return false; 643 } else { 644 if (Error Err = finiteLoop([&]() -> Expected<bool> { 645 return CU.updateDependenciesCompleteness(); 646 })) 647 return std::move(Err); 648 649 CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness); 650 } 651 } break; 652 653 case CompileUnit::Stage::UpdateDependenciesCompleteness: 654 #ifndef NDEBUG 655 CU.verifyDependencies(); 656 #endif 657 658 if (ArtificialTypeUnit) { 659 if (Error Err = 660 CU.assignTypeNames(ArtificialTypeUnit->getTypePool())) 661 return std::move(Err); 662 } 663 CU.setStage(CompileUnit::Stage::TypeNamesAssigned); 664 break; 665 666 case CompileUnit::Stage::TypeNamesAssigned: 667 // Clone input compile unit. 668 if (CU.isClangModule() || 669 GlobalData.getOptions().UpdateIndexTablesOnly || 670 CU.getContaingFile().Addresses->hasValidRelocs()) { 671 if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(), 672 ArtificialTypeUnit)) 673 return std::move(Err); 674 } 675 676 CU.setStage(CompileUnit::Stage::Cloned); 677 break; 678 679 case CompileUnit::Stage::Cloned: 680 // Update DIEs referencies. 681 CU.updateDieRefPatchesWithClonedOffsets(); 682 CU.setStage(CompileUnit::Stage::PatchesUpdated); 683 break; 684 685 case CompileUnit::Stage::PatchesUpdated: 686 // Cleanup resources. 687 CU.cleanupDataAfterClonning(); 688 CU.setStage(CompileUnit::Stage::Cleaned); 689 break; 690 691 case CompileUnit::Stage::Cleaned: 692 assert(false); 693 break; 694 695 case CompileUnit::Stage::Skipped: 696 // Nothing to do. 697 break; 698 } 699 700 return true; 701 })) { 702 CU.error(std::move(Err)); 703 CU.cleanupDataAfterClonning(); 704 CU.setStage(CompileUnit::Stage::Skipped); 705 } 706 } 707 708 Error DWARFLinkerImpl::LinkContext::emitInvariantSections() { 709 if (!GlobalData.getTargetTriple().has_value()) 710 return Error::success(); 711 712 getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS 713 << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data; 714 getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS 715 << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data; 716 getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS 717 << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data; 718 getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS 719 << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data; 720 getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS 721 << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection(); 722 getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS 723 << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data; 724 getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS 725 << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data; 726 727 return Error::success(); 728 } 729 730 Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() { 731 if (!GlobalData.getTargetTriple().has_value()) 732 return Error::success(); 733 734 if (InputDWARFFile.Dwarf == nullptr) 735 return Error::success(); 736 737 const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj(); 738 739 StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data; 740 if (OrigFrameData.empty()) 741 return Error::success(); 742 743 RangesTy AllUnitsRanges; 744 for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) { 745 for (auto CurRange : Unit->getFunctionRanges()) 746 AllUnitsRanges.insert(CurRange.Range, CurRange.Value); 747 } 748 749 unsigned SrcAddrSize = InputDWARFObj.getAddressSize(); 750 751 SectionDescriptor &OutSection = 752 getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame); 753 754 DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0); 755 uint64_t InputOffset = 0; 756 757 // Store the data of the CIEs defined in this object, keyed by their 758 // offsets. 759 DenseMap<uint64_t, StringRef> LocalCIES; 760 761 /// The CIEs that have been emitted in the output section. The actual CIE 762 /// data serves a the key to this StringMap. 763 StringMap<uint32_t> EmittedCIEs; 764 765 while (Data.isValidOffset(InputOffset)) { 766 uint64_t EntryOffset = InputOffset; 767 uint32_t InitialLength = Data.getU32(&InputOffset); 768 if (InitialLength == 0xFFFFFFFF) 769 return createFileError(InputDWARFObj.getFileName(), 770 createStringError(std::errc::invalid_argument, 771 "Dwarf64 bits no supported")); 772 773 uint32_t CIEId = Data.getU32(&InputOffset); 774 if (CIEId == 0xFFFFFFFF) { 775 // This is a CIE, store it. 776 StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4); 777 LocalCIES[EntryOffset] = CIEData; 778 // The -4 is to account for the CIEId we just read. 779 InputOffset += InitialLength - 4; 780 continue; 781 } 782 783 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize); 784 785 // Some compilers seem to emit frame info that doesn't start at 786 // the function entry point, thus we can't just lookup the address 787 // in the debug map. Use the AddressInfo's range map to see if the FDE 788 // describes something that we can relocate. 789 std::optional<AddressRangeValuePair> Range = 790 AllUnitsRanges.getRangeThatContains(Loc); 791 if (!Range) { 792 // The +4 is to account for the size of the InitialLength field itself. 793 InputOffset = EntryOffset + InitialLength + 4; 794 continue; 795 } 796 797 // This is an FDE, and we have a mapping. 798 // Have we already emitted a corresponding CIE? 799 StringRef CIEData = LocalCIES[CIEId]; 800 if (CIEData.empty()) 801 return createFileError( 802 InputDWARFObj.getFileName(), 803 createStringError(std::errc::invalid_argument, 804 "Inconsistent debug_frame content. Dropping.")); 805 806 uint64_t OffsetToCIERecord = OutSection.OS.tell(); 807 808 // Look if we already emitted a CIE that corresponds to the 809 // referenced one (the CIE data is the key of that lookup). 810 auto IteratorInserted = 811 EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord)); 812 OffsetToCIERecord = IteratorInserted.first->getValue(); 813 814 // Emit CIE for this ID if it is not emitted yet. 815 if (IteratorInserted.second) 816 OutSection.OS << CIEData; 817 818 // Remember offset to the FDE record, so that we might update 819 // field referencing CIE record(containing OffsetToCIERecord), 820 // when final offsets are known. OffsetToCIERecord(which is written later) 821 // is local to the current .debug_frame section, it should be updated 822 // with final offset of the .debug_frame section. 823 OutSection.notePatch( 824 DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true}); 825 826 // Emit the FDE with updated address and CIE pointer. 827 // (4 + AddrSize) is the size of the CIEId + initial_location 828 // fields that will get reconstructed by emitFDE(). 829 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize); 830 emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value, 831 OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection); 832 InputOffset += FDERemainingBytes; 833 } 834 835 return Error::success(); 836 } 837 838 /// Emit a FDE into the debug_frame section. \p FDEBytes 839 /// contains the FDE data without the length, CIE offset and address 840 /// which will be replaced with the parameter values. 841 void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset, 842 uint32_t AddrSize, uint64_t Address, 843 StringRef FDEBytes, 844 SectionDescriptor &Section) { 845 Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4); 846 Section.emitIntVal(CIEOffset, 4); 847 Section.emitIntVal(Address, AddrSize); 848 Section.OS.write(FDEBytes.data(), FDEBytes.size()); 849 } 850 851 void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() { 852 if (!GlobalData.getTargetTriple().has_value()) 853 return; 854 assert(SectionHandler); 855 856 // Go through all object files, all compile units and assign 857 // offsets to them. 858 assignOffsets(); 859 860 // Patch size/offsets fields according to the assigned CU offsets. 861 patchOffsetsAndSizes(); 862 863 // Emit common sections and write debug tables from all object files/compile 864 // units into the resulting file. 865 emitCommonSectionsAndWriteCompileUnitsToTheOutput(); 866 867 if (ArtificialTypeUnit != nullptr) 868 ArtificialTypeUnit.reset(); 869 870 // Write common debug sections into the resulting file. 871 writeCommonSectionsToTheOutput(); 872 873 // Cleanup data. 874 cleanupDataAfterDWARFOutputIsWritten(); 875 876 if (GlobalData.getOptions().Statistics) 877 printStatistic(); 878 } 879 880 void DWARFLinkerImpl::printStatistic() { 881 882 // For each object file map how many bytes were emitted. 883 StringMap<DebugInfoSize> SizeByObject; 884 885 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) { 886 uint64_t AllDebugInfoSectionsSize = 0; 887 888 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 889 if (std::optional<SectionDescriptor *> DebugInfo = 890 CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) 891 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size(); 892 893 auto &Size = SizeByObject[Context->InputDWARFFile.FileName]; 894 Size.Input = Context->OriginalDebugInfoSize; 895 Size.Output = AllDebugInfoSectionsSize; 896 } 897 898 // Create a vector sorted in descending order by output size. 899 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted; 900 for (auto &E : SizeByObject) 901 Sorted.emplace_back(E.first(), E.second); 902 llvm::sort(Sorted, [](auto &LHS, auto &RHS) { 903 return LHS.second.Output > RHS.second.Output; 904 }); 905 906 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float { 907 const float Difference = Output - Input; 908 const float Sum = Input + Output; 909 if (Sum == 0) 910 return 0; 911 return (Difference / (Sum / 2)); 912 }; 913 914 int64_t InputTotal = 0; 915 int64_t OutputTotal = 0; 916 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n"; 917 918 // Print header. 919 outs() << ".debug_info section size (in bytes)\n"; 920 outs() << "----------------------------------------------------------------" 921 "---------------\n"; 922 outs() << "Filename Object " 923 " dSYM Change\n"; 924 outs() << "----------------------------------------------------------------" 925 "---------------\n"; 926 927 // Print body. 928 for (auto &E : Sorted) { 929 InputTotal += E.second.Input; 930 OutputTotal += E.second.Output; 931 llvm::outs() << formatv( 932 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input, 933 E.second.Output, ComputePercentange(E.second.Input, E.second.Output)); 934 } 935 // Print total and footer. 936 outs() << "----------------------------------------------------------------" 937 "---------------\n"; 938 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal, 939 ComputePercentange(InputTotal, OutputTotal)); 940 outs() << "----------------------------------------------------------------" 941 "---------------\n\n"; 942 } 943 944 void DWARFLinkerImpl::assignOffsets() { 945 llvm::parallel::TaskGroup TGroup; 946 TGroup.spawn([&]() { assignOffsetsToStrings(); }); 947 TGroup.spawn([&]() { assignOffsetsToSections(); }); 948 } 949 950 void DWARFLinkerImpl::assignOffsetsToStrings() { 951 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry. 952 uint64_t CurDebugStrOffset = 953 1; // start from 1 to take into account zero entry. 954 size_t CurDebugLineStrIndex = 0; 955 uint64_t CurDebugLineStrOffset = 0; 956 957 // Enumerates all strings, add them into the DwarfStringPoolEntry map, 958 // assign offset and index to the string if it is not indexed yet. 959 forEachOutputString([&](StringDestinationKind Kind, 960 const StringEntry *String) { 961 switch (Kind) { 962 case StringDestinationKind::DebugStr: { 963 DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String); 964 assert(Entry != nullptr); 965 966 if (!Entry->isIndexed()) { 967 Entry->Offset = CurDebugStrOffset; 968 CurDebugStrOffset += Entry->String.size() + 1; 969 Entry->Index = CurDebugStrIndex++; 970 } 971 } break; 972 case StringDestinationKind::DebugLineStr: { 973 DwarfStringPoolEntryWithExtString *Entry = 974 DebugLineStrStrings.add(String); 975 assert(Entry != nullptr); 976 977 if (!Entry->isIndexed()) { 978 Entry->Offset = CurDebugLineStrOffset; 979 CurDebugLineStrOffset += Entry->String.size() + 1; 980 Entry->Index = CurDebugLineStrIndex++; 981 } 982 } break; 983 } 984 }); 985 } 986 987 void DWARFLinkerImpl::assignOffsetsToSections() { 988 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0}; 989 990 forEachObjectSectionsSet([&](OutputSections &UnitSections) { 991 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator); 992 }); 993 } 994 995 void DWARFLinkerImpl::forEachOutputString( 996 function_ref<void(StringDestinationKind Kind, const StringEntry *String)> 997 StringHandler) { 998 // To save space we do not create any separate string table. 999 // We use already allocated string patches and accelerator entries: 1000 // enumerate them in natural order and assign offsets. 1001 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str 1002 // sections in the same order as they were assigned offsets. 1003 forEachCompileUnit([&](CompileUnit *CU) { 1004 CU->forEach([&](SectionDescriptor &OutSection) { 1005 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) { 1006 StringHandler(StringDestinationKind::DebugStr, Patch.String); 1007 }); 1008 1009 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) { 1010 StringHandler(StringDestinationKind::DebugLineStr, Patch.String); 1011 }); 1012 }); 1013 1014 CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) { 1015 StringHandler(DebugStr, Info.String); 1016 }); 1017 }); 1018 1019 if (ArtificialTypeUnit != nullptr) { 1020 ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) { 1021 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) { 1022 StringHandler(StringDestinationKind::DebugStr, Patch.String); 1023 }); 1024 1025 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) { 1026 StringHandler(StringDestinationKind::DebugLineStr, Patch.String); 1027 }); 1028 1029 OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) { 1030 if (Patch.Die == nullptr) 1031 return; 1032 1033 StringHandler(StringDestinationKind::DebugStr, Patch.String); 1034 }); 1035 1036 OutSection.ListDebugTypeLineStrPatch.forEach( 1037 [&](DebugTypeLineStrPatch &Patch) { 1038 if (Patch.Die == nullptr) 1039 return; 1040 1041 StringHandler(StringDestinationKind::DebugStr, Patch.String); 1042 }); 1043 }); 1044 } 1045 } 1046 1047 void DWARFLinkerImpl::forEachObjectSectionsSet( 1048 function_ref<void(OutputSections &)> SectionsSetHandler) { 1049 // Handle artificial type unit first. 1050 if (ArtificialTypeUnit != nullptr) 1051 SectionsSetHandler(*ArtificialTypeUnit); 1052 1053 // Then all modules(before regular compilation units). 1054 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1055 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 1056 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 1057 SectionsSetHandler(*ModuleUnit.Unit); 1058 1059 // Finally all compilation units. 1060 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) { 1061 // Handle object file common sections. 1062 SectionsSetHandler(*Context); 1063 1064 // Handle compilation units. 1065 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 1066 if (CU->getStage() != CompileUnit::Stage::Skipped) 1067 SectionsSetHandler(*CU); 1068 } 1069 } 1070 1071 void DWARFLinkerImpl::forEachCompileAndTypeUnit( 1072 function_ref<void(DwarfUnit *CU)> UnitHandler) { 1073 if (ArtificialTypeUnit != nullptr) 1074 UnitHandler(ArtificialTypeUnit.get()); 1075 1076 // Enumerate module units. 1077 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1078 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 1079 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 1080 UnitHandler(ModuleUnit.Unit.get()); 1081 1082 // Enumerate compile units. 1083 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1084 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 1085 if (CU->getStage() != CompileUnit::Stage::Skipped) 1086 UnitHandler(CU.get()); 1087 } 1088 1089 void DWARFLinkerImpl::forEachCompileUnit( 1090 function_ref<void(CompileUnit *CU)> UnitHandler) { 1091 // Enumerate module units. 1092 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1093 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 1094 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 1095 UnitHandler(ModuleUnit.Unit.get()); 1096 1097 // Enumerate compile units. 1098 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1099 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 1100 if (CU->getStage() != CompileUnit::Stage::Skipped) 1101 UnitHandler(CU.get()); 1102 } 1103 1104 void DWARFLinkerImpl::patchOffsetsAndSizes() { 1105 forEachObjectSectionsSet([&](OutputSections &SectionsSet) { 1106 SectionsSet.forEach([&](SectionDescriptor &OutSection) { 1107 SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings, 1108 ArtificialTypeUnit.get()); 1109 }); 1110 }); 1111 } 1112 1113 void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() { 1114 llvm::parallel::TaskGroup TG; 1115 1116 // Create section descriptors ahead if they are not exist at the moment. 1117 // SectionDescriptors container is not thread safe. Thus we should be sure 1118 // that descriptors would not be created in following parallel tasks. 1119 1120 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr); 1121 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr); 1122 1123 if (llvm::is_contained(GlobalData.Options.AccelTables, 1124 AccelTableKind::Apple)) { 1125 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames); 1126 CommonSections.getOrCreateSectionDescriptor( 1127 DebugSectionKind::AppleNamespaces); 1128 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC); 1129 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes); 1130 } 1131 1132 if (llvm::is_contained(GlobalData.Options.AccelTables, 1133 AccelTableKind::DebugNames)) 1134 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames); 1135 1136 // Emit .debug_str and .debug_line_str sections. 1137 TG.spawn([&]() { emitStringSections(); }); 1138 1139 if (llvm::is_contained(GlobalData.Options.AccelTables, 1140 AccelTableKind::Apple)) { 1141 // Emit apple accelerator sections. 1142 TG.spawn([&]() { 1143 emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get()); 1144 }); 1145 } 1146 1147 if (llvm::is_contained(GlobalData.Options.AccelTables, 1148 AccelTableKind::DebugNames)) { 1149 // Emit .debug_names section. 1150 TG.spawn([&]() { 1151 emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get()); 1152 }); 1153 } 1154 1155 // Write compile units to the output file. 1156 TG.spawn([&]() { writeCompileUnitsToTheOutput(); }); 1157 } 1158 1159 void DWARFLinkerImpl::emitStringSections() { 1160 uint64_t DebugStrNextOffset = 0; 1161 uint64_t DebugLineStrNextOffset = 0; 1162 1163 // Emit zero length string. Accelerator tables does not work correctly 1164 // if the first string is not zero length string. 1165 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr) 1166 .emitInplaceString(""); 1167 DebugStrNextOffset++; 1168 1169 forEachOutputString( 1170 [&](StringDestinationKind Kind, const StringEntry *String) { 1171 switch (Kind) { 1172 case StringDestinationKind::DebugStr: { 1173 DwarfStringPoolEntryWithExtString *StringToEmit = 1174 DebugStrStrings.getExistingEntry(String); 1175 assert(StringToEmit->isIndexed()); 1176 1177 // Strings may be repeated. Use accumulated DebugStrNextOffset 1178 // to understand whether corresponding string is already emitted. 1179 // Skip string if its offset less than accumulated offset. 1180 if (StringToEmit->Offset >= DebugStrNextOffset) { 1181 DebugStrNextOffset = 1182 StringToEmit->Offset + StringToEmit->String.size() + 1; 1183 // Emit the string itself. 1184 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr) 1185 .emitInplaceString(StringToEmit->String); 1186 } 1187 } break; 1188 case StringDestinationKind::DebugLineStr: { 1189 DwarfStringPoolEntryWithExtString *StringToEmit = 1190 DebugLineStrStrings.getExistingEntry(String); 1191 assert(StringToEmit->isIndexed()); 1192 1193 // Strings may be repeated. Use accumulated DebugLineStrStrings 1194 // to understand whether corresponding string is already emitted. 1195 // Skip string if its offset less than accumulated offset. 1196 if (StringToEmit->Offset >= DebugLineStrNextOffset) { 1197 DebugLineStrNextOffset = 1198 StringToEmit->Offset + StringToEmit->String.size() + 1; 1199 // Emit the string itself. 1200 CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr) 1201 .emitInplaceString(StringToEmit->String); 1202 } 1203 } break; 1204 } 1205 }); 1206 } 1207 1208 void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) { 1209 AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces; 1210 AccelTable<AppleAccelTableStaticOffsetData> AppleNames; 1211 AccelTable<AppleAccelTableStaticOffsetData> AppleObjC; 1212 AccelTable<AppleAccelTableStaticTypeData> AppleTypes; 1213 1214 forEachCompileAndTypeUnit([&](DwarfUnit *CU) { 1215 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 1216 uint64_t OutOffset = Info.OutOffset; 1217 switch (Info.Type) { 1218 case DwarfUnit::AccelType::None: { 1219 llvm_unreachable("Unknown accelerator record"); 1220 } break; 1221 case DwarfUnit::AccelType::Namespace: { 1222 AppleNamespaces.addName( 1223 *DebugStrStrings.getExistingEntry(Info.String), 1224 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1225 OutOffset); 1226 } break; 1227 case DwarfUnit::AccelType::Name: { 1228 AppleNames.addName( 1229 *DebugStrStrings.getExistingEntry(Info.String), 1230 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1231 OutOffset); 1232 } break; 1233 case DwarfUnit::AccelType::ObjC: { 1234 AppleObjC.addName( 1235 *DebugStrStrings.getExistingEntry(Info.String), 1236 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1237 OutOffset); 1238 } break; 1239 case DwarfUnit::AccelType::Type: { 1240 AppleTypes.addName( 1241 *DebugStrStrings.getExistingEntry(Info.String), 1242 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1243 OutOffset, 1244 Info.Tag, 1245 Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation 1246 : 0, 1247 Info.QualifiedNameHash); 1248 } break; 1249 } 1250 }); 1251 }); 1252 1253 { 1254 // FIXME: we use AsmPrinter to emit accelerator sections. 1255 // It might be beneficial to directly emit accelerator data 1256 // to the raw_svector_ostream. 1257 SectionDescriptor &OutSection = 1258 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces); 1259 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1260 OutSection.OS); 1261 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1262 consumeError(std::move(Err)); 1263 return; 1264 } 1265 1266 // Emit table. 1267 Emitter.emitAppleNamespaces(AppleNamespaces); 1268 Emitter.finish(); 1269 1270 // Set start offset and size for output section. 1271 OutSection.setSizesForSectionCreatedByAsmPrinter(); 1272 } 1273 1274 { 1275 // FIXME: we use AsmPrinter to emit accelerator sections. 1276 // It might be beneficial to directly emit accelerator data 1277 // to the raw_svector_ostream. 1278 SectionDescriptor &OutSection = 1279 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames); 1280 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1281 OutSection.OS); 1282 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1283 consumeError(std::move(Err)); 1284 return; 1285 } 1286 1287 // Emit table. 1288 Emitter.emitAppleNames(AppleNames); 1289 Emitter.finish(); 1290 1291 // Set start offset ans size for output section. 1292 OutSection.setSizesForSectionCreatedByAsmPrinter(); 1293 } 1294 1295 { 1296 // FIXME: we use AsmPrinter to emit accelerator sections. 1297 // It might be beneficial to directly emit accelerator data 1298 // to the raw_svector_ostream. 1299 SectionDescriptor &OutSection = 1300 CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC); 1301 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1302 OutSection.OS); 1303 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1304 consumeError(std::move(Err)); 1305 return; 1306 } 1307 1308 // Emit table. 1309 Emitter.emitAppleObjc(AppleObjC); 1310 Emitter.finish(); 1311 1312 // Set start offset ans size for output section. 1313 OutSection.setSizesForSectionCreatedByAsmPrinter(); 1314 } 1315 1316 { 1317 // FIXME: we use AsmPrinter to emit accelerator sections. 1318 // It might be beneficial to directly emit accelerator data 1319 // to the raw_svector_ostream. 1320 SectionDescriptor &OutSection = 1321 CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes); 1322 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1323 OutSection.OS); 1324 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1325 consumeError(std::move(Err)); 1326 return; 1327 } 1328 1329 // Emit table. 1330 Emitter.emitAppleTypes(AppleTypes); 1331 Emitter.finish(); 1332 1333 // Set start offset ans size for output section. 1334 OutSection.setSizesForSectionCreatedByAsmPrinter(); 1335 } 1336 } 1337 1338 void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) { 1339 std::unique_ptr<DWARF5AccelTable> DebugNames; 1340 1341 DebugNamesUnitsOffsets CompUnits; 1342 CompUnitIDToIdx CUidToIdx; 1343 1344 unsigned Id = 0; 1345 1346 forEachCompileAndTypeUnit([&](DwarfUnit *CU) { 1347 bool HasRecords = false; 1348 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 1349 if (DebugNames == nullptr) 1350 DebugNames = std::make_unique<DWARF5AccelTable>(); 1351 1352 HasRecords = true; 1353 switch (Info.Type) { 1354 case DwarfUnit::AccelType::Name: 1355 case DwarfUnit::AccelType::Namespace: 1356 case DwarfUnit::AccelType::Type: { 1357 DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String), 1358 Info.OutOffset, std::nullopt /*ParentDIEOffset*/, 1359 Info.Tag, CU->getUniqueID(), 1360 CU->getTag() == dwarf::DW_TAG_type_unit); 1361 } break; 1362 1363 default: 1364 break; // Nothing to do. 1365 }; 1366 }); 1367 1368 if (HasRecords) { 1369 CompUnits.push_back( 1370 CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo) 1371 .StartOffset); 1372 CUidToIdx[CU->getUniqueID()] = Id++; 1373 } 1374 }); 1375 1376 if (DebugNames != nullptr) { 1377 // FIXME: we use AsmPrinter to emit accelerator sections. 1378 // It might be beneficial to directly emit accelerator data 1379 // to the raw_svector_ostream. 1380 SectionDescriptor &OutSection = 1381 CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames); 1382 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1383 OutSection.OS); 1384 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1385 consumeError(std::move(Err)); 1386 return; 1387 } 1388 1389 // Emit table. 1390 Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx); 1391 Emitter.finish(); 1392 1393 // Set start offset ans size for output section. 1394 OutSection.setSizesForSectionCreatedByAsmPrinter(); 1395 } 1396 } 1397 1398 void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() { 1399 GlobalData.getStringPool().clear(); 1400 DebugStrStrings.clear(); 1401 DebugLineStrStrings.clear(); 1402 } 1403 1404 void DWARFLinkerImpl::writeCompileUnitsToTheOutput() { 1405 // Enumerate all sections and store them into the final emitter. 1406 forEachObjectSectionsSet([&](OutputSections &Sections) { 1407 Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) { 1408 // Emit section content. 1409 SectionHandler(OutSection); 1410 }); 1411 }); 1412 } 1413 1414 void DWARFLinkerImpl::writeCommonSectionsToTheOutput() { 1415 CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) { 1416 SectionHandler(OutSection); 1417 }); 1418 } 1419