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