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