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