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