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