LLVM 23.0.0git
DWARFLinkerImpl.cpp
Go to the documentation of this file.
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"
16
17using namespace llvm;
18using namespace dwarf_linker;
19using namespace dwarf_linker::parallel;
20
28
30 DWARFFile &File, uint64_t ObjFileIdx,
32 std::atomic<size_t> &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
52
56
61
63 CompileUnitHandlerTy OnCUDieLoaded) {
64 ObjectContexts.emplace_back(std::make_unique<LinkContext>(
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();
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
87 ObjectContexts.reserve(ObjFilesNum);
88}
89
91 // UniqueUnitID is initialized by the constructor and must not be reset
92 // here. addObjectFile() may have already handed out IDs to clang module
93 // CUs loaded from .pcm files, and the IDs handed out below must stay
94 // disjoint from those.
95
97 return Err;
98
99 dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
102
103 if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
104 GlobalData.getTargetTriple()) {
105 GlobalEndianness = (*CurTriple).get().isLittleEndian()
108 }
109 std::optional<uint16_t> Language;
110
111 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
112 if (Context->InputDWARFFile.Dwarf == nullptr) {
113 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
114 continue;
115 }
116
117 if (GlobalData.getOptions().Verbose) {
118 outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
119 << "\n";
120
121 for (const std::unique_ptr<DWARFUnit> &OrigCU :
122 Context->InputDWARFFile.Dwarf->compile_units()) {
123 outs() << "Input compilation unit:";
124 DIDumpOptions DumpOpts;
125 DumpOpts.ChildRecurseDepth = 0;
126 DumpOpts.Verbose = GlobalData.getOptions().Verbose;
127 OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
128 }
129 }
130
131 // Verify input DWARF if requested.
132 if (GlobalData.getOptions().VerifyInputDWARF)
133 verifyInput(Context->InputDWARFFile);
134
135 if (!GlobalData.getTargetTriple())
136 GlobalEndianness = Context->getEndianness();
137 GlobalFormat.AddrSize =
138 std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
139
140 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
141
142 // FIXME: move creation of CompileUnits into the addObjectFile.
143 // This would allow to not scan for context Language and Modules state
144 // twice. And then following handling might be removed.
145 for (const std::unique_ptr<DWARFUnit> &OrigCU :
146 Context->InputDWARFFile.Dwarf->compile_units()) {
147 DWARFDie UnitDie = OrigCU->getUnitDIE();
148
149 if (!Language) {
150 if (std::optional<DWARFFormValue> Val =
151 UnitDie.find(dwarf::DW_AT_language)) {
152 uint16_t LangVal = dwarf::toUnsigned(Val, 0);
153 if (isODRLanguage(LangVal))
154 Language = LangVal;
155 }
156 }
157 }
158 }
159
160 if (GlobalFormat.AddrSize == 0) {
161 if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
162 GlobalData.getTargetTriple())
163 GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
164 else
165 GlobalFormat.AddrSize = 8;
166 }
167
168 CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
169
170 if (!GlobalData.Options.NoODR && Language.has_value()) {
172 TGroup.spawn([&]() {
173 ArtificialTypeUnit = std::make_unique<TypeUnit>(
174 GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);
175 });
176 }
177
178 // Set parallel options.
179 if (GlobalData.getOptions().Threads == 0)
181 else
183 hardware_concurrency(GlobalData.getOptions().Threads);
184
185 // Link object files.
186 if (GlobalData.getOptions().Threads == 1) {
187 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
188 // Link object file.
189 if (Error Err = Context->link(ArtificialTypeUnit.get()))
190 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
191 if (Error Err = Context->unloadInput())
192 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
193 }
194 } else {
196 for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
197 Pool.async([&]() {
198 // Link object file.
199 if (Error Err = Context->link(ArtificialTypeUnit.get()))
200 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
201 if (Error Err = Context->unloadInput())
202 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
203 });
204
205 Pool.wait();
206 }
207
208 // Merge staged parseable Swift interface entries into the shared map. Done
209 // serially so that the final map contents and any conflict warnings are
210 // deterministic.
211 if (DWARFLinkerBase::SwiftInterfacesMapTy *SwiftInterfaces =
212 GlobalData.Options.ParseableSwiftInterfaces) {
213 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
214 for (LinkContext::RefModuleUnit &ModuleUnit :
215 Context->ModulesCompileUnits)
216 ModuleUnit.Unit->mergeSwiftInterfaces(*SwiftInterfaces);
217 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
218 CU->mergeSwiftInterfaces(*SwiftInterfaces);
219 }
220 }
221
222 // Build the linker-wide CIE registry, then emit each context's
223 // .debug_frame in parallel. See CIERegistry for the ownership rules.
224 if (!GlobalData.getOptions().UpdateIndexTablesOnly) {
226 for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
227 if (Context->FrameScan)
228 Context->registerCIEs(CIEs);
229
231 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
232 if (!Context->FrameScan)
233 continue;
234 TGroup.spawn([&]() {
235 if (Error Err = Context->emitDebugFrame(CIEs))
236 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
237 });
238 }
239 }
240
241 if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()
242 .getRoot()
243 ->getValue()
244 .load()
245 ->Children.empty()) {
246 if (GlobalData.getTargetTriple().has_value())
247 if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(
248 (*GlobalData.getTargetTriple()).get()))
249 return Err;
250 }
251
252 // At this stage each compile units are cloned to their own set of debug
253 // sections. Now, update patches, assign offsets and assemble final file
254 // glueing debug tables from each compile unit.
256
257 return Error::success();
258}
259
261 assert(File.Dwarf);
262
263 std::string Buffer;
264 raw_string_ostream OS(Buffer);
265 DIDumpOptions DumpOpts;
266 if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
267 if (GlobalData.getOptions().InputVerificationHandler)
268 GlobalData.getOptions().InputVerificationHandler(File, OS.str());
269 }
270}
271
273 if (GlobalData.getOptions().TargetDWARFVersion == 0)
274 return createStringError(std::errc::invalid_argument,
275 "target DWARF version is not set");
276
277 if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
278 GlobalData.Options.Threads = 1;
279 GlobalData.warn(
280 "set number of threads to 1 to make --verbose to work properly.", "");
281 }
282
283 // Do not do types deduplication in case --update.
284 if (GlobalData.getOptions().UpdateIndexTablesOnly &&
285 !GlobalData.Options.NoODR)
286 GlobalData.Options.NoODR = true;
287
288 return Error::success();
289}
290
291/// Resolve the relative path to a build artifact referenced by DWARF by
292/// applying DW_AT_comp_dir.
294 sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
295}
296
297static uint64_t getDwoId(const DWARFDie &CUDie) {
298 auto DwoId = dwarf::toUnsigned(
299 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
300 if (DwoId)
301 return *DwoId;
302 return 0;
303}
304
305static std::string
307 const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
308 if (ObjectPrefixMap.empty())
309 return Path.str();
310
311 SmallString<256> p = Path;
312 for (const auto &Entry : ObjectPrefixMap)
313 if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
314 break;
315 return p.str().str();
316}
317
318static std::string getPCMFile(const DWARFDie &CUDie,
319 DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
320 std::string PCMFile = dwarf::toString(
321 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
322
323 if (PCMFile.empty())
324 return PCMFile;
325
326 if (ObjectPrefixMap)
327 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
328
329 return PCMFile;
330}
331
333 const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
334 if (PCMFile.empty())
335 return std::make_pair(false, false);
336
337 // Clang module DWARF skeleton CUs abuse this for the path to the module.
338 uint64_t DwoId = getDwoId(CUDie);
339
340 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
341 if (Name.empty()) {
342 if (!Quiet)
343 GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
344 InputDWARFFile.FileName);
345 return std::make_pair(true, true);
346 }
347
348 if (!Quiet && GlobalData.getOptions().Verbose) {
349 outs().indent(Indent);
350 outs() << "Found clang module reference " << PCMFile;
351 }
352
353 auto Cached = ClangModules.find(PCMFile);
354 if (Cached != ClangModules.end()) {
355 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
356 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
357 // ASTFileSignatures will change randomly when a module is rebuilt.
358 if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
359 GlobalData.warn(
360 Twine("hash mismatch: this object file was built against a "
361 "different version of the module ") +
362 PCMFile + ".",
363 InputDWARFFile.FileName);
364 if (!Quiet && GlobalData.getOptions().Verbose)
365 outs() << " [cached].\n";
366 return std::make_pair(true, true);
367 }
368
369 return std::make_pair(true, false);
370}
371
372/// If this compile unit is really a skeleton CU that points to a
373/// clang module, register it in ClangModules and return true.
374///
375/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
376/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
377/// hash.
379 const DWARFDie &CUDie, ObjFileLoaderTy Loader,
380 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
381 std::string PCMFile =
382 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
383 std::pair<bool, bool> IsClangModuleRef =
384 isClangModuleRef(CUDie, PCMFile, Indent, false);
385
386 if (!IsClangModuleRef.first)
387 return false;
388
389 if (IsClangModuleRef.second)
390 return true;
391
392 if (GlobalData.getOptions().Verbose)
393 outs() << " ...\n";
394
395 // Cyclic dependencies are disallowed by Clang, but we still
396 // shouldn't run into an infinite loop, so mark it as processed now.
397 ClangModules.insert({PCMFile, getDwoId(CUDie)});
398
399 if (Error E =
400 loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
401 consumeError(std::move(E));
402 return false;
403 }
404 return true;
405}
406
408 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
409 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
410
411 uint64_t DwoId = getDwoId(CUDie);
412 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
413
414 /// Using a SmallString<0> because loadClangModule() is recursive.
415 SmallString<0> Path(GlobalData.getOptions().PrependPath);
416 if (sys::path::is_relative(PCMFile))
417 resolveRelativeObjectPath(Path, CUDie);
418 sys::path::append(Path, PCMFile);
419 // Don't use the cached binary holder because we have no thread-safety
420 // guarantee and the lifetime is limited.
421
422 if (Loader == nullptr) {
423 GlobalData.error("cann't load clang module: loader is not specified.",
424 InputDWARFFile.FileName);
425 return Error::success();
426 }
427
428 auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
429 if (!ErrOrObj)
430 return Error::success();
431
432 std::unique_ptr<CompileUnit> Unit;
433 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
434 OnCUDieLoaded(*CU);
435 // Recursively get all modules imported by this one.
436 auto ChildCUDie = CU->getUnitDIE();
437 if (!ChildCUDie)
438 continue;
439 if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
440 if (Unit) {
441 std::string Err =
442 (PCMFile +
443 ": Clang modules are expected to have exactly 1 compile unit.\n");
444 GlobalData.error(Err, InputDWARFFile.FileName);
446 }
447 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
448 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
449 // ASTFileSignatures will change randomly when a module is rebuilt.
450 uint64_t PCMDwoId = getDwoId(ChildCUDie);
451 if (PCMDwoId != DwoId) {
452 if (GlobalData.getOptions().Verbose)
453 GlobalData.warn(
454 Twine("hash mismatch: this object file was built against a "
455 "different version of the module ") +
456 PCMFile + ".",
457 InputDWARFFile.FileName);
458 // Update the cache entry with the DwoId of the module loaded from disk.
459 ClangModules[PCMFile] = PCMDwoId;
460 }
461
462 // Empty modules units should not be cloned.
463 if (!ChildCUDie.hasChildren())
464 continue;
465
466 // Add this module.
467 Unit = std::make_unique<CompileUnit>(
468 GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
469 getUnitForOffset, CU->getFormParams(), getEndianness());
470 }
471 }
472
473 if (Unit) {
474 ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
475 // Preload line table, as it can't be loaded asynchronously.
476 ModulesCompileUnits.back().Unit->loadLineTable();
477 }
478
479 return Error::success();
480}
481
484 if (!InputDWARFFile.Dwarf)
485 return Error::success();
486
487 // Preload macro tables, as they can't be loaded asynchronously.
488 InputDWARFFile.Dwarf->getDebugMacinfo();
489 InputDWARFFile.Dwarf->getDebugMacro();
490
491 // Assign deterministic priorities to module CUs for type DIE allocation.
492 uint64_t LocalCUIdx = 0;
493 for (auto &Mod : ModulesCompileUnits) {
494 if (Error E = Mod.Unit->setPriority(ObjectFileIdx, LocalCUIdx++))
495 return E;
496 }
497
498 // Link modules compile units first.
501 });
502
503 // Check for live relocations. If there is no any live relocation then we
504 // can skip entire object file.
505 if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
506 !InputDWARFFile.Addresses->hasValidRelocs()) {
507 if (GlobalData.getOptions().Verbose)
508 outs() << "No valid relocations found. Skipping.\n";
509 return Error::success();
510 }
511
513
514 // Create CompileUnit structures to keep information about source
515 // DWARFUnit`s, load line tables.
516 for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
517 // Load only unit DIE at this stage.
518 auto CUDie = OrigCU->getUnitDIE();
519 std::string PCMFile =
520 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
521
522 // The !isClangModuleRef condition effectively skips over fully resolved
523 // skeleton units.
524 if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
525 !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
526 CompileUnits.emplace_back(std::make_unique<CompileUnit>(
527 GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
528 getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
529 if (llvm::Error E =
530 CompileUnits.back()->setPriority(ObjectFileIdx, LocalCUIdx++))
531 return E;
532
533 // Preload line table, as it can't be loaded asynchronously.
534 CompileUnits.back()->loadLineTable();
535 }
536 };
537
539
540 // Link self-sufficient compile units and discover inter-connected compile
541 // units.
542 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
544 });
545
546 // Link all inter-connected units.
549
550 if (Error Err = finiteLoop([&]() -> Expected<bool> {
552
553 // Load inter-connected units.
554 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
555 if (CU->isInterconnectedCU()) {
556 CU->maybeResetToLoadedStage();
559 }
560 });
561
562 // Do liveness analysis for inter-connected units.
563 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
566 });
567
568 return HasNewInterconnectedCUs.load();
569 }))
570 return Err;
571
572 // Update dependencies.
573 if (Error Err = finiteLoop([&]() -> Expected<bool> {
575 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
579 });
580 return HasNewGlobalDependency.load();
581 }))
582 return Err;
583 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
584 if (CU->isInterconnectedCU() &&
587 });
588
589 // Assign type names.
590 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
593 });
594
595 // Clone inter-connected units.
596 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
599 });
600
601 // Update patches for inter-connected units.
602 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
605 });
606
607 // Release data.
608 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
611 });
612 }
613
614 if (GlobalData.getOptions().UpdateIndexTablesOnly) {
615 // Emit Invariant sections.
616
617 if (Error Err = emitInvariantSections())
618 return Err;
619 }
620
621 return Error::success();
622}
623
626 enum CompileUnit::Stage DoUntilStage) {
627 if (InterCUProcessingStarted != CU.isInterconnectedCU())
628 return;
629
630 if (Error Err = finiteLoop([&]() -> Expected<bool> {
631 if (CU.getStage() >= DoUntilStage)
632 return false;
633
634 switch (CU.getStage()) {
636 // Load input compilation unit DIEs.
637 // Analyze properties of DIEs.
638 if (!CU.loadInputDIEs()) {
639 // We do not need to do liveness analysis for invalid compilation
640 // unit.
642 } else {
643 CU.analyzeDWARFStructure();
644
645 // The registerModuleReference() condition effectively skips
646 // over fully resolved skeleton units. This second pass of
647 // registerModuleReferences doesn't do any new work, but it
648 // will collect top-level errors, which are suppressed. Module
649 // warnings were already displayed in the first iteration.
651 CU.getOrigUnit().getUnitDIE(), nullptr,
652 [](const DWARFUnit &) {}, 0))
654 else
656 }
657 } break;
658
660 // Mark all the DIEs that need to be present in the generated output.
661 // If ODR requested, build type names.
662 if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
665 "Flag indicating new inter-connections is not set");
666 return false;
667 }
668
670 } break;
671
674 if (CU.updateDependenciesCompleteness())
676 return false;
677 } else {
678 if (Error Err = finiteLoop([&]() -> Expected<bool> {
679 return CU.updateDependenciesCompleteness();
680 }))
681 return std::move(Err);
682
684 }
685 } break;
686
688#ifndef NDEBUG
689 CU.verifyDependencies();
690#endif
691
692 if (ArtificialTypeUnit) {
693 if (Error Err =
694 CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
695 return std::move(Err);
696 }
698 break;
699
701 // Clone input compile unit.
702 if (CU.isClangModule() ||
703 GlobalData.getOptions().UpdateIndexTablesOnly ||
704 CU.getContaingFile().Addresses->hasValidRelocs()) {
705 if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
707 return std::move(Err);
708 }
709
711 break;
712
714 // Update DIEs referencies.
715 CU.updateDieRefPatchesWithClonedOffsets();
717 break;
718
720 // Cleanup resources.
721 CU.cleanupDataAfterClonning();
723 break;
724
726 assert(false);
727 break;
728
730 // Nothing to do.
731 break;
732 }
733
734 return true;
735 })) {
736 CU.error(std::move(Err));
737 CU.cleanupDataAfterClonning();
739 }
740}
741
743 if (!GlobalData.getTargetTriple().has_value())
744 return Error::success();
745
747 << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
749 << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
751 << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
753 << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
755 << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
757 << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
759 << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
760
761 return Error::success();
762}
763
765 if (GlobalData.getOptions().UpdateIndexTablesOnly)
766 return Error::success();
767 if (!GlobalData.getTargetTriple().has_value())
768 return Error::success();
769
770 if (InputDWARFFile.Dwarf == nullptr)
771 return Error::success();
772 if (CompileUnits.empty())
773 return Error::success();
774
775 const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
776
777 StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
778 if (OrigFrameData.empty())
779 return Error::success();
780
781 auto Scan = std::make_unique<FrameScanResult>();
782 Scan->FrameData = OrigFrameData;
783 Scan->AddressSize = InputDWARFObj.getAddressSize();
784
785 RangesTy AllUnitsRanges;
786 for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
787 for (auto CurRange : Unit->getFunctionRanges())
788 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
789 }
790
791 StringRef FrameBytes = Scan->FrameData;
792 DataExtractor Data(FrameBytes, InputDWARFObj.isLittleEndian(), 0);
793 uint64_t InputOffset = 0;
794 const unsigned SrcAddrSize = Scan->AddressSize;
795 // Width of the CIE_pointer field at the start of every FDE (and of the
796 // CIE_id sentinel at the start of every CIE) in DWARF32 .debug_frame.
797 constexpr unsigned CIEPointerSize = 4;
798
799 // CIEs defined in this input, keyed by their input offsets.
801 DenseSet<uint64_t> AddedCIEs;
802
803 while (Data.isValidOffset(InputOffset)) {
804 uint64_t EntryOffset = InputOffset;
805 uint32_t InitialLength = Data.getU32(&InputOffset);
806 if (InitialLength == 0xFFFFFFFF)
807 return createFileError(InputDWARFFile.FileName,
808 createStringError(std::errc::invalid_argument,
809 "Dwarf64 bits not supported"));
810
811 // Reject lengths that don't fit in the input section. substr() saturates
812 // silently, which would otherwise let a malformed length poison the
813 // CIE bytes used as the registry key.
814 if (InitialLength > FrameBytes.size() - InputOffset)
815 return createFileError(
816 InputDWARFFile.FileName,
817 createStringError(std::errc::invalid_argument,
818 "Truncated .debug_frame entry."));
819
820 uint32_t CIEId = Data.getU32(&InputOffset);
821 if (CIEId == 0xFFFFFFFF) {
822 // This is a CIE, store it.
823 StringRef CIEData = FrameBytes.substr(EntryOffset, InitialLength + 4);
824 LocalCIEs[EntryOffset] = CIEData;
825 // The -4 is to account for the CIEId we just read.
826 InputOffset += InitialLength - 4;
827 continue;
828 }
829
830 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
831
832 // Some compilers seem to emit frame info that doesn't start at
833 // the function entry point, thus we can't just lookup the address
834 // in the debug map. Use the AddressInfo's range map to see if the FDE
835 // describes something that we can relocate.
836 std::optional<AddressRangeValuePair> Range =
837 AllUnitsRanges.getRangeThatContains(Loc);
838 if (!Range) {
839 // The +4 is to account for the size of the InitialLength field itself.
840 InputOffset = EntryOffset + InitialLength + 4;
841 continue;
842 }
843
844 // This is an FDE, and we have a mapping.
845 StringRef CIEData = LocalCIEs.lookup(CIEId);
846 if (CIEData.empty())
847 return createFileError(
848 InputDWARFFile.FileName,
849 createStringError(std::errc::invalid_argument,
850 "Inconsistent debug_frame content. Dropping."));
851
852 // Reject FDEs whose length doesn't even cover the CIE_pointer and
853 // initial_location fields; otherwise the unsigned subtraction below
854 // would wrap and substr() would saturate to a giant garbage blob.
855 if (InitialLength < CIEPointerSize + SrcAddrSize)
856 return createFileError(InputDWARFFile.FileName,
857 createStringError(std::errc::invalid_argument,
858 "Truncated .debug_frame FDE."));
859
860 // Promote each CIE on first reference; CIEs no FDE references are
861 // dropped from the output.
862 if (AddedCIEs.insert(CIEId).second)
863 Scan->CIEs.push_back(CIEData);
864
865 unsigned FDERemainingBytes = InitialLength - (CIEPointerSize + SrcAddrSize);
866 Scan->FDEs.push_back({CIEData, Loc + Range->Value,
867 FrameBytes.substr(InputOffset, FDERemainingBytes)});
868 InputOffset += FDERemainingBytes;
869 }
870
871 FrameScan = std::move(Scan);
872 return Error::success();
873}
874
876 assert(FrameScan && "registerCIEs called without FrameScan");
877 SectionDescriptor &OutSection =
879
880 uint32_t NextLocalOffset = 0;
881 for (StringRef CIEBytes : FrameScan->CIEs) {
882 auto [It, Inserted] =
883 CIEs.try_emplace(CIEBytes, CIELocation{&OutSection, NextLocalOffset});
884 if (Inserted) {
885 FrameScan->OwnedCIEs.push_back(CIEBytes);
886 NextLocalOffset += static_cast<uint32_t>(CIEBytes.size());
887 }
888 }
889}
890
892 assert(FrameScan && "emitDebugFrame called without FrameScan");
893 SectionDescriptor &OutSection =
895
896 // Emit owned CIEs at the offsets registerCIEs reserved for them.
897 for (StringRef CIEBytes : FrameScan->OwnedCIEs)
898 OutSection.OS << CIEBytes;
899
900 const dwarf::FormParams FP = OutSection.getFormParams();
901 const unsigned SrcAddrSize = FrameScan->AddressSize;
902
903 for (const FrameScanResult::FDE &FDE : FrameScan->FDEs) {
904 auto It = CIEs.find(FDE.CIEBytes);
905 assert(It != CIEs.end() && "CIE missing from registry");
906 SectionDescriptor *CIEOwnerSection = It->second.OwnerSection;
907 const uint32_t CIELocalOffset = It->second.LocalOffset;
908
909 const uint64_t FDEPos = OutSection.OS.tell();
910 // Note: this guards against a single context's section exceeding the
911 // DWARF32 limit. It does NOT catch the post-glue overflow that would
912 // happen if the concatenated .debug_frame across all contexts pushes
913 // past 4 GB; that case slips through silently because StartOffset is
914 // not yet assigned. A post-glue check would belong in the patch
915 // resolver in OutputSections.cpp.
916 if (FDEPos > FP.getDwarfMaxOffset())
917 return createFileError(
918 InputDWARFFile.FileName,
919 createStringError(".debug_frame section offset "
920 "0x" +
921 Twine::utohexstr(FDEPos) + " exceeds the " +
922 dwarf::FormatString(FP.Format) + " limit"));
923
924 // CIE_pointer field follows the 4-byte initial_length.
925 OutSection.notePatch(DebugOffsetPatch{FDEPos + 4, CIEOwnerSection, true});
926
927 emitFDE(CIELocalOffset, SrcAddrSize, FDE.Address, FDE.Instructions,
928 OutSection);
929 }
930
931 FrameScan.reset();
932 return Error::success();
933}
934
936 // Scan the input's .debug_frame now, while the DWARFContext is still
937 // loaded, so the later (post-pool) emission pass can run against the
938 // scan result alone.
939 Error ScanErr = scanFrameData();
940 InputDWARFFile.unload();
941 return ScanErr;
942}
943
944/// Emit a FDE into the debug_frame section. \p FDEBytes
945/// contains the FDE data without the length, CIE offset and address
946/// which will be replaced with the parameter values.
948 uint32_t AddrSize, uint64_t Address,
949 StringRef FDEBytes,
950 SectionDescriptor &Section) {
951 Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
952 Section.emitIntVal(CIEOffset, 4);
953 Section.emitIntVal(Address, AddrSize);
954 Section.OS.write(FDEBytes.data(), FDEBytes.size());
955}
956
958 if (!GlobalData.getTargetTriple().has_value())
959 return;
961
962 // Go through all object files, all compile units and assign
963 // offsets to them.
965
966 // Patch size/offsets fields according to the assigned CU offsets.
968
969 // Emit common sections and write debug tables from all object files/compile
970 // units into the resulting file.
972
973 if (ArtificialTypeUnit != nullptr)
974 ArtificialTypeUnit.reset();
975
976 // Write common debug sections into the resulting file.
978
979 // Cleanup data.
981
982 if (GlobalData.getOptions().Statistics)
984}
985
987
988 // For each object file map how many bytes were emitted.
989 StringMap<DebugInfoSize> SizeByObject;
990
991 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
992 uint64_t AllDebugInfoSectionsSize = 0;
993
994 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
995 if (std::optional<SectionDescriptor *> DebugInfo =
996 CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
997 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
998
999 auto &Size = SizeByObject[Context->InputDWARFFile.FileName];
1000 Size.Input = Context->OriginalDebugInfoSize;
1001 Size.Output = AllDebugInfoSectionsSize;
1002 }
1003
1004 // Create a vector sorted in descending order by output size.
1005 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
1006 for (auto &E : SizeByObject)
1007 Sorted.emplace_back(E.first(), E.second);
1008 llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
1009 return LHS.second.Output > RHS.second.Output;
1010 });
1011
1012 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
1013 const float Difference = Output - Input;
1014 const float Sum = Input + Output;
1015 if (Sum == 0)
1016 return 0;
1017 return (Difference / (Sum / 2));
1018 };
1019
1020 int64_t InputTotal = 0;
1021 int64_t OutputTotal = 0;
1022 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
1023
1024 // Print header.
1025 outs() << ".debug_info section size (in bytes)\n";
1026 outs() << "----------------------------------------------------------------"
1027 "---------------\n";
1028 outs() << "Filename Object "
1029 " dSYM Change\n";
1030 outs() << "----------------------------------------------------------------"
1031 "---------------\n";
1032
1033 // Print body.
1034 for (auto &E : Sorted) {
1035 InputTotal += E.second.Input;
1036 OutputTotal += E.second.Output;
1037 llvm::outs() << formatv(
1038 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
1039 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
1040 }
1041 // Print total and footer.
1042 outs() << "----------------------------------------------------------------"
1043 "---------------\n";
1044 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
1045 ComputePercentange(InputTotal, OutputTotal));
1046 outs() << "----------------------------------------------------------------"
1047 "---------------\n\n";
1048}
1049
1052 TGroup.spawn([&]() { assignOffsetsToStrings(); });
1053 TGroup.spawn([&]() { assignOffsetsToSections(); });
1054}
1055
1057 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
1058 uint64_t CurDebugStrOffset =
1059 1; // start from 1 to take into account zero entry.
1060 size_t CurDebugLineStrIndex = 0;
1061 uint64_t CurDebugLineStrOffset = 0;
1062
1063 // Enumerates all strings, add them into the DwarfStringPoolEntry map,
1064 // assign offset and index to the string if it is not indexed yet.
1066 const StringEntry *String) {
1067 switch (Kind) {
1070 assert(Entry != nullptr);
1071
1072 if (!Entry->isIndexed()) {
1073 Entry->Offset = CurDebugStrOffset;
1074 CurDebugStrOffset += Entry->String.size() + 1;
1075 Entry->Index = CurDebugStrIndex++;
1076 }
1077 } break;
1081 assert(Entry != nullptr);
1082
1083 if (!Entry->isIndexed()) {
1084 Entry->Offset = CurDebugLineStrOffset;
1085 CurDebugLineStrOffset += Entry->String.size() + 1;
1086 Entry->Index = CurDebugLineStrIndex++;
1087 }
1088 } break;
1089 }
1090 });
1091}
1092
1094 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
1095
1096 forEachObjectSectionsSet([&](OutputSections &UnitSections) {
1097 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
1098 });
1099}
1100
1103 StringHandler) {
1104 // To save space we do not create any separate string table.
1105 // We use already allocated string patches and accelerator entries:
1106 // enumerate them in natural order and assign offsets.
1107 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
1108 // sections in the same order as they were assigned offsets.
1110 CU->forEach([&](SectionDescriptor &OutSection) {
1111 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1112 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1113 });
1114
1115 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1116 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1117 });
1118 });
1119
1120 CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
1121 StringHandler(DebugStr, Info.String);
1122 });
1123 });
1124
1125 if (ArtificialTypeUnit != nullptr) {
1126 ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
1127 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1128 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1129 });
1130
1131 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1132 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1133 });
1134
1135 OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
1136 if (Patch.Die == nullptr)
1137 return;
1138
1139 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
1140 if (&TypeEntry->getFinalDie() != Patch.Die)
1141 return;
1142
1143 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1144 });
1145
1146 OutSection.ListDebugTypeLineStrPatch.forEach(
1147 [&](DebugTypeLineStrPatch &Patch) {
1148 if (Patch.Die == nullptr)
1149 return;
1150
1151 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
1152 if (&TypeEntry->getFinalDie() != Patch.Die)
1153 return;
1154
1155 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1156 });
1157 });
1158 }
1159}
1160
1162 function_ref<void(OutputSections &)> SectionsSetHandler) {
1163 // Handle artificial type unit first.
1164 if (ArtificialTypeUnit != nullptr)
1165 SectionsSetHandler(*ArtificialTypeUnit);
1166
1167 // Then all modules(before regular compilation units).
1168 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1169 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1170 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1171 SectionsSetHandler(*ModuleUnit.Unit);
1172
1173 // Finally all compilation units.
1174 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1175 // Handle object file common sections.
1176 SectionsSetHandler(*Context);
1177
1178 // Handle compilation units.
1179 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1180 if (CU->getStage() != CompileUnit::Stage::Skipped)
1181 SectionsSetHandler(*CU);
1182 }
1183}
1184
1186 function_ref<void(DwarfUnit *CU)> UnitHandler) {
1187 if (ArtificialTypeUnit != nullptr)
1188 UnitHandler(ArtificialTypeUnit.get());
1189
1190 // Enumerate module units.
1191 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1192 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1193 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1194 UnitHandler(ModuleUnit.Unit.get());
1195
1196 // Enumerate compile units.
1197 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1198 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1199 if (CU->getStage() != CompileUnit::Stage::Skipped)
1200 UnitHandler(CU.get());
1201}
1202
1204 function_ref<void(CompileUnit *CU)> UnitHandler) {
1205 // Enumerate module units.
1206 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1207 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1208 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1209 UnitHandler(ModuleUnit.Unit.get());
1210
1211 // Enumerate compile units.
1212 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1213 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1214 if (CU->getStage() != CompileUnit::Stage::Skipped)
1215 UnitHandler(CU.get());
1216}
1217
1219 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
1220 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
1221 SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
1222 ArtificialTypeUnit.get());
1223 });
1224 });
1225}
1226
1229
1230 // Create section descriptors ahead if they are not exist at the moment.
1231 // SectionDescriptors container is not thread safe. Thus we should be sure
1232 // that descriptors would not be created in following parallel tasks.
1233
1234 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
1235 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
1236
1237 if (llvm::is_contained(GlobalData.Options.AccelTables,
1239 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
1240 CommonSections.getOrCreateSectionDescriptor(
1242 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
1243 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
1244 }
1245
1246 if (llvm::is_contained(GlobalData.Options.AccelTables,
1248 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
1249
1250 // Emit .debug_str and .debug_line_str sections.
1251 TG.spawn([&]() { emitStringSections(); });
1252
1253 if (llvm::is_contained(GlobalData.Options.AccelTables,
1255 // Emit apple accelerator sections.
1256 TG.spawn([&]() {
1257 emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
1258 });
1259 }
1260
1261 if (llvm::is_contained(GlobalData.Options.AccelTables,
1263 // Emit .debug_names section.
1264 TG.spawn([&]() {
1265 emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
1266 });
1267 }
1268
1269 // Write compile units to the output file.
1270 TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
1271}
1272
1274 uint64_t DebugStrNextOffset = 0;
1275 uint64_t DebugLineStrNextOffset = 0;
1276
1277 // Emit zero length string. Accelerator tables does not work correctly
1278 // if the first string is not zero length string.
1279 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1280 .emitInplaceString("");
1281 DebugStrNextOffset++;
1282
1284 [&](StringDestinationKind Kind, const StringEntry *String) {
1285 switch (Kind) {
1287 DwarfStringPoolEntryWithExtString *StringToEmit =
1288 DebugStrStrings.getExistingEntry(String);
1289 assert(StringToEmit->isIndexed());
1290
1291 // Strings may be repeated. Use accumulated DebugStrNextOffset
1292 // to understand whether corresponding string is already emitted.
1293 // Skip string if its offset less than accumulated offset.
1294 if (StringToEmit->Offset >= DebugStrNextOffset) {
1295 DebugStrNextOffset =
1296 StringToEmit->Offset + StringToEmit->String.size() + 1;
1297 // Emit the string itself.
1298 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1299 .emitInplaceString(StringToEmit->String);
1300 }
1301 } break;
1303 DwarfStringPoolEntryWithExtString *StringToEmit =
1304 DebugLineStrStrings.getExistingEntry(String);
1305 assert(StringToEmit->isIndexed());
1306
1307 // Strings may be repeated. Use accumulated DebugLineStrStrings
1308 // to understand whether corresponding string is already emitted.
1309 // Skip string if its offset less than accumulated offset.
1310 if (StringToEmit->Offset >= DebugLineStrNextOffset) {
1311 DebugLineStrNextOffset =
1312 StringToEmit->Offset + StringToEmit->String.size() + 1;
1313 // Emit the string itself.
1315 .emitInplaceString(StringToEmit->String);
1316 }
1317 } break;
1318 }
1319 });
1320}
1321
1327
1329 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1330 uint64_t OutOffset = Info.OutOffset;
1331 switch (Info.Type) {
1333 llvm_unreachable("Unknown accelerator record");
1334 } break;
1336 AppleNamespaces.addName(
1337 *DebugStrStrings.getExistingEntry(Info.String),
1338 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1339 OutOffset);
1340 } break;
1342 AppleNames.addName(
1343 *DebugStrStrings.getExistingEntry(Info.String),
1344 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1345 OutOffset);
1346 } break;
1348 AppleObjC.addName(
1349 *DebugStrStrings.getExistingEntry(Info.String),
1350 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1351 OutOffset);
1352 } break;
1354 AppleTypes.addName(
1355 *DebugStrStrings.getExistingEntry(Info.String),
1356 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1357 OutOffset,
1358 Info.Tag,
1359 Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1360 : 0,
1361 Info.QualifiedNameHash);
1362 } break;
1363 }
1364 });
1365 });
1366
1367 {
1368 // FIXME: we use AsmPrinter to emit accelerator sections.
1369 // It might be beneficial to directly emit accelerator data
1370 // to the raw_svector_ostream.
1371 SectionDescriptor &OutSection =
1374 OutSection.OS);
1375 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1376 consumeError(std::move(Err));
1377 return;
1378 }
1379
1380 // Emit table.
1381 Emitter.emitAppleNamespaces(AppleNamespaces);
1382 Emitter.finish();
1383
1384 // Set start offset and size for output section.
1386 }
1387
1388 {
1389 // FIXME: we use AsmPrinter to emit accelerator sections.
1390 // It might be beneficial to directly emit accelerator data
1391 // to the raw_svector_ostream.
1392 SectionDescriptor &OutSection =
1393 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
1395 OutSection.OS);
1396 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1397 consumeError(std::move(Err));
1398 return;
1399 }
1400
1401 // Emit table.
1402 Emitter.emitAppleNames(AppleNames);
1403 Emitter.finish();
1404
1405 // Set start offset ans size for output section.
1407 }
1408
1409 {
1410 // FIXME: we use AsmPrinter to emit accelerator sections.
1411 // It might be beneficial to directly emit accelerator data
1412 // to the raw_svector_ostream.
1413 SectionDescriptor &OutSection =
1414 CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
1416 OutSection.OS);
1417 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1418 consumeError(std::move(Err));
1419 return;
1420 }
1421
1422 // Emit table.
1423 Emitter.emitAppleObjc(AppleObjC);
1424 Emitter.finish();
1425
1426 // Set start offset ans size for output section.
1428 }
1429
1430 {
1431 // FIXME: we use AsmPrinter to emit accelerator sections.
1432 // It might be beneficial to directly emit accelerator data
1433 // to the raw_svector_ostream.
1434 SectionDescriptor &OutSection =
1435 CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
1437 OutSection.OS);
1438 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1439 consumeError(std::move(Err));
1440 return;
1441 }
1442
1443 // Emit table.
1444 Emitter.emitAppleTypes(AppleTypes);
1445 Emitter.finish();
1446
1447 // Set start offset ans size for output section.
1449 }
1450}
1451
1453 std::unique_ptr<DWARF5AccelTable> DebugNames;
1454
1455 DebugNamesUnitsOffsets CompUnits;
1456 CompUnitIDToIdx CUidToIdx;
1457
1458 unsigned Id = 0;
1459
1461 bool HasRecords = false;
1462 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1463 if (DebugNames == nullptr)
1464 DebugNames = std::make_unique<DWARF5AccelTable>();
1465
1466 HasRecords = true;
1467 switch (Info.Type) {
1471 DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1472 Info.OutOffset, Info.ParentOffset, Info.Tag,
1473 CU->getUniqueID(),
1474 CU->getTag() == dwarf::DW_TAG_type_unit);
1475 } break;
1476
1477 default:
1478 break; // Nothing to do.
1479 };
1480 });
1481
1482 if (HasRecords) {
1483 CompUnits.push_back(
1484 CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
1485 .StartOffset);
1486 CUidToIdx[CU->getUniqueID()] = Id++;
1487 }
1488 });
1489
1490 if (DebugNames != nullptr) {
1491 // FIXME: we use AsmPrinter to emit accelerator sections.
1492 // It might be beneficial to directly emit accelerator data
1493 // to the raw_svector_ostream.
1494 SectionDescriptor &OutSection =
1495 CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
1497 OutSection.OS);
1498 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1499 consumeError(std::move(Err));
1500 return;
1501 }
1502
1503 // Emit table.
1504 Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
1505 Emitter.finish();
1506
1507 // Set start offset ans size for output section.
1509 }
1510}
1511
1513 GlobalData.getStringPool().clear();
1514 DebugStrStrings.clear();
1515 DebugLineStrStrings.clear();
1516}
1517
1519 // Enumerate all sections and store them into the final emitter.
1521 Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1522 // Emit section content.
1523 SectionHandler(OutSection);
1524 });
1525 });
1526}
1527
1529 CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1530 SectionHandler(OutSection);
1531 });
1532}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
dxil DXContainer Global Emitter
static fatal_error_handler_t ErrorHandler
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
The Input class is used to parse a yaml document into in-memory structs and vectors.
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition AccelTable.h:203
std::optional< T > getRangeThatContains(uint64_t Addr) const
void insert(AddressRange Range, int64_t Value)
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:317
virtual bool isLittleEndian() const =0
virtual const DWARFSection & getFrameSection() const
Definition DWARFObject.h:44
virtual uint8_t getAddressSize() const
Definition DWARFObject.h:35
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:205
Implements a dense probed hash-table based set.
Definition DenseSet.h:279
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
void wait() override
Blocking wait for all the tasks to execute first.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:133
iterator end()
Definition StringMap.h:224
iterator find(StringRef Key)
Definition StringMap.h:237
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition StringMap.h:381
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Definition ThreadPool.h:80
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
This class represents DWARF information for source file and it's address map.
Definition DWARFFile.h:25
std::map< std::string, std::string > ObjectPrefixMapTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandlerTy
std::function< void( const Twine &Warning, StringRef Context, const DWARFDie *DIE)> MessageHandlerTy
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
std::map< std::string, std::string > SwiftInterfacesMapTy
std::function< ErrorOr< DWARFFile & >( StringRef ContainerName, StringRef Path)> ObjFileLoaderTy
Stores all information related to a compile unit, be it in its original instance of the object file o...
Stage
The stages of new compile unit processing.
@ CreatedNotLoaded
Created, linked with input DWARF file.
@ PatchesUpdated
Offsets inside patch records are updated.
@ Cleaned
Resources(Input DWARF, Output DWARF tree) are released.
@ LivenessAnalysisDone
Input DWARF is analysed(DIEs pointing to the real code section arediscovered, type names are assigned...
@ UpdateDependenciesCompleteness
Check if dependencies have incompatible placement.
void forEachObjectSectionsSet(function_ref< void(OutputSections &SectionsSet)> SectionsSetHandler)
Enumerates sections for modules, invariant for object files, compile units.
void emitDWARFv5DebugNamesSection(const Triple &TargetTriple)
Emit .debug_names section.
void writeCompileUnitsToTheOutput()
Enumerate all compile units and put their data into the output stream.
void forEachCompileUnit(function_ref< void(CompileUnit *CU)> UnitHandler)
Enumerates all comple units.
void assignOffsetsToStrings()
Enumerate all compile units and assign offsets to their strings.
void assignOffsets()
Enumerate all compile units and assign offsets to their sections and strings.
Error link() override
Link debug info for added files.
Error validateAndUpdateOptions()
Validate specified options.
void writeCommonSectionsToTheOutput()
Enumerate common sections and put their data into the output stream.
void assignOffsetsToSections()
Enumerate all compile units and assign offsets to their sections.
void printStatistic()
Print statistic for processed Debug Info.
void glueCompileUnitsAndWriteToTheOutput()
Take already linked compile units and glue them into single file.
void emitAppleAcceleratorSections(const Triple &TargetTriple)
Emit apple accelerator sections.
void verifyInput(const DWARFFile &File)
Verify input DWARF file.
void forEachCompileAndTypeUnit(function_ref< void(DwarfUnit *CU)> UnitHandler)
Enumerates all compile and type units.
DWARFLinkerImpl(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler)
void addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader=nullptr, CompileUnitHandlerTy OnCUDieLoaded=[](const DWARFUnit &) {}) override
Add object file to be linked.
void cleanupDataAfterDWARFOutputIsWritten()
Cleanup data(string pools) after output sections are generated.
void forEachOutputString(function_ref< void(StringDestinationKind, const StringEntry *)> StringHandler)
Enumerates all strings.
void emitCommonSectionsAndWriteCompileUnitsToTheOutput()
Emit debug sections common for all input files.
void patchOffsetsAndSizes()
Enumerates all patches and update them with the correct values.
This class emits DWARF data to the output stream.
Base class for all Dwarf units(Compile unit/Type table unit).
This class keeps data and services common for the whole linking process.
This class keeps contents and offsets to the debug sections.
void applyPatches(SectionDescriptor &Section, StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, TypeUnit *TypeUnitPtr)
Enumerate all sections, for each section apply all section patches.
OutputSections(LinkingGlobalData &GlobalData)
void forEach(function_ref< void(SectionDescriptor &)> Handler)
Enumerate all sections and call Handler for each.
llvm::endianness getEndianness() const
Endiannes for the sections.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
void assignSectionsOffsetAndAccumulateSize(std::array< uint64_t, SectionKindsNum > &SectionSizesAccumulator)
Enumerate all sections, for each section set current offset (kept by SectionSizesAccumulator),...
const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
Keeps cloned data for the type DIE.
Definition TypePool.h:31
Type Unit is used to represent an artificial compilation unit which keeps all type information.
An efficient, type-erasing, non-owning reference to a callable.
LLVM_ABI void spawn(std::function< void()> f)
Definition Parallel.cpp:257
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
std::atomic< size_t > UniqueUnitID
Unique ID for compile unit.
uint64_t OverallNumberOfCU
Overall compile units number.
SmallVector< std::unique_ptr< LinkContext > > ObjectContexts
Keeps all linking contexts.
StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings
DwarfStringPoolEntries for .debug_line_str section.
SectionHandlerTy SectionHandler
Hanler for output sections.
std::unique_ptr< TypeUnit > ArtificialTypeUnit
Type unit.
StringEntryToDwarfStringPoolEntryMap DebugStrStrings
DwarfStringPoolEntries for .debug_str section.
OutputSections CommonSections
Common sections.
StringMap< uint64_t > ClangModules
Mapping the PCM filename to the DwoId.
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1023
void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override
Set estimated objects files amount, for preliminary data allocation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isODRLanguage(uint16_t Language)
std::vector< std::variant< MCSymbol *, uint64_t > > DebugNamesUnitsOffsets
DenseMap< unsigned, unsigned > CompUnitIDToIdx
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:28
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
Definition StringPool.h:23
Error finiteLoop(function_ref< Expected< bool >()> Iteration, size_t MaxCounter=100000)
This function calls Iteration() until it returns false.
Definition Utils.h:44
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
@ DWARF32
Definition Dwarf.h:93
@ DW_FLAG_type_implementation
Definition Dwarf.h:953
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
LLVM_ABI ThreadPoolStrategy strategy
Definition Parallel.cpp:27
LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition Path.cpp:706
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:584
LLVM_ABI bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
Definition Path.cpp:519
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
Definition Threading.h:190
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition Error.h:1415
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
static std::string remapPath(StringRef Path, const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)
Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.
static std::string getPCMFile(const DWARFDie &CUDie, const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1635
ThreadPoolStrategy optimal_concurrency(unsigned TaskCount=0)
Returns an optimal thread strategy to execute specified amount of tasks.
Definition Threading.h:211
static uint64_t getDwoId(const DWARFDie &CUDie)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ Other
Any other memory.
Definition ModRef.h:68
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
SingleThreadExecutor DefaultThreadPool
Definition ThreadPool.h:262
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1916
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn)
Definition Parallel.h:229
endianness
Definition bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:874
Container for dump options that control which debug information will be dumped.
Definition DIContext.h:196
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
Definition DIContext.h:228
unsigned ChildRecurseDepth
Definition DIContext.h:198
DwarfStringPoolEntry with string keeping externally.
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
Definition Dwarf.h:1114
Section + local offset of a .debug_frame CIE that has been (or will be) emitted by some LinkContext.
Keep information for referenced clang module: already loaded DWARF info of the clang module and a Com...
RefModuleUnit(DWARFFile &File, std::unique_ptr< CompileUnit > Unit)
uint64_t getInputDebugInfoSize() const
Computes the total size of the debug info.
bool InterCUProcessingStarted
Flag indicating that all inter-connected units are loaded and the dwarf linking process for these uni...
bool registerModuleReference(const DWARFDie &CUDie, ObjFileLoaderTy Loader, CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent=0)
If this compile unit is really a skeleton CU that points to a clang module, register it in ClangModul...
Error loadClangModule(ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile, CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent=0)
Recursively add the debug info in this clang module .pcm file (and all the modules imported by it in ...
Error scanFrameData()
Parse this context's input .debug_frame into FrameScan.
uint64_t OriginalDebugInfoSize
Size of Debug info before optimizing.
std::pair< bool, bool > isClangModuleRef(const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet)
Check whether specified CUDie is a Clang module reference.
void addModulesCompileUnit(RefModuleUnit &&Unit)
Add Compile Unit corresponding to the module.
void emitFDE(uint32_t CIEOffset, uint32_t AddrSize, uint64_t Address, StringRef FDEBytes, SectionDescriptor &Section)
Emit FDE record.
UnitListTy CompileUnits
Set of Compilation Units(may be accessed asynchroniously for reading).
void linkSingleCompileUnit(CompileUnit &CU, TypeUnit *ArtificialTypeUnit, enum CompileUnit::Stage DoUntilStage=CompileUnit::Stage::Cleaned)
Link specified compile unit until specified stage.
void registerCIEs(CIERegistry &CIEs)
Register this context's CIEs with the linker-wide registry.
LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File, uint64_t ObjFileIdx, StringMap< uint64_t > &ClangModules, std::atomic< size_t > &UniqueUnitID)
std::atomic< bool > HasNewInterconnectedCUs
Flag indicating that new inter-connected compilation units were discovered.
Error emitDebugFrame(const CIERegistry &CIEs)
Emit this context's .debug_frame section.
std::atomic< size_t > & UniqueUnitID
Counter for compile units ID.
Error link(TypeUnit *ArtificialTypeUnit)
Link compile units for this context.
StringMap< CIELocation > CIERegistry
Linker-wide registry for .debug_frame CIEs.
Error unloadInput()
Unload the input DWARFContext after scanning the input .debug_frame into FrameScan.
uint64_t ObjectFileIdx
Index of this object file in the link order (used for deterministic type DIE allocation).
std::function< CompileUnit *(uint64_t)> getUnitForOffset
ModuleUnitListTy ModulesCompileUnits
Set of Compile Units for modules.
This structure is used to update strings offsets into .debug_line_str.
This structure is used to update strings offsets into .debug_str.
This structure keeps fields which would be used for creating accelerator table.
dwarf::FormParams getFormParams() const
Returns FormParams used by section.
This structure is used to keep data of the concrete section.
raw_svector_ostream OS
Stream which stores data to the Contents.
void setSizesForSectionCreatedByAsmPrinter()
Some sections are emitted using AsmPrinter.