LLVM 24.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
50 CompileUnitHandlerTy OnCUDieLoaded) {
51 ObjectContexts.emplace_back(std::make_unique<LinkContext>(
53
54 if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
55 for (const std::unique_ptr<DWARFUnit> &CU :
56 ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
57 DWARFDie CUDie = CU->getUnitDIE();
58
59 if (!CUDie)
60 continue;
61
62 OnCUDieLoaded(*CU);
63
64 // Register mofule reference.
65 if (!GlobalData.getOptions().UpdateIndexTablesOnly)
66 ObjectContexts.back()->registerModuleReference(CUDie, Loader,
67 OnCUDieLoaded);
68 }
69 }
70}
71
73 ObjectContexts.reserve(ObjFilesNum);
74}
75
77 // UniqueUnitID is initialized by the constructor and must not be reset
78 // here. addObjectFile() may have already handed out IDs to clang module
79 // CUs loaded from .pcm files, and the IDs handed out below must stay
80 // disjoint from those.
81
83 return Err;
84
85 dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
88
89 if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
90 GlobalData.getTargetTriple()) {
91 GlobalEndianness = (*CurTriple).get().isLittleEndian()
94 }
95 std::optional<uint16_t> Language;
96
97 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
98 if (Context->InputDWARFFile.Dwarf == nullptr) {
99 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
100 continue;
101 }
102
103 if (GlobalData.getOptions().Verbose) {
104 outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
105 << "\n";
106
107 for (const std::unique_ptr<DWARFUnit> &OrigCU :
108 Context->InputDWARFFile.Dwarf->compile_units()) {
109 outs() << "Input compilation unit:";
110 DIDumpOptions DumpOpts;
111 DumpOpts.ChildRecurseDepth = 0;
112 DumpOpts.Verbose = GlobalData.getOptions().Verbose;
113 OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
114 }
115 }
116
117 // Verify input DWARF if requested.
118 if (GlobalData.getOptions().VerifyInputDWARF)
119 verifyInput(Context->InputDWARFFile);
120
121 if (!GlobalData.getTargetTriple())
122 GlobalEndianness = Context->getEndianness();
123 GlobalFormat.AddrSize =
124 std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
125
126 Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
127
128 // FIXME: move creation of CompileUnits into the addObjectFile.
129 // This would allow to not scan for context Language and Modules state
130 // twice. And then following handling might be removed.
131 for (const std::unique_ptr<DWARFUnit> &OrigCU :
132 Context->InputDWARFFile.Dwarf->compile_units()) {
133 DWARFDie UnitDie = OrigCU->getUnitDIE();
134
135 if (!Language) {
136 if (std::optional<uint64_t> LangVal = UnitDie.getLanguage())
137 if (isODRLanguage(*LangVal))
138 Language = static_cast<uint16_t>(*LangVal);
139 }
140 }
141
142 // Clang module units decide their ODR availability from their own
143 // language, so they have to be part of this scan as well. A module unit
144 // can be the only ODR unit of a link, and any unit which deduplicates
145 // types requires the artificial type unit to exist.
146 for (const std::unique_ptr<CompileUnit> &Module :
147 Context->ModulesCompileUnits) {
148 if (!Language) {
149 if (std::optional<uint16_t> LangVal = Module->getLanguage())
150 if (isODRLanguage(*LangVal))
151 Language = *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 (std::unique_ptr<CompileUnit> &ModuleUnit :
214 Context->ModulesCompileUnits)
215 ModuleUnit->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(std::move(Unit));
474 // Preload line table, as it can't be loaded asynchronously.
475 ModulesCompileUnits.back()->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 (std::unique_ptr<CompileUnit> &Mod : ModulesCompileUnits) {
493 if (Error E = Mod->setPriority(ObjectFileIdx, LocalCUIdx++))
494 return E;
495 }
496
497 // Link modules compile units first.
498 parallelForEach(ModulesCompileUnits, [&](std::unique_ptr<CompileUnit> &Mod) {
499 // A module unit describes DIEs which no address reaches, so nothing marks
500 // it inter-connected and the inter-connected loops below, which iterate
501 // CompileUnits alone, would never advance it.
502 assert(!Mod->isInterconnectedCU() && "module unit is inter-connected");
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.getContainingFile().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 (std::unique_ptr<CompileUnit> &ModuleUnit :
1173 Context->ModulesCompileUnits)
1174 if (ModuleUnit->getStage() != CompileUnit::Stage::Skipped)
1175 SectionsSetHandler(*ModuleUnit);
1176
1177 // Finally all compilation units.
1178 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1179 // Handle object file common sections.
1180 SectionsSetHandler(*Context);
1181
1182 // Handle compilation units.
1183 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1184 if (CU->getStage() != CompileUnit::Stage::Skipped)
1185 SectionsSetHandler(*CU);
1186 }
1187}
1188
1190 function_ref<void(DwarfUnit *CU)> UnitHandler) {
1191 if (ArtificialTypeUnit != nullptr)
1192 UnitHandler(ArtificialTypeUnit.get());
1193
1194 // Enumerate module units.
1195 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1196 for (std::unique_ptr<CompileUnit> &ModuleUnit :
1197 Context->ModulesCompileUnits)
1198 if (ModuleUnit->getStage() != CompileUnit::Stage::Skipped)
1199 UnitHandler(ModuleUnit.get());
1200
1201 // Enumerate compile units.
1202 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1203 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1204 if (CU->getStage() != CompileUnit::Stage::Skipped)
1205 UnitHandler(CU.get());
1206}
1207
1209 function_ref<void(CompileUnit *CU)> UnitHandler) {
1210 // Enumerate module units.
1211 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1212 for (std::unique_ptr<CompileUnit> &ModuleUnit :
1213 Context->ModulesCompileUnits)
1214 if (ModuleUnit->getStage() != CompileUnit::Stage::Skipped)
1215 UnitHandler(ModuleUnit.get());
1216
1217 // Enumerate compile units.
1218 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1219 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1220 if (CU->getStage() != CompileUnit::Stage::Skipped)
1221 UnitHandler(CU.get());
1222}
1223
1225 forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
1226 SectionsSet.forEach([&](SectionDescriptor &OutSection) {
1227 SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
1228 ArtificialTypeUnit.get());
1229 });
1230 });
1231}
1232
1235
1236 // Create section descriptors ahead if they are not exist at the moment.
1237 // SectionDescriptors container is not thread safe. Thus we should be sure
1238 // that descriptors would not be created in following parallel tasks.
1239
1240 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
1241 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
1242
1243 if (llvm::is_contained(GlobalData.Options.AccelTables,
1245 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
1246 CommonSections.getOrCreateSectionDescriptor(
1248 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
1249 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
1250 }
1251
1252 if (llvm::is_contained(GlobalData.Options.AccelTables,
1254 CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
1255
1256 // Emit .debug_str and .debug_line_str sections.
1257 TG.spawn([&]() { emitStringSections(); });
1258
1259 if (llvm::is_contained(GlobalData.Options.AccelTables,
1261 // Emit apple accelerator sections.
1262 TG.spawn([&]() {
1263 emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
1264 });
1265 }
1266
1267 if (llvm::is_contained(GlobalData.Options.AccelTables,
1269 // Emit .debug_names section.
1270 TG.spawn([&]() {
1271 emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
1272 });
1273 }
1274
1275 // Write compile units to the output file.
1276 TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
1277}
1278
1280 uint64_t DebugStrNextOffset = 0;
1281 uint64_t DebugLineStrNextOffset = 0;
1282
1283 // Emit zero length string. Accelerator tables does not work correctly
1284 // if the first string is not zero length string.
1285 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1286 .emitInplaceString("");
1287 DebugStrNextOffset++;
1288
1290 [&](StringDestinationKind Kind, const StringEntry *String) {
1291 switch (Kind) {
1293 DwarfStringPoolEntryWithExtString *StringToEmit =
1294 DebugStrStrings.getExistingEntry(String);
1295 assert(StringToEmit->isIndexed());
1296
1297 // Strings may be repeated. Use accumulated DebugStrNextOffset
1298 // to understand whether corresponding string is already emitted.
1299 // Skip string if its offset less than accumulated offset.
1300 if (StringToEmit->Offset >= DebugStrNextOffset) {
1301 DebugStrNextOffset =
1302 StringToEmit->Offset + StringToEmit->String.size() + 1;
1303 // Emit the string itself.
1304 CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
1305 .emitInplaceString(StringToEmit->String);
1306 }
1307 } break;
1309 DwarfStringPoolEntryWithExtString *StringToEmit =
1310 DebugLineStrStrings.getExistingEntry(String);
1311 assert(StringToEmit->isIndexed());
1312
1313 // Strings may be repeated. Use accumulated DebugLineStrStrings
1314 // to understand whether corresponding string is already emitted.
1315 // Skip string if its offset less than accumulated offset.
1316 if (StringToEmit->Offset >= DebugLineStrNextOffset) {
1317 DebugLineStrNextOffset =
1318 StringToEmit->Offset + StringToEmit->String.size() + 1;
1319 // Emit the string itself.
1321 .emitInplaceString(StringToEmit->String);
1322 }
1323 } break;
1324 }
1325 });
1326}
1327
1333
1335 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1336 uint64_t OutOffset = Info.OutOffset;
1337 switch (Info.Type) {
1339 llvm_unreachable("Unknown accelerator record");
1340 } break;
1342 AppleNamespaces.addName(
1343 *DebugStrStrings.getExistingEntry(Info.String),
1344 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1345 OutOffset);
1346 } break;
1348 AppleNames.addName(
1349 *DebugStrStrings.getExistingEntry(Info.String),
1350 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1351 OutOffset);
1352 } break;
1354 AppleObjC.addName(
1355 *DebugStrStrings.getExistingEntry(Info.String),
1356 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1357 OutOffset);
1358 } break;
1360 AppleTypes.addName(
1361 *DebugStrStrings.getExistingEntry(Info.String),
1362 CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
1363 OutOffset,
1364 Info.Tag,
1365 Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1366 : 0,
1367 Info.QualifiedNameHash);
1368 } break;
1369 }
1370 });
1371 });
1372
1373 {
1374 // FIXME: we use AsmPrinter to emit accelerator sections.
1375 // It might be beneficial to directly emit accelerator data
1376 // to the raw_svector_ostream.
1377 SectionDescriptor &OutSection =
1380 OutSection.OS);
1381 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1382 consumeError(std::move(Err));
1383 return;
1384 }
1385
1386 // Emit table.
1387 Emitter.emitAppleNamespaces(AppleNamespaces);
1388 Emitter.finish();
1389
1390 // Set start offset and size for output section.
1392 }
1393
1394 {
1395 // FIXME: we use AsmPrinter to emit accelerator sections.
1396 // It might be beneficial to directly emit accelerator data
1397 // to the raw_svector_ostream.
1398 SectionDescriptor &OutSection =
1399 CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
1401 OutSection.OS);
1402 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1403 consumeError(std::move(Err));
1404 return;
1405 }
1406
1407 // Emit table.
1408 Emitter.emitAppleNames(AppleNames);
1409 Emitter.finish();
1410
1411 // Set start offset ans size for output section.
1413 }
1414
1415 {
1416 // FIXME: we use AsmPrinter to emit accelerator sections.
1417 // It might be beneficial to directly emit accelerator data
1418 // to the raw_svector_ostream.
1419 SectionDescriptor &OutSection =
1420 CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
1422 OutSection.OS);
1423 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1424 consumeError(std::move(Err));
1425 return;
1426 }
1427
1428 // Emit table.
1429 Emitter.emitAppleObjc(AppleObjC);
1430 Emitter.finish();
1431
1432 // Set start offset ans size for output section.
1434 }
1435
1436 {
1437 // FIXME: we use AsmPrinter to emit accelerator sections.
1438 // It might be beneficial to directly emit accelerator data
1439 // to the raw_svector_ostream.
1440 SectionDescriptor &OutSection =
1441 CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
1443 OutSection.OS);
1444 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1445 consumeError(std::move(Err));
1446 return;
1447 }
1448
1449 // Emit table.
1450 Emitter.emitAppleTypes(AppleTypes);
1451 Emitter.finish();
1452
1453 // Set start offset ans size for output section.
1455 }
1456}
1457
1459 std::unique_ptr<DWARF5AccelTable> DebugNames;
1460
1461 DebugNamesUnitsOffsets CompUnits;
1462 CompUnitIDToIdx CUidToIdx;
1463
1464 unsigned Id = 0;
1465
1467 bool HasRecords = false;
1468 CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1469 if (DebugNames == nullptr)
1470 DebugNames = std::make_unique<DWARF5AccelTable>();
1471
1472 HasRecords = true;
1473 switch (Info.Type) {
1477 DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1478 Info.OutOffset, Info.ParentOffset, Info.Tag,
1479 CU->getUniqueID(),
1480 CU->getTag() == dwarf::DW_TAG_type_unit);
1481 } break;
1482
1483 default:
1484 break; // Nothing to do.
1485 };
1486 });
1487
1488 if (HasRecords) {
1489 CompUnits.push_back(
1490 CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
1491 .StartOffset);
1492 CUidToIdx[CU->getUniqueID()] = Id++;
1493 }
1494 });
1495
1496 if (DebugNames != nullptr) {
1497 // FIXME: we use AsmPrinter to emit accelerator sections.
1498 // It might be beneficial to directly emit accelerator data
1499 // to the raw_svector_ostream.
1500 SectionDescriptor &OutSection =
1501 CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
1503 OutSection.OS);
1504 if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
1505 consumeError(std::move(Err));
1506 return;
1507 }
1508
1509 // Emit table.
1510 Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
1511 Emitter.finish();
1512
1513 // Set start offset ans size for output section.
1515 }
1516}
1517
1519 GlobalData.getStringPool().clear();
1520 DebugStrStrings.clear();
1521 DebugLineStrStrings.clear();
1522}
1523
1525 // Enumerate all sections and store them into the final emitter.
1527 Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1528 // Emit section content.
1529 SectionHandler(OutSection);
1530 });
1531 });
1532}
1533
1535 CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1536 SectionHandler(OutSection);
1537 });
1538}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
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:48
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:244
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:1062
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:1036
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
void call_once(once_flag &flag, Function &&F, Args &&... ArgList)
Execute the function specified as a parameter once.
Definition Threading.h:86
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:209
endianness
Definition bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
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:1199
Section + local offset of a .debug_frame CIE that has been (or will be) emitted by some LinkContext.
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 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.
UnitListTy ModulesCompileUnits
Set of Compile Units for modules.
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
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