LLVM 23.0.0git
DWARFLinkerImpl.cpp
Go to the documentation of this file.
1//=== DWARFLinkerImpl.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DWARFLinkerImpl.h"
10#include "DependencyTracker.h"
16
17using namespace llvm;
18using namespace dwarf_linker;
19using namespace dwarf_linker::parallel;
20
28
30 DWARFFile &File, uint64_t ObjFileIdx,
32 std::atomic<size_t> &UniqueUnitID)
36
37 if (File.Dwarf) {
38 if (!File.Dwarf->compile_units().empty())
39 CompileUnits.reserve(File.Dwarf->getNumCompileUnits());
40
41 // Set context format&endianness based on the input file.
42 Format.Version = File.Dwarf->getMaxVersion();
43 Format.AddrSize = File.Dwarf->getCUAddrSize();
44 Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
45 : llvm::endianness::big;
46 }
47}
48
52
56
61
63 CompileUnitHandlerTy OnCUDieLoaded) {
64 ObjectContexts.emplace_back(std::make_unique<LinkContext>(
66
67 if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
68 for (const std::unique_ptr<DWARFUnit> &CU :
69 ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
70 DWARFDie CUDie = CU->getUnitDIE();
72
73 if (!CUDie)
74 continue;
75
76 OnCUDieLoaded(*CU);
77
78 // Register mofule reference.
79 if (!GlobalData.getOptions().UpdateIndexTablesOnly)
80 ObjectContexts.back()->registerModuleReference(CUDie, Loader,
81 OnCUDieLoaded);
82 }
83 }
84}
85
87 ObjectContexts.reserve(ObjFilesNum);
88}
89
91 // reset compile unit unique ID counter.
92 UniqueUnitID = 0;
93
95 return Err;
96
97 dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
100
101 if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
102 GlobalData.getTargetTriple()) {
103 GlobalEndianness = (*CurTriple).get().isLittleEndian()
106 }
107 std::optional<uint16_t> Language;
108
109 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
110 if (Context->InputDWARFFile.Dwarf == nullptr) {
111 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
112 continue;
113 }
114
115 if (GlobalData.getOptions().Verbose) {
116 outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
117 << "\n";
118
119 for (const std::unique_ptr<DWARFUnit> &OrigCU :
120 Context->InputDWARFFile.Dwarf->compile_units()) {
121 outs() << "Input compilation unit:";
122 DIDumpOptions DumpOpts;
123 DumpOpts.ChildRecurseDepth = 0;
124 DumpOpts.Verbose = GlobalData.getOptions().Verbose;
125 OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
126 }
127 }
128
129 // Verify input DWARF if requested.
130 if (GlobalData.getOptions().VerifyInputDWARF)
131 verifyInput(Context->InputDWARFFile);
132
133 if (!GlobalData.getTargetTriple())
134 GlobalEndianness = Context->getEndianness();
135 GlobalFormat.AddrSize =
136 std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
137
138 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
139
140 // FIXME: move creation of CompileUnits into the addObjectFile.
141 // This would allow to not scan for context Language and Modules state
142 // twice. And then following handling might be removed.
143 for (const std::unique_ptr<DWARFUnit> &OrigCU :
144 Context->InputDWARFFile.Dwarf->compile_units()) {
145 DWARFDie UnitDie = OrigCU->getUnitDIE();
146
147 if (!Language) {
148 if (std::optional<DWARFFormValue> Val =
149 UnitDie.find(dwarf::DW_AT_language)) {
150 uint16_t LangVal = dwarf::toUnsigned(Val, 0);
151 if (isODRLanguage(LangVal))
152 Language = LangVal;
153 }
154 }
155 }
156 }
157
158 if (GlobalFormat.AddrSize == 0) {
159 if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
160 GlobalData.getTargetTriple())
161 GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
162 else
163 GlobalFormat.AddrSize = 8;
164 }
165
166 CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
167
168 if (!GlobalData.Options.NoODR && Language.has_value()) {
170 TGroup.spawn([&]() {
171 ArtificialTypeUnit = std::make_unique<TypeUnit>(
172 GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);
173 });
174 }
175
176 // Set parallel options.
177 if (GlobalData.getOptions().Threads == 0)
179 else
181 hardware_concurrency(GlobalData.getOptions().Threads);
182
183 // Link object files.
184 if (GlobalData.getOptions().Threads == 1) {
185 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
186 // Link object file.
187 if (Error Err = Context->link(ArtificialTypeUnit.get()))
188 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
189
190 Context->InputDWARFFile.unload();
191 }
192 } else {
194 for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
195 Pool.async([&]() {
196 // Link object file.
197 if (Error Err = Context->link(ArtificialTypeUnit.get()))
198 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
199
200 Context->InputDWARFFile.unload();
201 });
202
203 Pool.wait();
204 }
205
206 if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()
207 .getRoot()
208 ->getValue()
209 .load()
210 ->Children.empty()) {
211 if (GlobalData.getTargetTriple().has_value())
212 if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(
213 (*GlobalData.getTargetTriple()).get()))
214 return Err;
215 }
216
217 // At this stage each compile units are cloned to their own set of debug
218 // sections. Now, update patches, assign offsets and assemble final file
219 // glueing debug tables from each compile unit.
221
222 return Error::success();
223}
224
226 assert(File.Dwarf);
227
228 std::string Buffer;
229 raw_string_ostream OS(Buffer);
230 DIDumpOptions DumpOpts;
231 if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
232 if (GlobalData.getOptions().InputVerificationHandler)
233 GlobalData.getOptions().InputVerificationHandler(File, OS.str());
234 }
235}
236
238 if (GlobalData.getOptions().TargetDWARFVersion == 0)
239 return createStringError(std::errc::invalid_argument,
240 "target DWARF version is not set");
241
242 if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
243 GlobalData.Options.Threads = 1;
244 GlobalData.warn(
245 "set number of threads to 1 to make --verbose to work properly.", "");
246 }
247
248 // Do not do types deduplication in case --update.
249 if (GlobalData.getOptions().UpdateIndexTablesOnly &&
250 !GlobalData.Options.NoODR)
251 GlobalData.Options.NoODR = true;
252
253 return Error::success();
254}
255
256/// Resolve the relative path to a build artifact referenced by DWARF by
257/// applying DW_AT_comp_dir.
259 sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
260}
261
262static uint64_t getDwoId(const DWARFDie &CUDie) {
263 auto DwoId = dwarf::toUnsigned(
264 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
265 if (DwoId)
266 return *DwoId;
267 return 0;
268}
269
270static std::string
272 const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
273 if (ObjectPrefixMap.empty())
274 return Path.str();
275
276 SmallString<256> p = Path;
277 for (const auto &Entry : ObjectPrefixMap)
278 if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
279 break;
280 return p.str().str();
281}
282
283static std::string getPCMFile(const DWARFDie &CUDie,
284 DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
285 std::string PCMFile = dwarf::toString(
286 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
287
288 if (PCMFile.empty())
289 return PCMFile;
290
291 if (ObjectPrefixMap)
292 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
293
294 return PCMFile;
295}
296
298 const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
299 if (PCMFile.empty())
300 return std::make_pair(false, false);
301
302 // Clang module DWARF skeleton CUs abuse this for the path to the module.
303 uint64_t DwoId = getDwoId(CUDie);
304
305 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
306 if (Name.empty()) {
307 if (!Quiet)
308 GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
309 InputDWARFFile.FileName);
310 return std::make_pair(true, true);
311 }
312
313 if (!Quiet && GlobalData.getOptions().Verbose) {
314 outs().indent(Indent);
315 outs() << "Found clang module reference " << PCMFile;
316 }
317
318 auto Cached = ClangModules.find(PCMFile);
319 if (Cached != ClangModules.end()) {
320 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
321 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
322 // ASTFileSignatures will change randomly when a module is rebuilt.
323 if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
324 GlobalData.warn(
325 Twine("hash mismatch: this object file was built against a "
326 "different version of the module ") +
327 PCMFile + ".",
328 InputDWARFFile.FileName);
329 if (!Quiet && GlobalData.getOptions().Verbose)
330 outs() << " [cached].\n";
331 return std::make_pair(true, true);
332 }
333
334 return std::make_pair(true, false);
335}
336
337/// If this compile unit is really a skeleton CU that points to a
338/// clang module, register it in ClangModules and return true.
339///
340/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
341/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
342/// hash.
344 const DWARFDie &CUDie, ObjFileLoaderTy Loader,
345 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
346 std::string PCMFile =
347 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
348 std::pair<bool, bool> IsClangModuleRef =
349 isClangModuleRef(CUDie, PCMFile, Indent, false);
350
351 if (!IsClangModuleRef.first)
352 return false;
353
354 if (IsClangModuleRef.second)
355 return true;
356
357 if (GlobalData.getOptions().Verbose)
358 outs() << " ...\n";
359
360 // Cyclic dependencies are disallowed by Clang, but we still
361 // shouldn't run into an infinite loop, so mark it as processed now.
362 ClangModules.insert({PCMFile, getDwoId(CUDie)});
363
364 if (Error E =
365 loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
366 consumeError(std::move(E));
367 return false;
368 }
369 return true;
370}
371
373 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
374 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
375
376 uint64_t DwoId = getDwoId(CUDie);
377 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
378
379 /// Using a SmallString<0> because loadClangModule() is recursive.
380 SmallString<0> Path(GlobalData.getOptions().PrependPath);
381 if (sys::path::is_relative(PCMFile))
382 resolveRelativeObjectPath(Path, CUDie);
383 sys::path::append(Path, PCMFile);
384 // Don't use the cached binary holder because we have no thread-safety
385 // guarantee and the lifetime is limited.
386
387 if (Loader == nullptr) {
388 GlobalData.error("cann't load clang module: loader is not specified.",
389 InputDWARFFile.FileName);
390 return Error::success();
391 }
392
393 auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
394 if (!ErrOrObj)
395 return Error::success();
396
397 std::unique_ptr<CompileUnit> Unit;
398 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
399 OnCUDieLoaded(*CU);
400 // Recursively get all modules imported by this one.
401 auto ChildCUDie = CU->getUnitDIE();
402 if (!ChildCUDie)
403 continue;
404 if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
405 if (Unit) {
406 std::string Err =
407 (PCMFile +
408 ": Clang modules are expected to have exactly 1 compile unit.\n");
409 GlobalData.error(Err, InputDWARFFile.FileName);
411 }
412 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
413 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
414 // ASTFileSignatures will change randomly when a module is rebuilt.
415 uint64_t PCMDwoId = getDwoId(ChildCUDie);
416 if (PCMDwoId != DwoId) {
417 if (GlobalData.getOptions().Verbose)
418 GlobalData.warn(
419 Twine("hash mismatch: this object file was built against a "
420 "different version of the module ") +
421 PCMFile + ".",
422 InputDWARFFile.FileName);
423 // Update the cache entry with the DwoId of the module loaded from disk.
424 ClangModules[PCMFile] = PCMDwoId;
425 }
426
427 // Empty modules units should not be cloned.
428 if (!ChildCUDie.hasChildren())
429 continue;
430
431 // Add this module.
432 Unit = std::make_unique<CompileUnit>(
433 GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
434 getUnitForOffset, CU->getFormParams(), getEndianness());
435 }
436 }
437
438 if (Unit) {
439 ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
440 // Preload line table, as it can't be loaded asynchronously.
441 ModulesCompileUnits.back().Unit->loadLineTable();
442 }
443
444 return Error::success();
445}
446
449 if (!InputDWARFFile.Dwarf)
450 return Error::success();
451
452 // Preload macro tables, as they can't be loaded asynchronously.
453 InputDWARFFile.Dwarf->getDebugMacinfo();
454 InputDWARFFile.Dwarf->getDebugMacro();
455
456 // Assign deterministic priorities to module CUs for type DIE allocation.
457 uint64_t LocalCUIdx = 0;
458 for (auto &Mod : ModulesCompileUnits) {
459 if (Error E = Mod.Unit->setPriority(ObjectFileIdx, LocalCUIdx++))
460 return E;
461 }
462
463 // Link modules compile units first.
466 });
467
468 // Check for live relocations. If there is no any live relocation then we
469 // can skip entire object file.
470 if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
471 !InputDWARFFile.Addresses->hasValidRelocs()) {
472 if (GlobalData.getOptions().Verbose)
473 outs() << "No valid relocations found. Skipping.\n";
474 return Error::success();
475 }
476
478
479 // Create CompileUnit structures to keep information about source
480 // DWARFUnit`s, load line tables.
481 for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
482 // Load only unit DIE at this stage.
483 auto CUDie = OrigCU->getUnitDIE();
484 std::string PCMFile =
485 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
486
487 // The !isClangModuleRef condition effectively skips over fully resolved
488 // skeleton units.
489 if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
490 !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
491 CompileUnits.emplace_back(std::make_unique<CompileUnit>(
492 GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
493 getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
494 if (llvm::Error E =
495 CompileUnits.back()->setPriority(ObjectFileIdx, LocalCUIdx++))
496 return E;
497
498 // Preload line table, as it can't be loaded asynchronously.
499 CompileUnits.back()->loadLineTable();
500 }
501 };
502
504
505 // Link self-sufficient compile units and discover inter-connected compile
506 // units.
507 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
509 });
510
511 // Link all inter-connected units.
514
515 if (Error Err = finiteLoop([&]() -> Expected<bool> {
517
518 // Load inter-connected units.
519 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
520 if (CU->isInterconnectedCU()) {
521 CU->maybeResetToLoadedStage();
524 }
525 });
526
527 // Do liveness analysis for inter-connected units.
528 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
531 });
532
533 return HasNewInterconnectedCUs.load();
534 }))
535 return Err;
536
537 // Update dependencies.
538 if (Error Err = finiteLoop([&]() -> Expected<bool> {
540 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
544 });
545 return HasNewGlobalDependency.load();
546 }))
547 return Err;
548 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
549 if (CU->isInterconnectedCU() &&
552 });
553
554 // Assign type names.
555 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
558 });
559
560 // Clone inter-connected units.
561 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
564 });
565
566 // Update patches for inter-connected units.
567 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
570 });
571
572 // Release data.
573 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
576 });
577 }
578
579 if (GlobalData.getOptions().UpdateIndexTablesOnly) {
580 // Emit Invariant sections.
581
582 if (Error Err = emitInvariantSections())
583 return Err;
584 } else if (!CompileUnits.empty()) {
585 // Emit .debug_frame section.
586
587 Error ResultErr = Error::success();
589 // We use task group here as PerThreadBumpPtrAllocator should be called from
590 // the threads created by ThreadPoolExecutor.
591 TGroup.spawn([&]() {
592 if (Error Err = cloneAndEmitDebugFrame())
593 ResultErr = std::move(Err);
594 });
595 return ResultErr;
596 }
597
598 return Error::success();
599}
600
603 enum CompileUnit::Stage DoUntilStage) {
604 if (InterCUProcessingStarted != CU.isInterconnectedCU())
605 return;
606
607 if (Error Err = finiteLoop([&]() -> Expected<bool> {
608 if (CU.getStage() >= DoUntilStage)
609 return false;
610
611 switch (CU.getStage()) {
613 // Load input compilation unit DIEs.
614 // Analyze properties of DIEs.
615 if (!CU.loadInputDIEs()) {
616 // We do not need to do liveness analysis for invalid compilation
617 // unit.
619 } else {
620 CU.analyzeDWARFStructure();
621
622 // The registerModuleReference() condition effectively skips
623 // over fully resolved skeleton units. This second pass of
624 // registerModuleReferences doesn't do any new work, but it
625 // will collect top-level errors, which are suppressed. Module
626 // warnings were already displayed in the first iteration.
628 CU.getOrigUnit().getUnitDIE(), nullptr,
629 [](const DWARFUnit &) {}, 0))
631 else
633 }
634 } break;
635
637 // Mark all the DIEs that need to be present in the generated output.
638 // If ODR requested, build type names.
639 if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
642 "Flag indicating new inter-connections is not set");
643 return false;
644 }
645
647 } break;
648
651 if (CU.updateDependenciesCompleteness())
653 return false;
654 } else {
655 if (Error Err = finiteLoop([&]() -> Expected<bool> {
656 return CU.updateDependenciesCompleteness();
657 }))
658 return std::move(Err);
659
661 }
662 } break;
663
665#ifndef NDEBUG
666 CU.verifyDependencies();
667#endif
668
669 if (ArtificialTypeUnit) {
670 if (Error Err =
671 CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
672 return std::move(Err);
673 }
675 break;
676
678 // Clone input compile unit.
679 if (CU.isClangModule() ||
680 GlobalData.getOptions().UpdateIndexTablesOnly ||
681 CU.getContaingFile().Addresses->hasValidRelocs()) {
682 if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
684 return std::move(Err);
685 }
686
688 break;
689
691 // Update DIEs referencies.
692 CU.updateDieRefPatchesWithClonedOffsets();
694 break;
695
697 // Cleanup resources.
698 CU.cleanupDataAfterClonning();
700 break;
701
703 assert(false);
704 break;
705
707 // Nothing to do.
708 break;
709 }
710
711 return true;
712 })) {
713 CU.error(std::move(Err));
714 CU.cleanupDataAfterClonning();
716 }
717}
718
720 if (!GlobalData.getTargetTriple().has_value())
721 return Error::success();
722
724 << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
726 << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
728 << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
730 << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
732 << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
734 << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
736 << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
737
738 return Error::success();
739}
740
742 if (!GlobalData.getTargetTriple().has_value())
743 return Error::success();
744
745 if (InputDWARFFile.Dwarf == nullptr)
746 return Error::success();
747
748 const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
749
750 StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
751 if (OrigFrameData.empty())
752 return Error::success();
753
754 RangesTy AllUnitsRanges;
755 for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
756 for (auto CurRange : Unit->getFunctionRanges())
757 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
758 }
759
760 unsigned SrcAddrSize = InputDWARFObj.getAddressSize();
761
762 SectionDescriptor &OutSection =
764
765 DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);
766 uint64_t InputOffset = 0;
767
768 // Store the data of the CIEs defined in this object, keyed by their
769 // offsets.
771
772 /// The CIEs that have been emitted in the output section. The actual CIE
773 /// data serves a the key to this StringMap.
774 StringMap<uint32_t> EmittedCIEs;
775
776 while (Data.isValidOffset(InputOffset)) {
777 uint64_t EntryOffset = InputOffset;
778 uint32_t InitialLength = Data.getU32(&InputOffset);
779 if (InitialLength == 0xFFFFFFFF)
780 return createFileError(InputDWARFObj.getFileName(),
781 createStringError(std::errc::invalid_argument,
782 "Dwarf64 bits no supported"));
783
784 uint32_t CIEId = Data.getU32(&InputOffset);
785 if (CIEId == 0xFFFFFFFF) {
786 // This is a CIE, store it.
787 StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4);
788 LocalCIES[EntryOffset] = CIEData;
789 // The -4 is to account for the CIEId we just read.
790 InputOffset += InitialLength - 4;
791 continue;
792 }
793
794 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
795
796 // Some compilers seem to emit frame info that doesn't start at
797 // the function entry point, thus we can't just lookup the address
798 // in the debug map. Use the AddressInfo's range map to see if the FDE
799 // describes something that we can relocate.
800 std::optional<AddressRangeValuePair> Range =
801 AllUnitsRanges.getRangeThatContains(Loc);
802 if (!Range) {
803 // The +4 is to account for the size of the InitialLength field itself.
804 InputOffset = EntryOffset + InitialLength + 4;
805 continue;
806 }
807
808 // This is an FDE, and we have a mapping.
809 // Have we already emitted a corresponding CIE?
810 StringRef CIEData = LocalCIES[CIEId];
811 if (CIEData.empty())
812 return createFileError(
813 InputDWARFObj.getFileName(),
814 createStringError(std::errc::invalid_argument,
815 "Inconsistent debug_frame content. Dropping."));
816
817 uint64_t OffsetToCIERecord = OutSection.OS.tell();
818
819 // Look if we already emitted a CIE that corresponds to the
820 // referenced one (the CIE data is the key of that lookup).
821 auto IteratorInserted =
822 EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord));
823 OffsetToCIERecord = IteratorInserted.first->getValue();
824
825 // Emit CIE for this ID if it is not emitted yet.
826 if (IteratorInserted.second)
827 OutSection.OS << CIEData;
828
829 // Remember offset to the FDE record, so that we might update
830 // field referencing CIE record(containing OffsetToCIERecord),
831 // when final offsets are known. OffsetToCIERecord(which is written later)
832 // is local to the current .debug_frame section, it should be updated
833 // with final offset of the .debug_frame section.
834 OutSection.notePatch(
835 DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});
836
837 // Emit the FDE with updated address and CIE pointer.
838 // (4 + AddrSize) is the size of the CIEId + initial_location
839 // fields that will get reconstructed by emitFDE().
840 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
841 emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value,
842 OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection);
843 InputOffset += FDERemainingBytes;
844 }
845
846 return Error::success();
847}
848
849/// Emit a FDE into the debug_frame section. \p FDEBytes
850/// contains the FDE data without the length, CIE offset and address
851/// which will be replaced with the parameter values.
853 uint32_t AddrSize, uint64_t Address,
854 StringRef FDEBytes,
855 SectionDescriptor &Section) {
856 Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
857 Section.emitIntVal(CIEOffset, 4);
858 Section.emitIntVal(Address, AddrSize);
859 Section.OS.write(FDEBytes.data(), FDEBytes.size());
860}
861
863 if (!GlobalData.getTargetTriple().has_value())
864 return;
866
867 // Go through all object files, all compile units and assign
868 // offsets to them.
870
871 // Patch size/offsets fields according to the assigned CU offsets.
873
874 // Emit common sections and write debug tables from all object files/compile
875 // units into the resulting file.
877
878 if (ArtificialTypeUnit != nullptr)
879 ArtificialTypeUnit.reset();
880
881 // Write common debug sections into the resulting file.
883
884 // Cleanup data.
886
887 if (GlobalData.getOptions().Statistics)
889}
890
892
893 // For each object file map how many bytes were emitted.
894 StringMap<DebugInfoSize> SizeByObject;
895
896 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
897 uint64_t AllDebugInfoSectionsSize = 0;
898
899 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
900 if (std::optional<SectionDescriptor *> DebugInfo =
901 CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
902 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
903
904 auto &Size = SizeByObject[Context->InputDWARFFile.FileName];
905 Size.Input = Context->OriginalDebugInfoSize;
906 Size.Output = AllDebugInfoSectionsSize;
907 }
908
909 // Create a vector sorted in descending order by output size.
910 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
911 for (auto &E : SizeByObject)
912 Sorted.emplace_back(E.first(), E.second);
913 llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
914 return LHS.second.Output > RHS.second.Output;
915 });
916
917 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
918 const float Difference = Output - Input;
919 const float Sum = Input + Output;
920 if (Sum == 0)
921 return 0;
922 return (Difference / (Sum / 2));
923 };
924
925 int64_t InputTotal = 0;
926 int64_t OutputTotal = 0;
927 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
928
929 // Print header.
930 outs() << ".debug_info section size (in bytes)\n";
931 outs() << "----------------------------------------------------------------"
932 "---------------\n";
933 outs() << "Filename Object "
934 " dSYM Change\n";
935 outs() << "----------------------------------------------------------------"
936 "---------------\n";
937
938 // Print body.
939 for (auto &E : Sorted) {
940 InputTotal += E.second.Input;
941 OutputTotal += E.second.Output;
942 llvm::outs() << formatv(
943 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
944 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
945 }
946 // Print total and footer.
947 outs() << "----------------------------------------------------------------"
948 "---------------\n";
949 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
950 ComputePercentange(InputTotal, OutputTotal));
951 outs() << "----------------------------------------------------------------"
952 "---------------\n\n";
953}
954
957 TGroup.spawn([&]() { assignOffsetsToStrings(); });
958 TGroup.spawn([&]() { assignOffsetsToSections(); });
959}
960
962 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
963 uint64_t CurDebugStrOffset =
964 1; // start from 1 to take into account zero entry.
965 size_t CurDebugLineStrIndex = 0;
966 uint64_t CurDebugLineStrOffset = 0;
967
968 // Enumerates all strings, add them into the DwarfStringPoolEntry map,
969 // assign offset and index to the string if it is not indexed yet.
971 const StringEntry *String) {
972 switch (Kind) {
975 assert(Entry != nullptr);
976
977 if (!Entry->isIndexed()) {
978 Entry->Offset = CurDebugStrOffset;
979 CurDebugStrOffset += Entry->String.size() + 1;
980 Entry->Index = CurDebugStrIndex++;
981 }
982 } break;
986 assert(Entry != nullptr);
987
988 if (!Entry->isIndexed()) {
989 Entry->Offset = CurDebugLineStrOffset;
990 CurDebugLineStrOffset += Entry->String.size() + 1;
991 Entry->Index = CurDebugLineStrIndex++;
992 }
993 } break;
994 }
995 });
996}
997
999 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
1000
1001 forEachObjectSectionsSet([&](OutputSections &UnitSections) {
1002 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
1003 });
1004}
1005
1008 StringHandler) {
1009 // To save space we do not create any separate string table.
1010 // We use already allocated string patches and accelerator entries:
1011 // enumerate them in natural order and assign offsets.
1012 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
1013 // sections in the same order as they were assigned offsets.
1015 CU->forEach([&](SectionDescriptor &OutSection) {
1016 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1017 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1018 });
1019
1020 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1021 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1022 });
1023 });
1024
1025 CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
1026 StringHandler(DebugStr, Info.String);
1027 });
1028 });
1029
1030 if (ArtificialTypeUnit != nullptr) {
1031 ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
1032 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1033 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1034 });
1035
1036 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1037 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1038 });
1039
1040 OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
1041 if (Patch.Die == nullptr)
1042 return;
1043
1044 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
1045 if (&TypeEntry->getFinalDie() != Patch.Die)
1046 return;
1047
1048 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1049 });
1050
1051 OutSection.ListDebugTypeLineStrPatch.forEach(
1052 [&](DebugTypeLineStrPatch &Patch) {
1053 if (Patch.Die == nullptr)
1054 return;
1055
1056 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
1057 if (&TypeEntry->getFinalDie() != Patch.Die)
1058 return;
1059
1060 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1061 });
1062 });
1063 }
1064}
1065
1067 function_ref<void(OutputSections &)> SectionsSetHandler) {
1068 // Handle artificial type unit first.
1069 if (ArtificialTypeUnit != nullptr)
1070 SectionsSetHandler(*ArtificialTypeUnit);
1071
1072 // Then all modules(before regular compilation units).
1073 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1074 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1075 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1076 SectionsSetHandler(*ModuleUnit.Unit);
1077
1078 // Finally all compilation units.
1079 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1080 // Handle object file common sections.
1081 SectionsSetHandler(*Context);
1082
1083 // Handle compilation units.
1084 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1085 if (CU->getStage() != CompileUnit::Stage::Skipped)
1086 SectionsSetHandler(*CU);
1087 }
1088}
1089
1091 function_ref<void(DwarfUnit *CU)> UnitHandler) {
1092 if (ArtificialTypeUnit != nullptr)
1093 UnitHandler(ArtificialTypeUnit.get());
1094
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 function_ref<void(CompileUnit *CU)> UnitHandler) {
1110 // Enumerate module units.
1111 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1112 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1113 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1114 UnitHandler(ModuleUnit.Unit.get());
1115
1116 // Enumerate compile units.
1117 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1118 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1119 if (CU->getStage() != CompileUnit::Stage::Skipped)
1120 UnitHandler(CU.get());
1121}
1122
1124 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
1125 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
1126 SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
1127 ArtificialTypeUnit.get());
1128 });
1129 });
1130}
1131
1134
1135 // Create section descriptors ahead if they are not exist at the moment.
1136 // SectionDescriptors container is not thread safe. Thus we should be sure
1137 // that descriptors would not be created in following parallel tasks.
1138
1139 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
1140 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
1141
1142 if (llvm::is_contained(GlobalData.Options.AccelTables,
1144 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
1145 CommonSections.getOrCreateSectionDescriptor(
1147 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
1148 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
1149 }
1150
1151 if (llvm::is_contained(GlobalData.Options.AccelTables,
1153 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
1154
1155 // Emit .debug_str and .debug_line_str sections.
1156 TG.spawn([&]() { emitStringSections(); });
1157
1158 if (llvm::is_contained(GlobalData.Options.AccelTables,
1160 // Emit apple accelerator sections.
1161 TG.spawn([&]() {
1162 emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
1163 });
1164 }
1165
1166 if (llvm::is_contained(GlobalData.Options.AccelTables,
1168 // Emit .debug_names section.
1169 TG.spawn([&]() {
1170 emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
1171 });
1172 }
1173
1174 // Write compile units to the output file.
1175 TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
1176}
1177
1179 uint64_t DebugStrNextOffset = 0;
1180 uint64_t DebugLineStrNextOffset = 0;
1181
1182 // Emit zero length string. Accelerator tables does not work correctly
1183 // if the first string is not zero length string.
1184 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1185 .emitInplaceString("");
1186 DebugStrNextOffset++;
1187
1189 [&](StringDestinationKind Kind, const StringEntry *String) {
1190 switch (Kind) {
1192 DwarfStringPoolEntryWithExtString *StringToEmit =
1193 DebugStrStrings.getExistingEntry(String);
1194 assert(StringToEmit->isIndexed());
1195
1196 // Strings may be repeated. Use accumulated DebugStrNextOffset
1197 // to understand whether corresponding string is already emitted.
1198 // Skip string if its offset less than accumulated offset.
1199 if (StringToEmit->Offset >= DebugStrNextOffset) {
1200 DebugStrNextOffset =
1201 StringToEmit->Offset + StringToEmit->String.size() + 1;
1202 // Emit the string itself.
1203 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1204 .emitInplaceString(StringToEmit->String);
1205 }
1206 } break;
1208 DwarfStringPoolEntryWithExtString *StringToEmit =
1209 DebugLineStrStrings.getExistingEntry(String);
1210 assert(StringToEmit->isIndexed());
1211
1212 // Strings may be repeated. Use accumulated DebugLineStrStrings
1213 // to understand whether corresponding string is already emitted.
1214 // Skip string if its offset less than accumulated offset.
1215 if (StringToEmit->Offset >= DebugLineStrNextOffset) {
1216 DebugLineStrNextOffset =
1217 StringToEmit->Offset + StringToEmit->String.size() + 1;
1218 // Emit the string itself.
1220 .emitInplaceString(StringToEmit->String);
1221 }
1222 } break;
1223 }
1224 });
1225}
1226
1232
1234 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1235 uint64_t OutOffset = Info.OutOffset;
1236 switch (Info.Type) {
1238 llvm_unreachable("Unknown accelerator record");
1239 } break;
1241 AppleNamespaces.addName(
1242 *DebugStrStrings.getExistingEntry(Info.String),
1243 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1244 OutOffset);
1245 } break;
1247 AppleNames.addName(
1248 *DebugStrStrings.getExistingEntry(Info.String),
1249 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1250 OutOffset);
1251 } break;
1253 AppleObjC.addName(
1254 *DebugStrStrings.getExistingEntry(Info.String),
1255 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1256 OutOffset);
1257 } break;
1259 AppleTypes.addName(
1260 *DebugStrStrings.getExistingEntry(Info.String),
1261 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1262 OutOffset,
1263 Info.Tag,
1264 Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1265 : 0,
1266 Info.QualifiedNameHash);
1267 } break;
1268 }
1269 });
1270 });
1271
1272 {
1273 // FIXME: we use AsmPrinter to emit accelerator sections.
1274 // It might be beneficial to directly emit accelerator data
1275 // to the raw_svector_ostream.
1276 SectionDescriptor &OutSection =
1279 OutSection.OS);
1280 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1281 consumeError(std::move(Err));
1282 return;
1283 }
1284
1285 // Emit table.
1286 Emitter.emitAppleNamespaces(AppleNamespaces);
1287 Emitter.finish();
1288
1289 // Set start offset and size for output section.
1291 }
1292
1293 {
1294 // FIXME: we use AsmPrinter to emit accelerator sections.
1295 // It might be beneficial to directly emit accelerator data
1296 // to the raw_svector_ostream.
1297 SectionDescriptor &OutSection =
1298 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
1300 OutSection.OS);
1301 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1302 consumeError(std::move(Err));
1303 return;
1304 }
1305
1306 // Emit table.
1307 Emitter.emitAppleNames(AppleNames);
1308 Emitter.finish();
1309
1310 // Set start offset ans size for output section.
1312 }
1313
1314 {
1315 // FIXME: we use AsmPrinter to emit accelerator sections.
1316 // It might be beneficial to directly emit accelerator data
1317 // to the raw_svector_ostream.
1318 SectionDescriptor &OutSection =
1319 CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
1321 OutSection.OS);
1322 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1323 consumeError(std::move(Err));
1324 return;
1325 }
1326
1327 // Emit table.
1328 Emitter.emitAppleObjc(AppleObjC);
1329 Emitter.finish();
1330
1331 // Set start offset ans size for output section.
1333 }
1334
1335 {
1336 // FIXME: we use AsmPrinter to emit accelerator sections.
1337 // It might be beneficial to directly emit accelerator data
1338 // to the raw_svector_ostream.
1339 SectionDescriptor &OutSection =
1340 CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
1342 OutSection.OS);
1343 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1344 consumeError(std::move(Err));
1345 return;
1346 }
1347
1348 // Emit table.
1349 Emitter.emitAppleTypes(AppleTypes);
1350 Emitter.finish();
1351
1352 // Set start offset ans size for output section.
1354 }
1355}
1356
1358 std::unique_ptr<DWARF5AccelTable> DebugNames;
1359
1360 DebugNamesUnitsOffsets CompUnits;
1361 CompUnitIDToIdx CUidToIdx;
1362
1363 unsigned Id = 0;
1364
1366 bool HasRecords = false;
1367 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1368 if (DebugNames == nullptr)
1369 DebugNames = std::make_unique<DWARF5AccelTable>();
1370
1371 HasRecords = true;
1372 switch (Info.Type) {
1376 DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1377 Info.OutOffset, std::nullopt /*ParentDIEOffset*/,
1378 Info.Tag, CU->getUniqueID(),
1379 CU->getTag() == dwarf::DW_TAG_type_unit);
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 != 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 =
1400 CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
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
1418 GlobalData.getStringPool().clear();
1419 DebugStrStrings.clear();
1420 DebugLineStrStrings.clear();
1421}
1422
1424 // Enumerate all sections and store them into the final emitter.
1426 Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1427 // Emit section content.
1428 SectionHandler(OutSection);
1429 });
1430 });
1431}
1432
1434 CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1435 SectionHandler(OutSection);
1436 });
1437}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
dxil DXContainer Global Emitter
static fatal_error_handler_t ErrorHandler
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
The Input class is used to parse a yaml document into in-memory structs and vectors.
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
Definition AccelTable.h:203
std::optional< T > getRangeThatContains(uint64_t Addr) const
void insert(AddressRange Range, int64_t Value)
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:317
virtual bool isLittleEndian() const =0
virtual StringRef getFileName() const
Definition DWARFObject.h:31
virtual const DWARFSection & getFrameSection() const
Definition DWARFObject.h:44
virtual uint8_t getAddressSize() const
Definition DWARFObject.h:35
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
void wait() override
Blocking wait for all the tasks to execute first.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:133
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition StringMap.h:321
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:591
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:140
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:143
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:137
auto async(Function &&F, Args &&...ArgList)
Asynchronous submission of a task to the pool.
Definition ThreadPool.h:80
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
This class represents DWARF information for source file and it's address map.
Definition DWARFFile.h:25
std::map< std::string, std::string > ObjectPrefixMapTy
function_ref< void(const DWARFUnit &Unit)> CompileUnitHandlerTy
std::function< void( const Twine &Warning, StringRef Context, const DWARFDie *DIE)> MessageHandlerTy
@ Apple
.apple_names, .apple_namespaces, .apple_types, .apple_objc.
std::function< ErrorOr< DWARFFile & >( StringRef ContainerName, StringRef Path)> ObjFileLoaderTy
Stores all information related to a compile unit, be it in its original instance of the object file o...
Stage
The stages of new compile unit processing.
@ CreatedNotLoaded
Created, linked with input DWARF file.
@ PatchesUpdated
Offsets inside patch records are updated.
@ Cleaned
Resources(Input DWARF, Output DWARF tree) are released.
@ LivenessAnalysisDone
Input DWARF is analysed(DIEs pointing to the real code section arediscovered, type names are assigned...
@ UpdateDependenciesCompleteness
Check if dependencies have incompatible placement.
void forEachObjectSectionsSet(function_ref< void(OutputSections &SectionsSet)> SectionsSetHandler)
Enumerates sections for modules, invariant for object files, compile units.
void emitDWARFv5DebugNamesSection(const Triple &TargetTriple)
Emit .debug_names section.
void writeCompileUnitsToTheOutput()
Enumerate all compile units and put their data into the output stream.
void forEachCompileUnit(function_ref< void(CompileUnit *CU)> UnitHandler)
Enumerates all comple units.
void assignOffsetsToStrings()
Enumerate all compile units and assign offsets to their strings.
void assignOffsets()
Enumerate all compile units and assign offsets to their sections and strings.
Error link() override
Link debug info for added files.
Error validateAndUpdateOptions()
Validate specified options.
void writeCommonSectionsToTheOutput()
Enumerate common sections and put their data into the output stream.
void assignOffsetsToSections()
Enumerate all compile units and assign offsets to their sections.
void printStatistic()
Print statistic for processed Debug Info.
void glueCompileUnitsAndWriteToTheOutput()
Take already linked compile units and glue them into single file.
void emitAppleAcceleratorSections(const Triple &TargetTriple)
Emit apple accelerator sections.
void verifyInput(const DWARFFile &File)
Verify input DWARF file.
void forEachCompileAndTypeUnit(function_ref< void(DwarfUnit *CU)> UnitHandler)
Enumerates all compile and type units.
DWARFLinkerImpl(MessageHandlerTy ErrorHandler, MessageHandlerTy WarningHandler)
void addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader=nullptr, CompileUnitHandlerTy OnCUDieLoaded=[](const DWARFUnit &) {}) override
Add object file to be linked.
void cleanupDataAfterDWARFOutputIsWritten()
Cleanup data(string pools) after output sections are generated.
void forEachOutputString(function_ref< void(StringDestinationKind, const StringEntry *)> StringHandler)
Enumerates all strings.
void emitCommonSectionsAndWriteCompileUnitsToTheOutput()
Emit debug sections common for all input files.
void patchOffsetsAndSizes()
Enumerates all patches and update them with the correct values.
This class emits DWARF data to the output stream.
Base class for all Dwarf units(Compile unit/Type table unit).
This class keeps data and services common for the whole linking process.
This class keeps contents and offsets to the debug sections.
void applyPatches(SectionDescriptor &Section, StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, TypeUnit *TypeUnitPtr)
Enumerate all sections, for each section apply all section patches.
OutputSections(LinkingGlobalData &GlobalData)
void forEach(function_ref< void(SectionDescriptor &)> Handler)
Enumerate all sections and call Handler for each.
llvm::endianness getEndianness() const
Endiannes for the sections.
SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)
Returns descriptor for the specified section of SectionKind.
void assignSectionsOffsetAndAccumulateSize(std::array< uint64_t, SectionKindsNum > &SectionSizesAccumulator)
Enumerate all sections, for each section set current offset (kept by SectionSizesAccumulator),...
Keeps cloned data for the type DIE.
Definition TypePool.h:31
Type Unit is used to represent an artificial compilation unit which keeps all type information.
An efficient, type-erasing, non-owning reference to a callable.
LLVM_ABI void spawn(std::function< void()> f)
Definition Parallel.cpp:257
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
std::atomic< size_t > UniqueUnitID
Unique ID for compile unit.
uint64_t OverallNumberOfCU
Overall compile units number.
SmallVector< std::unique_ptr< LinkContext > > ObjectContexts
Keeps all linking contexts.
StringEntryToDwarfStringPoolEntryMap DebugLineStrStrings
DwarfStringPoolEntries for .debug_line_str section.
SectionHandlerTy SectionHandler
Hanler for output sections.
std::unique_ptr< TypeUnit > ArtificialTypeUnit
Type unit.
StringEntryToDwarfStringPoolEntryMap DebugStrStrings
DwarfStringPoolEntries for .debug_str section.
OutputSections CommonSections
Common sections.
StringMap< uint64_t > ClangModules
Mapping the PCM filename to the DwoId.
void setEstimatedObjfilesAmount(unsigned ObjFilesNum) override
Set estimated objects files amount, for preliminary data allocation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isODRLanguage(uint16_t Language)
std::vector< std::variant< MCSymbol *, uint64_t > > DebugNamesUnitsOffsets
DenseMap< unsigned, unsigned > CompUnitIDToIdx
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:28
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
Definition StringPool.h:23
Error finiteLoop(function_ref< Expected< bool >()> Iteration, size_t MaxCounter=100000)
This function calls Iteration() until it returns false.
Definition Utils.h:26
AddressRangesMap RangesTy
Mapped value in the address map is the offset to apply to the linked address.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
@ DWARF32
Definition Dwarf.h:93
@ DW_FLAG_type_implementation
Definition Dwarf.h:953
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
LLVM_ABI ThreadPoolStrategy strategy
Definition Parallel.cpp:27
LLVM_ABI bool is_relative(const Twine &path, Style style=Style::native)
Is path relative?
Definition Path.cpp:706
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:584
LLVM_ABI bool replace_path_prefix(SmallVectorImpl< char > &Path, StringRef OldPrefix, StringRef NewPrefix, Style style=Style::native)
Replace matching path prefix with another path.
Definition Path.cpp:519
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
Definition Threading.h:190
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
Definition Error.h:1415
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition Error.cpp:94
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
static std::string remapPath(StringRef Path, const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
static void resolveRelativeObjectPath(SmallVectorImpl< char > &Buf, DWARFDie CU)
Resolve the relative path to a build artifact referenced by DWARF by applying DW_AT_comp_dir.
static std::string getPCMFile(const DWARFDie &CUDie, const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1635
ThreadPoolStrategy optimal_concurrency(unsigned TaskCount=0)
Returns an optimal thread strategy to execute specified amount of tasks.
Definition Threading.h:211
static uint64_t getDwoId(const DWARFDie &CUDie)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ Other
Any other memory.
Definition ModRef.h:68
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
SingleThreadExecutor DefaultThreadPool
Definition ThreadPool.h:262
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1916
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1946
void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn)
Definition Parallel.h:229
endianness
Definition bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
Container for dump options that control which debug information will be dumped.
Definition DIContext.h:196
DIDumpOptions noImplicitRecursion() const
Return the options with RecurseDepth set to 0 unless explicitly required.
Definition DIContext.h:228
unsigned ChildRecurseDepth
Definition DIContext.h:198
DwarfStringPoolEntry with string keeping externally.
A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...
Definition Dwarf.h:1114
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 ...
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.
LinkContext(LinkingGlobalData &GlobalData, DWARFFile &File, uint64_t ObjFileIdx, StringMap< uint64_t > &ClangModules, std::atomic< size_t > &UniqueUnitID)
std::atomic< bool > HasNewInterconnectedCUs
Flag indicating that new inter-connected compilation units were discovered.
std::atomic< size_t > & UniqueUnitID
Counter for compile units ID.
Error link(TypeUnit *ArtificialTypeUnit)
Link compile units for this context.
uint64_t ObjectFileIdx
Index of this object file in the link order (used for deterministic type DIE allocation).
std::function< CompileUnit *(uint64_t)> getUnitForOffset
ModuleUnitListTy ModulesCompileUnits
Set of Compile Units for modules.
This structure is used to update strings offsets into .debug_line_str.
This structure is used to update strings offsets into .debug_str.
This structure keeps fields which would be used for creating accelerator table.
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.