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