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