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