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 if (Error Err = Context->unloadInput())
190 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
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 if (Error Err = Context->unloadInput())
200 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
201 });
202
203 Pool.wait();
204 }
205
206 // Merge staged parseable Swift interface entries into the shared map. Done
207 // serially so that the final map contents and any conflict warnings are
208 // deterministic.
209 if (DWARFLinkerBase::SwiftInterfacesMapTy *SwiftInterfaces =
210 GlobalData.Options.ParseableSwiftInterfaces) {
211 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
212 for (LinkContext::RefModuleUnit &ModuleUnit :
213 Context->ModulesCompileUnits)
214 ModuleUnit.Unit->mergeSwiftInterfaces(*SwiftInterfaces);
215 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
216 CU->mergeSwiftInterfaces(*SwiftInterfaces);
217 }
218 }
219
220 // Build the linker-wide CIE registry, then emit each context's
221 // .debug_frame in parallel. See CIERegistry for the ownership rules.
222 if (!GlobalData.getOptions().UpdateIndexTablesOnly) {
224 for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
225 if (Context->FrameScan)
226 Context->registerCIEs(CIEs);
227
229 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
230 if (!Context->FrameScan)
231 continue;
232 TGroup.spawn([&]() {
233 if (Error Err = Context->emitDebugFrame(CIEs))
234 GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
235 });
236 }
237 }
238
239 if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()
240 .getRoot()
241 ->getValue()
242 .load()
243 ->Children.empty()) {
244 if (GlobalData.getTargetTriple().has_value())
245 if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(
246 (*GlobalData.getTargetTriple()).get()))
247 return Err;
248 }
249
250 // At this stage each compile units are cloned to their own set of debug
251 // sections. Now, update patches, assign offsets and assemble final file
252 // glueing debug tables from each compile unit.
254
255 return Error::success();
256}
257
259 assert(File.Dwarf);
260
261 std::string Buffer;
262 raw_string_ostream OS(Buffer);
263 DIDumpOptions DumpOpts;
264 if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
265 if (GlobalData.getOptions().InputVerificationHandler)
266 GlobalData.getOptions().InputVerificationHandler(File, OS.str());
267 }
268}
269
271 if (GlobalData.getOptions().TargetDWARFVersion == 0)
272 return createStringError(std::errc::invalid_argument,
273 "target DWARF version is not set");
274
275 if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
276 GlobalData.Options.Threads = 1;
277 GlobalData.warn(
278 "set number of threads to 1 to make --verbose to work properly.", "");
279 }
280
281 // Do not do types deduplication in case --update.
282 if (GlobalData.getOptions().UpdateIndexTablesOnly &&
283 !GlobalData.Options.NoODR)
284 GlobalData.Options.NoODR = true;
285
286 return Error::success();
287}
288
289/// Resolve the relative path to a build artifact referenced by DWARF by
290/// applying DW_AT_comp_dir.
292 sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
293}
294
295static uint64_t getDwoId(const DWARFDie &CUDie) {
296 auto DwoId = dwarf::toUnsigned(
297 CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
298 if (DwoId)
299 return *DwoId;
300 return 0;
301}
302
303static std::string
305 const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
306 if (ObjectPrefixMap.empty())
307 return Path.str();
308
309 SmallString<256> p = Path;
310 for (const auto &Entry : ObjectPrefixMap)
311 if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
312 break;
313 return p.str().str();
314}
315
316static std::string getPCMFile(const DWARFDie &CUDie,
317 DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
318 std::string PCMFile = dwarf::toString(
319 CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
320
321 if (PCMFile.empty())
322 return PCMFile;
323
324 if (ObjectPrefixMap)
325 PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
326
327 return PCMFile;
328}
329
331 const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
332 if (PCMFile.empty())
333 return std::make_pair(false, false);
334
335 // Clang module DWARF skeleton CUs abuse this for the path to the module.
336 uint64_t DwoId = getDwoId(CUDie);
337
338 std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
339 if (Name.empty()) {
340 if (!Quiet)
341 GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
342 InputDWARFFile.FileName);
343 return std::make_pair(true, true);
344 }
345
346 if (!Quiet && GlobalData.getOptions().Verbose) {
347 outs().indent(Indent);
348 outs() << "Found clang module reference " << PCMFile;
349 }
350
351 auto Cached = ClangModules.find(PCMFile);
352 if (Cached != ClangModules.end()) {
353 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
354 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
355 // ASTFileSignatures will change randomly when a module is rebuilt.
356 if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
357 GlobalData.warn(
358 Twine("hash mismatch: this object file was built against a "
359 "different version of the module ") +
360 PCMFile + ".",
361 InputDWARFFile.FileName);
362 if (!Quiet && GlobalData.getOptions().Verbose)
363 outs() << " [cached].\n";
364 return std::make_pair(true, true);
365 }
366
367 return std::make_pair(true, false);
368}
369
370/// If this compile unit is really a skeleton CU that points to a
371/// clang module, register it in ClangModules and return true.
372///
373/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
374/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
375/// hash.
377 const DWARFDie &CUDie, ObjFileLoaderTy Loader,
378 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
379 std::string PCMFile =
380 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
381 std::pair<bool, bool> IsClangModuleRef =
382 isClangModuleRef(CUDie, PCMFile, Indent, false);
383
384 if (!IsClangModuleRef.first)
385 return false;
386
387 if (IsClangModuleRef.second)
388 return true;
389
390 if (GlobalData.getOptions().Verbose)
391 outs() << " ...\n";
392
393 // Cyclic dependencies are disallowed by Clang, but we still
394 // shouldn't run into an infinite loop, so mark it as processed now.
395 ClangModules.insert({PCMFile, getDwoId(CUDie)});
396
397 if (Error E =
398 loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
399 consumeError(std::move(E));
400 return false;
401 }
402 return true;
403}
404
406 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
407 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
408
409 uint64_t DwoId = getDwoId(CUDie);
410 std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
411
412 /// Using a SmallString<0> because loadClangModule() is recursive.
413 SmallString<0> Path(GlobalData.getOptions().PrependPath);
414 if (sys::path::is_relative(PCMFile))
415 resolveRelativeObjectPath(Path, CUDie);
416 sys::path::append(Path, PCMFile);
417 // Don't use the cached binary holder because we have no thread-safety
418 // guarantee and the lifetime is limited.
419
420 if (Loader == nullptr) {
421 GlobalData.error("cann't load clang module: loader is not specified.",
422 InputDWARFFile.FileName);
423 return Error::success();
424 }
425
426 auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
427 if (!ErrOrObj)
428 return Error::success();
429
430 std::unique_ptr<CompileUnit> Unit;
431 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
432 OnCUDieLoaded(*CU);
433 // Recursively get all modules imported by this one.
434 auto ChildCUDie = CU->getUnitDIE();
435 if (!ChildCUDie)
436 continue;
437 if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
438 if (Unit) {
439 std::string Err =
440 (PCMFile +
441 ": Clang modules are expected to have exactly 1 compile unit.\n");
442 GlobalData.error(Err, InputDWARFFile.FileName);
444 }
445 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
446 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
447 // ASTFileSignatures will change randomly when a module is rebuilt.
448 uint64_t PCMDwoId = getDwoId(ChildCUDie);
449 if (PCMDwoId != DwoId) {
450 if (GlobalData.getOptions().Verbose)
451 GlobalData.warn(
452 Twine("hash mismatch: this object file was built against a "
453 "different version of the module ") +
454 PCMFile + ".",
455 InputDWARFFile.FileName);
456 // Update the cache entry with the DwoId of the module loaded from disk.
457 ClangModules[PCMFile] = PCMDwoId;
458 }
459
460 // Empty modules units should not be cloned.
461 if (!ChildCUDie.hasChildren())
462 continue;
463
464 // Add this module.
465 Unit = std::make_unique<CompileUnit>(
466 GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
467 getUnitForOffset, CU->getFormParams(), getEndianness());
468 }
469 }
470
471 if (Unit) {
472 ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
473 // Preload line table, as it can't be loaded asynchronously.
474 ModulesCompileUnits.back().Unit->loadLineTable();
475 }
476
477 return Error::success();
478}
479
482 if (!InputDWARFFile.Dwarf)
483 return Error::success();
484
485 // Preload macro tables, as they can't be loaded asynchronously.
486 InputDWARFFile.Dwarf->getDebugMacinfo();
487 InputDWARFFile.Dwarf->getDebugMacro();
488
489 // Assign deterministic priorities to module CUs for type DIE allocation.
490 uint64_t LocalCUIdx = 0;
491 for (auto &Mod : ModulesCompileUnits) {
492 if (Error E = Mod.Unit->setPriority(ObjectFileIdx, LocalCUIdx++))
493 return E;
494 }
495
496 // Link modules compile units first.
499 });
500
501 // Check for live relocations. If there is no any live relocation then we
502 // can skip entire object file.
503 if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
504 !InputDWARFFile.Addresses->hasValidRelocs()) {
505 if (GlobalData.getOptions().Verbose)
506 outs() << "No valid relocations found. Skipping.\n";
507 return Error::success();
508 }
509
511
512 // Create CompileUnit structures to keep information about source
513 // DWARFUnit`s, load line tables.
514 for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
515 // Load only unit DIE at this stage.
516 auto CUDie = OrigCU->getUnitDIE();
517 std::string PCMFile =
518 getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
519
520 // The !isClangModuleRef condition effectively skips over fully resolved
521 // skeleton units.
522 if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
523 !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
524 CompileUnits.emplace_back(std::make_unique<CompileUnit>(
525 GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
526 getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
527 if (llvm::Error E =
528 CompileUnits.back()->setPriority(ObjectFileIdx, LocalCUIdx++))
529 return E;
530
531 // Preload line table, as it can't be loaded asynchronously.
532 CompileUnits.back()->loadLineTable();
533 }
534 };
535
537
538 // Link self-sufficient compile units and discover inter-connected compile
539 // units.
540 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
542 });
543
544 // Link all inter-connected units.
547
548 if (Error Err = finiteLoop([&]() -> Expected<bool> {
550
551 // Load inter-connected units.
552 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
553 if (CU->isInterconnectedCU()) {
554 CU->maybeResetToLoadedStage();
557 }
558 });
559
560 // Do liveness analysis for inter-connected units.
561 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
564 });
565
566 return HasNewInterconnectedCUs.load();
567 }))
568 return Err;
569
570 // Update dependencies.
571 if (Error Err = finiteLoop([&]() -> Expected<bool> {
573 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
577 });
578 return HasNewGlobalDependency.load();
579 }))
580 return Err;
581 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
582 if (CU->isInterconnectedCU() &&
585 });
586
587 // Assign type names.
588 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
591 });
592
593 // Clone inter-connected units.
594 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
597 });
598
599 // Update patches for inter-connected units.
600 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
603 });
604
605 // Release data.
606 parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
609 });
610 }
611
612 if (GlobalData.getOptions().UpdateIndexTablesOnly) {
613 // Emit Invariant sections.
614
615 if (Error Err = emitInvariantSections())
616 return Err;
617 }
618
619 return Error::success();
620}
621
624 enum CompileUnit::Stage DoUntilStage) {
625 if (InterCUProcessingStarted != CU.isInterconnectedCU())
626 return;
627
628 if (Error Err = finiteLoop([&]() -> Expected<bool> {
629 if (CU.getStage() >= DoUntilStage)
630 return false;
631
632 switch (CU.getStage()) {
634 // Load input compilation unit DIEs.
635 // Analyze properties of DIEs.
636 if (!CU.loadInputDIEs()) {
637 // We do not need to do liveness analysis for invalid compilation
638 // unit.
640 } else {
641 CU.analyzeDWARFStructure();
642
643 // The registerModuleReference() condition effectively skips
644 // over fully resolved skeleton units. This second pass of
645 // registerModuleReferences doesn't do any new work, but it
646 // will collect top-level errors, which are suppressed. Module
647 // warnings were already displayed in the first iteration.
649 CU.getOrigUnit().getUnitDIE(), nullptr,
650 [](const DWARFUnit &) {}, 0))
652 else
654 }
655 } break;
656
658 // Mark all the DIEs that need to be present in the generated output.
659 // If ODR requested, build type names.
660 if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
663 "Flag indicating new inter-connections is not set");
664 return false;
665 }
666
668 } break;
669
672 if (CU.updateDependenciesCompleteness())
674 return false;
675 } else {
676 if (Error Err = finiteLoop([&]() -> Expected<bool> {
677 return CU.updateDependenciesCompleteness();
678 }))
679 return std::move(Err);
680
682 }
683 } break;
684
686#ifndef NDEBUG
687 CU.verifyDependencies();
688#endif
689
690 if (ArtificialTypeUnit) {
691 if (Error Err =
692 CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
693 return std::move(Err);
694 }
696 break;
697
699 // Clone input compile unit.
700 if (CU.isClangModule() ||
701 GlobalData.getOptions().UpdateIndexTablesOnly ||
702 CU.getContaingFile().Addresses->hasValidRelocs()) {
703 if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
705 return std::move(Err);
706 }
707
709 break;
710
712 // Update DIEs referencies.
713 CU.updateDieRefPatchesWithClonedOffsets();
715 break;
716
718 // Cleanup resources.
719 CU.cleanupDataAfterClonning();
721 break;
722
724 assert(false);
725 break;
726
728 // Nothing to do.
729 break;
730 }
731
732 return true;
733 })) {
734 CU.error(std::move(Err));
735 CU.cleanupDataAfterClonning();
737 }
738}
739
741 if (!GlobalData.getTargetTriple().has_value())
742 return Error::success();
743
745 << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
747 << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
749 << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
751 << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
753 << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
755 << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
757 << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
758
759 return Error::success();
760}
761
763 if (GlobalData.getOptions().UpdateIndexTablesOnly)
764 return Error::success();
765 if (!GlobalData.getTargetTriple().has_value())
766 return Error::success();
767
768 if (InputDWARFFile.Dwarf == nullptr)
769 return Error::success();
770 if (CompileUnits.empty())
771 return Error::success();
772
773 const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
774
775 StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
776 if (OrigFrameData.empty())
777 return Error::success();
778
779 auto Scan = std::make_unique<FrameScanResult>();
780 Scan->FrameData = OrigFrameData;
781 Scan->AddressSize = InputDWARFObj.getAddressSize();
782
783 RangesTy AllUnitsRanges;
784 for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
785 for (auto CurRange : Unit->getFunctionRanges())
786 AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
787 }
788
789 StringRef FrameBytes = Scan->FrameData;
790 DataExtractor Data(FrameBytes, InputDWARFObj.isLittleEndian(), 0);
791 uint64_t InputOffset = 0;
792 const unsigned SrcAddrSize = Scan->AddressSize;
793 // Width of the CIE_pointer field at the start of every FDE (and of the
794 // CIE_id sentinel at the start of every CIE) in DWARF32 .debug_frame.
795 constexpr unsigned CIEPointerSize = 4;
796
797 // CIEs defined in this input, keyed by their input offsets.
799 DenseSet<uint64_t> AddedCIEs;
800
801 while (Data.isValidOffset(InputOffset)) {
802 uint64_t EntryOffset = InputOffset;
803 uint32_t InitialLength = Data.getU32(&InputOffset);
804 if (InitialLength == 0xFFFFFFFF)
805 return createFileError(InputDWARFFile.FileName,
806 createStringError(std::errc::invalid_argument,
807 "Dwarf64 bits not supported"));
808
809 // Reject lengths that don't fit in the input section. substr() saturates
810 // silently, which would otherwise let a malformed length poison the
811 // CIE bytes used as the registry key.
812 if (InitialLength > FrameBytes.size() - InputOffset)
813 return createFileError(
814 InputDWARFFile.FileName,
815 createStringError(std::errc::invalid_argument,
816 "Truncated .debug_frame entry."));
817
818 uint32_t CIEId = Data.getU32(&InputOffset);
819 if (CIEId == 0xFFFFFFFF) {
820 // This is a CIE, store it.
821 StringRef CIEData = FrameBytes.substr(EntryOffset, InitialLength + 4);
822 LocalCIEs[EntryOffset] = CIEData;
823 // The -4 is to account for the CIEId we just read.
824 InputOffset += InitialLength - 4;
825 continue;
826 }
827
828 uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
829
830 // Some compilers seem to emit frame info that doesn't start at
831 // the function entry point, thus we can't just lookup the address
832 // in the debug map. Use the AddressInfo's range map to see if the FDE
833 // describes something that we can relocate.
834 std::optional<AddressRangeValuePair> Range =
835 AllUnitsRanges.getRangeThatContains(Loc);
836 if (!Range) {
837 // The +4 is to account for the size of the InitialLength field itself.
838 InputOffset = EntryOffset + InitialLength + 4;
839 continue;
840 }
841
842 // This is an FDE, and we have a mapping.
843 StringRef CIEData = LocalCIEs.lookup(CIEId);
844 if (CIEData.empty())
845 return createFileError(
846 InputDWARFFile.FileName,
847 createStringError(std::errc::invalid_argument,
848 "Inconsistent debug_frame content. Dropping."));
849
850 // Reject FDEs whose length doesn't even cover the CIE_pointer and
851 // initial_location fields; otherwise the unsigned subtraction below
852 // would wrap and substr() would saturate to a giant garbage blob.
853 if (InitialLength < CIEPointerSize + SrcAddrSize)
854 return createFileError(InputDWARFFile.FileName,
855 createStringError(std::errc::invalid_argument,
856 "Truncated .debug_frame FDE."));
857
858 // Promote each CIE on first reference; CIEs no FDE references are
859 // dropped from the output.
860 if (AddedCIEs.insert(CIEId).second)
861 Scan->CIEs.push_back(CIEData);
862
863 unsigned FDERemainingBytes = InitialLength - (CIEPointerSize + SrcAddrSize);
864 Scan->FDEs.push_back({CIEData, Loc + Range->Value,
865 FrameBytes.substr(InputOffset, FDERemainingBytes)});
866 InputOffset += FDERemainingBytes;
867 }
868
869 FrameScan = std::move(Scan);
870 return Error::success();
871}
872
874 assert(FrameScan && "registerCIEs called without FrameScan");
875 SectionDescriptor &OutSection =
877
878 uint32_t NextLocalOffset = 0;
879 for (StringRef CIEBytes : FrameScan->CIEs) {
880 auto [It, Inserted] =
881 CIEs.try_emplace(CIEBytes, CIELocation{&OutSection, NextLocalOffset});
882 if (Inserted) {
883 FrameScan->OwnedCIEs.push_back(CIEBytes);
884 NextLocalOffset += static_cast<uint32_t>(CIEBytes.size());
885 }
886 }
887}
888
890 assert(FrameScan && "emitDebugFrame called without FrameScan");
891 SectionDescriptor &OutSection =
893
894 // Emit owned CIEs at the offsets registerCIEs reserved for them.
895 for (StringRef CIEBytes : FrameScan->OwnedCIEs)
896 OutSection.OS << CIEBytes;
897
898 const dwarf::FormParams FP = OutSection.getFormParams();
899 const unsigned SrcAddrSize = FrameScan->AddressSize;
900
901 for (const FrameScanResult::FDE &FDE : FrameScan->FDEs) {
902 auto It = CIEs.find(FDE.CIEBytes);
903 assert(It != CIEs.end() && "CIE missing from registry");
904 SectionDescriptor *CIEOwnerSection = It->second.OwnerSection;
905 const uint32_t CIELocalOffset = It->second.LocalOffset;
906
907 const uint64_t FDEPos = OutSection.OS.tell();
908 // Note: this guards against a single context's section exceeding the
909 // DWARF32 limit. It does NOT catch the post-glue overflow that would
910 // happen if the concatenated .debug_frame across all contexts pushes
911 // past 4 GB; that case slips through silently because StartOffset is
912 // not yet assigned. A post-glue check would belong in the patch
913 // resolver in OutputSections.cpp.
914 if (FDEPos > FP.getDwarfMaxOffset())
915 return createFileError(
916 InputDWARFFile.FileName,
917 createStringError(".debug_frame section offset "
918 "0x" +
919 Twine::utohexstr(FDEPos) + " exceeds the " +
920 dwarf::FormatString(FP.Format) + " limit"));
921
922 // CIE_pointer field follows the 4-byte initial_length.
923 OutSection.notePatch(DebugOffsetPatch{FDEPos + 4, CIEOwnerSection, true});
924
925 emitFDE(CIELocalOffset, SrcAddrSize, FDE.Address, FDE.Instructions,
926 OutSection);
927 }
928
929 FrameScan.reset();
930 return Error::success();
931}
932
934 // Scan the input's .debug_frame now, while the DWARFContext is still
935 // loaded, so the later (post-pool) emission pass can run against the
936 // scan result alone.
937 Error ScanErr = scanFrameData();
938 InputDWARFFile.unload();
939 return ScanErr;
940}
941
942/// Emit a FDE into the debug_frame section. \p FDEBytes
943/// contains the FDE data without the length, CIE offset and address
944/// which will be replaced with the parameter values.
946 uint32_t AddrSize, uint64_t Address,
947 StringRef FDEBytes,
948 SectionDescriptor &Section) {
949 Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
950 Section.emitIntVal(CIEOffset, 4);
951 Section.emitIntVal(Address, AddrSize);
952 Section.OS.write(FDEBytes.data(), FDEBytes.size());
953}
954
956 if (!GlobalData.getTargetTriple().has_value())
957 return;
959
960 // Go through all object files, all compile units and assign
961 // offsets to them.
963
964 // Patch size/offsets fields according to the assigned CU offsets.
966
967 // Emit common sections and write debug tables from all object files/compile
968 // units into the resulting file.
970
971 if (ArtificialTypeUnit != nullptr)
972 ArtificialTypeUnit.reset();
973
974 // Write common debug sections into the resulting file.
976
977 // Cleanup data.
979
980 if (GlobalData.getOptions().Statistics)
982}
983
985
986 // For each object file map how many bytes were emitted.
987 StringMap<DebugInfoSize> SizeByObject;
988
989 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
990 uint64_t AllDebugInfoSectionsSize = 0;
991
992 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
993 if (std::optional<SectionDescriptor *> DebugInfo =
994 CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
995 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
996
997 auto &Size = SizeByObject[Context->InputDWARFFile.FileName];
998 Size.Input = Context->OriginalDebugInfoSize;
999 Size.Output = AllDebugInfoSectionsSize;
1000 }
1001
1002 // Create a vector sorted in descending order by output size.
1003 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
1004 for (auto &E : SizeByObject)
1005 Sorted.emplace_back(E.first(), E.second);
1006 llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
1007 return LHS.second.Output > RHS.second.Output;
1008 });
1009
1010 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
1011 const float Difference = Output - Input;
1012 const float Sum = Input + Output;
1013 if (Sum == 0)
1014 return 0;
1015 return (Difference / (Sum / 2));
1016 };
1017
1018 int64_t InputTotal = 0;
1019 int64_t OutputTotal = 0;
1020 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
1021
1022 // Print header.
1023 outs() << ".debug_info section size (in bytes)\n";
1024 outs() << "----------------------------------------------------------------"
1025 "---------------\n";
1026 outs() << "Filename Object "
1027 " dSYM Change\n";
1028 outs() << "----------------------------------------------------------------"
1029 "---------------\n";
1030
1031 // Print body.
1032 for (auto &E : Sorted) {
1033 InputTotal += E.second.Input;
1034 OutputTotal += E.second.Output;
1035 llvm::outs() << formatv(
1036 FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
1037 E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
1038 }
1039 // Print total and footer.
1040 outs() << "----------------------------------------------------------------"
1041 "---------------\n";
1042 llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
1043 ComputePercentange(InputTotal, OutputTotal));
1044 outs() << "----------------------------------------------------------------"
1045 "---------------\n\n";
1046}
1047
1050 TGroup.spawn([&]() { assignOffsetsToStrings(); });
1051 TGroup.spawn([&]() { assignOffsetsToSections(); });
1052}
1053
1055 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
1056 uint64_t CurDebugStrOffset =
1057 1; // start from 1 to take into account zero entry.
1058 size_t CurDebugLineStrIndex = 0;
1059 uint64_t CurDebugLineStrOffset = 0;
1060
1061 // Enumerates all strings, add them into the DwarfStringPoolEntry map,
1062 // assign offset and index to the string if it is not indexed yet.
1064 const StringEntry *String) {
1065 switch (Kind) {
1068 assert(Entry != nullptr);
1069
1070 if (!Entry->isIndexed()) {
1071 Entry->Offset = CurDebugStrOffset;
1072 CurDebugStrOffset += Entry->String.size() + 1;
1073 Entry->Index = CurDebugStrIndex++;
1074 }
1075 } break;
1079 assert(Entry != nullptr);
1080
1081 if (!Entry->isIndexed()) {
1082 Entry->Offset = CurDebugLineStrOffset;
1083 CurDebugLineStrOffset += Entry->String.size() + 1;
1084 Entry->Index = CurDebugLineStrIndex++;
1085 }
1086 } break;
1087 }
1088 });
1089}
1090
1092 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
1093
1094 forEachObjectSectionsSet([&](OutputSections &UnitSections) {
1095 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
1096 });
1097}
1098
1101 StringHandler) {
1102 // To save space we do not create any separate string table.
1103 // We use already allocated string patches and accelerator entries:
1104 // enumerate them in natural order and assign offsets.
1105 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
1106 // sections in the same order as they were assigned offsets.
1108 CU->forEach([&](SectionDescriptor &OutSection) {
1109 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1110 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1111 });
1112
1113 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1114 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1115 });
1116 });
1117
1118 CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
1119 StringHandler(DebugStr, Info.String);
1120 });
1121 });
1122
1123 if (ArtificialTypeUnit != nullptr) {
1124 ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
1125 OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
1126 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1127 });
1128
1129 OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
1130 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1131 });
1132
1133 OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
1134 if (Patch.Die == nullptr)
1135 return;
1136
1137 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
1138 if (&TypeEntry->getFinalDie() != Patch.Die)
1139 return;
1140
1141 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1142 });
1143
1144 OutSection.ListDebugTypeLineStrPatch.forEach(
1145 [&](DebugTypeLineStrPatch &Patch) {
1146 if (Patch.Die == nullptr)
1147 return;
1148
1149 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();
1150 if (&TypeEntry->getFinalDie() != Patch.Die)
1151 return;
1152
1153 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1154 });
1155 });
1156 }
1157}
1158
1160 function_ref<void(OutputSections &)> SectionsSetHandler) {
1161 // Handle artificial type unit first.
1162 if (ArtificialTypeUnit != nullptr)
1163 SectionsSetHandler(*ArtificialTypeUnit);
1164
1165 // Then all modules(before regular compilation units).
1166 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1167 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1168 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1169 SectionsSetHandler(*ModuleUnit.Unit);
1170
1171 // Finally all compilation units.
1172 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1173 // Handle object file common sections.
1174 SectionsSetHandler(*Context);
1175
1176 // Handle compilation units.
1177 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1178 if (CU->getStage() != CompileUnit::Stage::Skipped)
1179 SectionsSetHandler(*CU);
1180 }
1181}
1182
1184 function_ref<void(DwarfUnit *CU)> UnitHandler) {
1185 if (ArtificialTypeUnit != nullptr)
1186 UnitHandler(ArtificialTypeUnit.get());
1187
1188 // Enumerate module units.
1189 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1190 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1191 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1192 UnitHandler(ModuleUnit.Unit.get());
1193
1194 // Enumerate compile units.
1195 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1196 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1197 if (CU->getStage() != CompileUnit::Stage::Skipped)
1198 UnitHandler(CU.get());
1199}
1200
1202 function_ref<void(CompileUnit *CU)> UnitHandler) {
1203 // Enumerate module units.
1204 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1205 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1206 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1207 UnitHandler(ModuleUnit.Unit.get());
1208
1209 // Enumerate compile units.
1210 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1211 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1212 if (CU->getStage() != CompileUnit::Stage::Skipped)
1213 UnitHandler(CU.get());
1214}
1215
1217 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
1218 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
1219 SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
1220 ArtificialTypeUnit.get());
1221 });
1222 });
1223}
1224
1227
1228 // Create section descriptors ahead if they are not exist at the moment.
1229 // SectionDescriptors container is not thread safe. Thus we should be sure
1230 // that descriptors would not be created in following parallel tasks.
1231
1232 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
1233 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
1234
1235 if (llvm::is_contained(GlobalData.Options.AccelTables,
1237 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
1238 CommonSections.getOrCreateSectionDescriptor(
1240 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
1241 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
1242 }
1243
1244 if (llvm::is_contained(GlobalData.Options.AccelTables,
1246 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
1247
1248 // Emit .debug_str and .debug_line_str sections.
1249 TG.spawn([&]() { emitStringSections(); });
1250
1251 if (llvm::is_contained(GlobalData.Options.AccelTables,
1253 // Emit apple accelerator sections.
1254 TG.spawn([&]() {
1255 emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
1256 });
1257 }
1258
1259 if (llvm::is_contained(GlobalData.Options.AccelTables,
1261 // Emit .debug_names section.
1262 TG.spawn([&]() {
1263 emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
1264 });
1265 }
1266
1267 // Write compile units to the output file.
1268 TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
1269}
1270
1272 uint64_t DebugStrNextOffset = 0;
1273 uint64_t DebugLineStrNextOffset = 0;
1274
1275 // Emit zero length string. Accelerator tables does not work correctly
1276 // if the first string is not zero length string.
1277 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1278 .emitInplaceString("");
1279 DebugStrNextOffset++;
1280
1282 [&](StringDestinationKind Kind, const StringEntry *String) {
1283 switch (Kind) {
1285 DwarfStringPoolEntryWithExtString *StringToEmit =
1286 DebugStrStrings.getExistingEntry(String);
1287 assert(StringToEmit->isIndexed());
1288
1289 // Strings may be repeated. Use accumulated DebugStrNextOffset
1290 // to understand whether corresponding string is already emitted.
1291 // Skip string if its offset less than accumulated offset.
1292 if (StringToEmit->Offset >= DebugStrNextOffset) {
1293 DebugStrNextOffset =
1294 StringToEmit->Offset + StringToEmit->String.size() + 1;
1295 // Emit the string itself.
1296 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1297 .emitInplaceString(StringToEmit->String);
1298 }
1299 } break;
1301 DwarfStringPoolEntryWithExtString *StringToEmit =
1302 DebugLineStrStrings.getExistingEntry(String);
1303 assert(StringToEmit->isIndexed());
1304
1305 // Strings may be repeated. Use accumulated DebugLineStrStrings
1306 // to understand whether corresponding string is already emitted.
1307 // Skip string if its offset less than accumulated offset.
1308 if (StringToEmit->Offset >= DebugLineStrNextOffset) {
1309 DebugLineStrNextOffset =
1310 StringToEmit->Offset + StringToEmit->String.size() + 1;
1311 // Emit the string itself.
1313 .emitInplaceString(StringToEmit->String);
1314 }
1315 } break;
1316 }
1317 });
1318}
1319
1325
1327 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1328 uint64_t OutOffset = Info.OutOffset;
1329 switch (Info.Type) {
1331 llvm_unreachable("Unknown accelerator record");
1332 } break;
1334 AppleNamespaces.addName(
1335 *DebugStrStrings.getExistingEntry(Info.String),
1336 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1337 OutOffset);
1338 } break;
1340 AppleNames.addName(
1341 *DebugStrStrings.getExistingEntry(Info.String),
1342 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1343 OutOffset);
1344 } break;
1346 AppleObjC.addName(
1347 *DebugStrStrings.getExistingEntry(Info.String),
1348 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1349 OutOffset);
1350 } break;
1352 AppleTypes.addName(
1353 *DebugStrStrings.getExistingEntry(Info.String),
1354 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1355 OutOffset,
1356 Info.Tag,
1357 Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1358 : 0,
1359 Info.QualifiedNameHash);
1360 } break;
1361 }
1362 });
1363 });
1364
1365 {
1366 // FIXME: we use AsmPrinter to emit accelerator sections.
1367 // It might be beneficial to directly emit accelerator data
1368 // to the raw_svector_ostream.
1369 SectionDescriptor &OutSection =
1372 OutSection.OS);
1373 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1374 consumeError(std::move(Err));
1375 return;
1376 }
1377
1378 // Emit table.
1379 Emitter.emitAppleNamespaces(AppleNamespaces);
1380 Emitter.finish();
1381
1382 // Set start offset and size for output section.
1384 }
1385
1386 {
1387 // FIXME: we use AsmPrinter to emit accelerator sections.
1388 // It might be beneficial to directly emit accelerator data
1389 // to the raw_svector_ostream.
1390 SectionDescriptor &OutSection =
1391 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
1393 OutSection.OS);
1394 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1395 consumeError(std::move(Err));
1396 return;
1397 }
1398
1399 // Emit table.
1400 Emitter.emitAppleNames(AppleNames);
1401 Emitter.finish();
1402
1403 // Set start offset ans size for output section.
1405 }
1406
1407 {
1408 // FIXME: we use AsmPrinter to emit accelerator sections.
1409 // It might be beneficial to directly emit accelerator data
1410 // to the raw_svector_ostream.
1411 SectionDescriptor &OutSection =
1412 CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
1414 OutSection.OS);
1415 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1416 consumeError(std::move(Err));
1417 return;
1418 }
1419
1420 // Emit table.
1421 Emitter.emitAppleObjc(AppleObjC);
1422 Emitter.finish();
1423
1424 // Set start offset ans size for output section.
1426 }
1427
1428 {
1429 // FIXME: we use AsmPrinter to emit accelerator sections.
1430 // It might be beneficial to directly emit accelerator data
1431 // to the raw_svector_ostream.
1432 SectionDescriptor &OutSection =
1433 CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
1435 OutSection.OS);
1436 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1437 consumeError(std::move(Err));
1438 return;
1439 }
1440
1441 // Emit table.
1442 Emitter.emitAppleTypes(AppleTypes);
1443 Emitter.finish();
1444
1445 // Set start offset ans size for output section.
1447 }
1448}
1449
1451 std::unique_ptr<DWARF5AccelTable> DebugNames;
1452
1453 DebugNamesUnitsOffsets CompUnits;
1454 CompUnitIDToIdx CUidToIdx;
1455
1456 unsigned Id = 0;
1457
1459 bool HasRecords = false;
1460 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1461 if (DebugNames == nullptr)
1462 DebugNames = std::make_unique<DWARF5AccelTable>();
1463
1464 HasRecords = true;
1465 switch (Info.Type) {
1469 DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1470 Info.OutOffset, Info.ParentOffset, Info.Tag,
1471 CU->getUniqueID(),
1472 CU->getTag() == dwarf::DW_TAG_type_unit);
1473 } break;
1474
1475 default:
1476 break; // Nothing to do.
1477 };
1478 });
1479
1480 if (HasRecords) {
1481 CompUnits.push_back(
1482 CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
1483 .StartOffset);
1484 CUidToIdx[CU->getUniqueID()] = Id++;
1485 }
1486 });
1487
1488 if (DebugNames != nullptr) {
1489 // FIXME: we use AsmPrinter to emit accelerator sections.
1490 // It might be beneficial to directly emit accelerator data
1491 // to the raw_svector_ostream.
1492 SectionDescriptor &OutSection =
1493 CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
1495 OutSection.OS);
1496 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1497 consumeError(std::move(Err));
1498 return;
1499 }
1500
1501 // Emit table.
1502 Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
1503 Emitter.finish();
1504
1505 // Set start offset ans size for output section.
1507 }
1508}
1509
1511 GlobalData.getStringPool().clear();
1512 DebugStrStrings.clear();
1513 DebugLineStrStrings.clear();
1514}
1515
1517 // Enumerate all sections and store them into the final emitter.
1519 Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1520 // Emit section content.
1521 SectionHandler(OutSection);
1522 });
1523 });
1524}
1525
1527 CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1528 SectionHandler(OutSection);
1529 });
1530}
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 const DWARFSection & getFrameSection() const
Definition DWARFObject.h:44
virtual uint8_t getAddressSize() const
Definition DWARFObject.h:35
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:205
Implements a dense probed hash-table based set.
Definition DenseSet.h:279
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
iterator end()
Definition StringMap.h:224
iterator find(StringRef Key)
Definition StringMap.h:237
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition StringMap.h:381
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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
Check if the string is empty.
Definition StringRef.h:141
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Definition StringRef.h:138
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
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
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::map< std::string, std::string > SwiftInterfacesMapTy
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),...
const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind) const
Returns descriptor for the specified section of SectionKind.
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.
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1023
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:44
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:874
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
Section + local offset of a .debug_frame CIE that has been (or will be) emitted by some LinkContext.
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 ...
Error scanFrameData()
Parse this context's input .debug_frame into FrameScan.
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.
void registerCIEs(CIERegistry &CIEs)
Register this context's CIEs with the linker-wide registry.
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.
Error emitDebugFrame(const CIERegistry &CIEs)
Emit this context's .debug_frame section.
std::atomic< size_t > & UniqueUnitID
Counter for compile units ID.
Error link(TypeUnit *ArtificialTypeUnit)
Link compile units for this context.
StringMap< CIELocation > CIERegistry
Linker-wide registry for .debug_frame CIEs.
Error unloadInput()
Unload the input DWARFContext after scanning the input .debug_frame into FrameScan.
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.
dwarf::FormParams getFormParams() const
Returns FormParams used by section.
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.