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