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