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"
11#include "llvm/DWARFLinker/Utils.h"
12#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
13#include "llvm/Support/FormatVariadic.h"
14#include "llvm/Support/Parallel.h"
15#include "llvm/Support/ThreadPool.h"
16
17using namespace llvm;
18using namespace dwarf_linker;
19using namespace dwarf_linker::parallel;
20
21DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
22 MessageHandlerTy WarningHandler)
23 : UniqueUnitID(0), DebugStrStrings(GlobalData),
24 DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {
25 GlobalData.setErrorHandler(ErrorHandler);
26 GlobalData.setWarningHandler(WarningHandler);
27}
28
29DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,
30 DWARFFile &File,
31 StringMap<uint64_t> &ClangModules,
32 std::atomic<size_t> &UniqueUnitID)
33 : OutputSections(GlobalData), InputDWARFFile(File),
34 ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) {
35
36 if (File.Dwarf) {
37 if (!File.Dwarf->compile_units().empty())
38 CompileUnits.reserve(N: File.Dwarf->getNumCompileUnits());
39
40 // Set context format&endianness based on the input file.
41 Format.Version = File.Dwarf->getMaxVersion();
42 Format.AddrSize = File.Dwarf->getCUAddrSize();
43 Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
44 : llvm::endianness::big;
45 }
46}
47
48DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
49 DWARFFile &File, std::unique_ptr<CompileUnit> Unit)
50 : File(File), Unit(std::move(Unit)) {}
51
52DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
53 LinkContext::RefModuleUnit &&Other)
54 : File(Other.File), Unit(std::move(Other.Unit)) {}
55
56void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(
57 LinkContext::RefModuleUnit &&Unit) {
58 ModulesCompileUnits.emplace_back(Args: std::move(Unit));
59}
60
61void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
62 CompileUnitHandlerTy OnCUDieLoaded) {
63 ObjectContexts.emplace_back(Args: std::make_unique<LinkContext>(
64 args&: GlobalData, args&: File, args&: ClangModules, args&: UniqueUnitID));
65
66 if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
67 for (const std::unique_ptr<DWARFUnit> &CU :
68 ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
69 DWARFDie CUDie = CU->getUnitDIE();
70 OverallNumberOfCU++;
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
85void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
86 ObjectContexts.reserve(N: ObjFilesNum);
87}
88
89Error DWARFLinkerImpl::link() {
90 // reset compile unit unique ID counter.
91 UniqueUnitID = 0;
92
93 if (Error Err = validateAndUpdateOptions())
94 return Err;
95
96 dwarf::FormParams GlobalFormat = {.Version: GlobalData.getOptions().TargetDWARFVersion,
97 .AddrSize: 0, .Format: dwarf::DwarfFormat::DWARF32};
98 llvm::endianness GlobalEndianness = llvm::endianness::native;
99
100 if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
101 GlobalData.getTargetTriple()) {
102 GlobalEndianness = (*CurTriple).get().isLittleEndian()
103 ? llvm::endianness::little
104 : llvm::endianness::big;
105 }
106 std::optional<uint16_t> Language;
107
108 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
109 if (Context->InputDWARFFile.Dwarf == nullptr) {
110 Context->setOutputFormat(Format: Context->getFormParams(), Endianness: GlobalEndianness);
111 continue;
112 }
113
114 if (GlobalData.getOptions().Verbose) {
115 outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
116 << "\n";
117
118 for (const std::unique_ptr<DWARFUnit> &OrigCU :
119 Context->InputDWARFFile.Dwarf->compile_units()) {
120 outs() << "Input compilation unit:";
121 DIDumpOptions DumpOpts;
122 DumpOpts.ChildRecurseDepth = 0;
123 DumpOpts.Verbose = GlobalData.getOptions().Verbose;
124 OrigCU->getUnitDIE().dump(OS&: outs(), indent: 0, DumpOpts);
125 }
126 }
127
128 // Verify input DWARF if requested.
129 if (GlobalData.getOptions().VerifyInputDWARF)
130 verifyInput(File: Context->InputDWARFFile);
131
132 if (!GlobalData.getTargetTriple())
133 GlobalEndianness = Context->getEndianness();
134 GlobalFormat.AddrSize =
135 std::max(a: GlobalFormat.AddrSize, b: Context->getFormParams().AddrSize);
136
137 Context->setOutputFormat(Format: Context->getFormParams(), Endianness: GlobalEndianness);
138
139 // FIXME: move creation of CompileUnits into the addObjectFile.
140 // This would allow to not scan for context Language and Modules state
141 // twice. And then following handling might be removed.
142 for (const std::unique_ptr<DWARFUnit> &OrigCU :
143 Context->InputDWARFFile.Dwarf->compile_units()) {
144 DWARFDie UnitDie = OrigCU->getUnitDIE();
145
146 if (!Language) {
147 if (std::optional<DWARFFormValue> Val =
148 UnitDie.find(Attr: dwarf::DW_AT_language)) {
149 uint16_t LangVal = dwarf::toUnsigned(V: Val, Default: 0);
150 if (isODRLanguage(Language: LangVal))
151 Language = LangVal;
152 }
153 }
154 }
155 }
156
157 if (GlobalFormat.AddrSize == 0) {
158 if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
159 GlobalData.getTargetTriple())
160 GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
161 else
162 GlobalFormat.AddrSize = 8;
163 }
164
165 CommonSections.setOutputFormat(Format: GlobalFormat, Endianness: GlobalEndianness);
166
167 if (!GlobalData.Options.NoODR && Language.has_value()) {
168 llvm::parallel::TaskGroup TGroup;
169 TGroup.spawn(f: [&]() {
170 ArtificialTypeUnit = std::make_unique<TypeUnit>(
171 args&: GlobalData, args: UniqueUnitID++, args&: Language, args&: GlobalFormat, args&: GlobalEndianness);
172 });
173 }
174
175 // Set parallel options.
176 if (GlobalData.getOptions().Threads == 0)
177 llvm::parallel::strategy = optimal_concurrency(TaskCount: OverallNumberOfCU);
178 else
179 llvm::parallel::strategy =
180 hardware_concurrency(ThreadCount: GlobalData.getOptions().Threads);
181
182 // Link object files.
183 if (GlobalData.getOptions().Threads == 1) {
184 for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
185 // Link object file.
186 if (Error Err = Context->link(ArtificialTypeUnit: ArtificialTypeUnit.get()))
187 GlobalData.error(Err: std::move(Err), Context: Context->InputDWARFFile.FileName);
188
189 Context->InputDWARFFile.unload();
190 }
191 } else {
192 DefaultThreadPool Pool(llvm::parallel::strategy);
193 for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
194 Pool.async(F: [&]() {
195 // Link object file.
196 if (Error Err = Context->link(ArtificialTypeUnit: ArtificialTypeUnit.get()))
197 GlobalData.error(Err: std::move(Err), Context: Context->InputDWARFFile.FileName);
198
199 Context->InputDWARFFile.unload();
200 });
201
202 Pool.wait();
203 }
204
205 if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()
206 .getRoot()
207 ->getValue()
208 .load()
209 ->Children.empty()) {
210 if (GlobalData.getTargetTriple().has_value())
211 if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(
212 TargetTriple: (*GlobalData.getTargetTriple()).get()))
213 return Err;
214 }
215
216 // At this stage each compile units are cloned to their own set of debug
217 // sections. Now, update patches, assign offsets and assemble final file
218 // glueing debug tables from each compile unit.
219 glueCompileUnitsAndWriteToTheOutput();
220
221 return Error::success();
222}
223
224void DWARFLinkerImpl::verifyInput(const DWARFFile &File) {
225 assert(File.Dwarf);
226
227 std::string Buffer;
228 raw_string_ostream OS(Buffer);
229 DIDumpOptions DumpOpts;
230 if (!File.Dwarf->verify(OS, DumpOpts: DumpOpts.noImplicitRecursion())) {
231 if (GlobalData.getOptions().InputVerificationHandler)
232 GlobalData.getOptions().InputVerificationHandler(File, OS.str());
233 }
234}
235
236Error DWARFLinkerImpl::validateAndUpdateOptions() {
237 if (GlobalData.getOptions().TargetDWARFVersion == 0)
238 return createStringError(EC: std::errc::invalid_argument,
239 Fmt: "target DWARF version is not set");
240
241 if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
242 GlobalData.Options.Threads = 1;
243 GlobalData.warn(
244 Warning: "set number of threads to 1 to make --verbose to work properly.", Context: "");
245 }
246
247 // Do not do types deduplication in case --update.
248 if (GlobalData.getOptions().UpdateIndexTablesOnly &&
249 !GlobalData.Options.NoODR)
250 GlobalData.Options.NoODR = true;
251
252 return Error::success();
253}
254
255/// Resolve the relative path to a build artifact referenced by DWARF by
256/// applying DW_AT_comp_dir.
257static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
258 sys::path::append(path&: Buf, a: dwarf::toString(V: CU.find(Attr: dwarf::DW_AT_comp_dir), Default: ""));
259}
260
261static uint64_t getDwoId(const DWARFDie &CUDie) {
262 auto DwoId = dwarf::toUnsigned(
263 V: CUDie.find(Attrs: {dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
264 if (DwoId)
265 return *DwoId;
266 return 0;
267}
268
269static std::string
270remapPath(StringRef Path,
271 const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
272 if (ObjectPrefixMap.empty())
273 return Path.str();
274
275 SmallString<256> p = Path;
276 for (const auto &Entry : ObjectPrefixMap)
277 if (llvm::sys::path::replace_path_prefix(Path&: p, OldPrefix: Entry.first, NewPrefix: Entry.second))
278 break;
279 return p.str().str();
280}
281
282static std::string getPCMFile(const DWARFDie &CUDie,
283 DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
284 std::string PCMFile = dwarf::toString(
285 V: CUDie.find(Attrs: {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), Default: "");
286
287 if (PCMFile.empty())
288 return PCMFile;
289
290 if (ObjectPrefixMap)
291 PCMFile = remapPath(Path: PCMFile, ObjectPrefixMap: *ObjectPrefixMap);
292
293 return PCMFile;
294}
295
296std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(
297 const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
298 if (PCMFile.empty())
299 return std::make_pair(x: false, y: false);
300
301 // Clang module DWARF skeleton CUs abuse this for the path to the module.
302 uint64_t DwoId = getDwoId(CUDie);
303
304 std::string Name = dwarf::toString(V: CUDie.find(Attr: dwarf::DW_AT_name), Default: "");
305 if (Name.empty()) {
306 if (!Quiet)
307 GlobalData.warn(Warning: "anonymous module skeleton CU for " + PCMFile + ".",
308 Context: InputDWARFFile.FileName);
309 return std::make_pair(x: true, y: true);
310 }
311
312 if (!Quiet && GlobalData.getOptions().Verbose) {
313 outs().indent(NumSpaces: Indent);
314 outs() << "Found clang module reference " << PCMFile;
315 }
316
317 auto Cached = ClangModules.find(Key: PCMFile);
318 if (Cached != ClangModules.end()) {
319 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
320 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
321 // ASTFileSignatures will change randomly when a module is rebuilt.
322 if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
323 GlobalData.warn(
324 Warning: Twine("hash mismatch: this object file was built against a "
325 "different version of the module ") +
326 PCMFile + ".",
327 Context: InputDWARFFile.FileName);
328 if (!Quiet && GlobalData.getOptions().Verbose)
329 outs() << " [cached].\n";
330 return std::make_pair(x: true, y: true);
331 }
332
333 return std::make_pair(x: true, y: false);
334}
335
336/// If this compile unit is really a skeleton CU that points to a
337/// clang module, register it in ClangModules and return true.
338///
339/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
340/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
341/// hash.
342bool DWARFLinkerImpl::LinkContext::registerModuleReference(
343 const DWARFDie &CUDie, ObjFileLoaderTy Loader,
344 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
345 std::string PCMFile =
346 getPCMFile(CUDie, ObjectPrefixMap: GlobalData.getOptions().ObjectPrefixMap);
347 std::pair<bool, bool> IsClangModuleRef =
348 isClangModuleRef(CUDie, PCMFile, Indent, Quiet: false);
349
350 if (!IsClangModuleRef.first)
351 return false;
352
353 if (IsClangModuleRef.second)
354 return true;
355
356 if (GlobalData.getOptions().Verbose)
357 outs() << " ...\n";
358
359 // Cyclic dependencies are disallowed by Clang, but we still
360 // shouldn't run into an infinite loop, so mark it as processed now.
361 ClangModules.insert(KV: {PCMFile, getDwoId(CUDie)});
362
363 if (Error E =
364 loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent: Indent + 2)) {
365 consumeError(Err: std::move(E));
366 return false;
367 }
368 return true;
369}
370
371Error DWARFLinkerImpl::LinkContext::loadClangModule(
372 ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
373 CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
374
375 uint64_t DwoId = getDwoId(CUDie);
376 std::string ModuleName = dwarf::toString(V: CUDie.find(Attr: dwarf::DW_AT_name), Default: "");
377
378 /// Using a SmallString<0> because loadClangModule() is recursive.
379 SmallString<0> Path(GlobalData.getOptions().PrependPath);
380 if (sys::path::is_relative(path: PCMFile))
381 resolveRelativeObjectPath(Buf&: Path, CU: CUDie);
382 sys::path::append(path&: Path, a: PCMFile);
383 // Don't use the cached binary holder because we have no thread-safety
384 // guarantee and the lifetime is limited.
385
386 if (Loader == nullptr) {
387 GlobalData.error(Err: "cann't load clang module: loader is not specified.",
388 Context: InputDWARFFile.FileName);
389 return Error::success();
390 }
391
392 auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
393 if (!ErrOrObj)
394 return Error::success();
395
396 std::unique_ptr<CompileUnit> Unit;
397 for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
398 OnCUDieLoaded(*CU);
399 // Recursively get all modules imported by this one.
400 auto ChildCUDie = CU->getUnitDIE();
401 if (!ChildCUDie)
402 continue;
403 if (!registerModuleReference(CUDie: ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
404 if (Unit) {
405 std::string Err =
406 (PCMFile +
407 ": Clang modules are expected to have exactly 1 compile unit.\n");
408 GlobalData.error(Err, Context: InputDWARFFile.FileName);
409 return make_error<StringError>(Args&: Err, Args: inconvertibleErrorCode());
410 }
411 // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
412 // fixed in clang, only warn about DWO_id mismatches in verbose mode.
413 // ASTFileSignatures will change randomly when a module is rebuilt.
414 uint64_t PCMDwoId = getDwoId(CUDie: ChildCUDie);
415 if (PCMDwoId != DwoId) {
416 if (GlobalData.getOptions().Verbose)
417 GlobalData.warn(
418 Warning: Twine("hash mismatch: this object file was built against a "
419 "different version of the module ") +
420 PCMFile + ".",
421 Context: InputDWARFFile.FileName);
422 // Update the cache entry with the DwoId of the module loaded from disk.
423 ClangModules[PCMFile] = PCMDwoId;
424 }
425
426 // Empty modules units should not be cloned.
427 if (!ChildCUDie.hasChildren())
428 continue;
429
430 // Add this module.
431 Unit = std::make_unique<CompileUnit>(
432 args&: GlobalData, args&: *CU, args: UniqueUnitID.fetch_add(i: 1), args&: ModuleName, args&: *ErrOrObj,
433 args&: getUnitForOffset, args: CU->getFormParams(), args: getEndianness());
434 }
435 }
436
437 if (Unit) {
438 ModulesCompileUnits.emplace_back(Args: RefModuleUnit{*ErrOrObj, std::move(Unit)});
439 // Preload line table, as it can't be loaded asynchronously.
440 ModulesCompileUnits.back().Unit->loadLineTable();
441 }
442
443 return Error::success();
444}
445
446Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
447 InterCUProcessingStarted = false;
448 if (!InputDWARFFile.Dwarf)
449 return Error::success();
450
451 // Preload macro tables, as they can't be loaded asynchronously.
452 InputDWARFFile.Dwarf->getDebugMacinfo();
453 InputDWARFFile.Dwarf->getDebugMacro();
454
455 // Link modules compile units first.
456 parallelForEach(R&: ModulesCompileUnits, Fn: [&](RefModuleUnit &RefModule) {
457 linkSingleCompileUnit(CU&: *RefModule.Unit, ArtificialTypeUnit);
458 });
459
460 // Check for live relocations. If there is no any live relocation then we
461 // can skip entire object file.
462 if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
463 !InputDWARFFile.Addresses->hasValidRelocs()) {
464 if (GlobalData.getOptions().Verbose)
465 outs() << "No valid relocations found. Skipping.\n";
466 return Error::success();
467 }
468
469 OriginalDebugInfoSize = getInputDebugInfoSize();
470
471 // Create CompileUnit structures to keep information about source
472 // DWARFUnit`s, load line tables.
473 for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
474 // Load only unit DIE at this stage.
475 auto CUDie = OrigCU->getUnitDIE();
476 std::string PCMFile =
477 getPCMFile(CUDie, ObjectPrefixMap: GlobalData.getOptions().ObjectPrefixMap);
478
479 // The !isClangModuleRef condition effectively skips over fully resolved
480 // skeleton units.
481 if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
482 !isClangModuleRef(CUDie, PCMFile, Indent: 0, Quiet: true).first) {
483 CompileUnits.emplace_back(Args: std::make_unique<CompileUnit>(
484 args&: GlobalData, args&: *OrigCU, args: UniqueUnitID.fetch_add(i: 1), args: "", args&: InputDWARFFile,
485 args&: getUnitForOffset, args: OrigCU->getFormParams(), args: getEndianness()));
486
487 // Preload line table, as it can't be loaded asynchronously.
488 CompileUnits.back()->loadLineTable();
489 }
490 };
491
492 HasNewInterconnectedCUs = false;
493
494 // Link self-sufficient compile units and discover inter-connected compile
495 // units.
496 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
497 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit);
498 });
499
500 // Link all inter-connected units.
501 if (HasNewInterconnectedCUs) {
502 InterCUProcessingStarted = true;
503
504 if (Error Err = finiteLoop(Iteration: [&]() -> Expected<bool> {
505 HasNewInterconnectedCUs = false;
506
507 // Load inter-connected units.
508 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
509 if (CU->isInterconnectedCU()) {
510 CU->maybeResetToLoadedStage();
511 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit,
512 DoUntilStage: CompileUnit::Stage::Loaded);
513 }
514 });
515
516 // Do liveness analysis for inter-connected units.
517 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
518 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit,
519 DoUntilStage: CompileUnit::Stage::LivenessAnalysisDone);
520 });
521
522 return HasNewInterconnectedCUs.load();
523 }))
524 return Err;
525
526 // Update dependencies.
527 if (Error Err = finiteLoop(Iteration: [&]() -> Expected<bool> {
528 HasNewGlobalDependency = false;
529 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
530 linkSingleCompileUnit(
531 CU&: *CU, ArtificialTypeUnit,
532 DoUntilStage: CompileUnit::Stage::UpdateDependenciesCompleteness);
533 });
534 return HasNewGlobalDependency.load();
535 }))
536 return Err;
537 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
538 if (CU->isInterconnectedCU() &&
539 CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
540 CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
541 });
542
543 // Assign type names.
544 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
545 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit,
546 DoUntilStage: CompileUnit::Stage::TypeNamesAssigned);
547 });
548
549 // Clone inter-connected units.
550 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
551 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit,
552 DoUntilStage: CompileUnit::Stage::Cloned);
553 });
554
555 // Update patches for inter-connected units.
556 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
557 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit,
558 DoUntilStage: CompileUnit::Stage::PatchesUpdated);
559 });
560
561 // Release data.
562 parallelForEach(R&: CompileUnits, Fn: [&](std::unique_ptr<CompileUnit> &CU) {
563 linkSingleCompileUnit(CU&: *CU, ArtificialTypeUnit,
564 DoUntilStage: CompileUnit::Stage::Cleaned);
565 });
566 }
567
568 if (GlobalData.getOptions().UpdateIndexTablesOnly) {
569 // Emit Invariant sections.
570
571 if (Error Err = emitInvariantSections())
572 return Err;
573 } else if (!CompileUnits.empty()) {
574 // Emit .debug_frame section.
575
576 Error ResultErr = Error::success();
577 llvm::parallel::TaskGroup TGroup;
578 // We use task group here as PerThreadBumpPtrAllocator should be called from
579 // the threads created by ThreadPoolExecutor.
580 TGroup.spawn(f: [&]() {
581 if (Error Err = cloneAndEmitDebugFrame())
582 ResultErr = std::move(Err);
583 });
584 return ResultErr;
585 }
586
587 return Error::success();
588}
589
590void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
591 CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
592 enum CompileUnit::Stage DoUntilStage) {
593 if (InterCUProcessingStarted != CU.isInterconnectedCU())
594 return;
595
596 if (Error Err = finiteLoop(Iteration: [&]() -> Expected<bool> {
597 if (CU.getStage() >= DoUntilStage)
598 return false;
599
600 switch (CU.getStage()) {
601 case CompileUnit::Stage::CreatedNotLoaded: {
602 // Load input compilation unit DIEs.
603 // Analyze properties of DIEs.
604 if (!CU.loadInputDIEs()) {
605 // We do not need to do liveness analysis for invalid compilation
606 // unit.
607 CU.setStage(CompileUnit::Stage::Skipped);
608 } else {
609 CU.analyzeDWARFStructure();
610
611 // The registerModuleReference() condition effectively skips
612 // over fully resolved skeleton units. This second pass of
613 // registerModuleReferences doesn't do any new work, but it
614 // will collect top-level errors, which are suppressed. Module
615 // warnings were already displayed in the first iteration.
616 if (registerModuleReference(
617 CUDie: CU.getOrigUnit().getUnitDIE(), Loader: nullptr,
618 OnCUDieLoaded: [](const DWARFUnit &) {}, Indent: 0))
619 CU.setStage(CompileUnit::Stage::PatchesUpdated);
620 else
621 CU.setStage(CompileUnit::Stage::Loaded);
622 }
623 } break;
624
625 case CompileUnit::Stage::Loaded: {
626 // Mark all the DIEs that need to be present in the generated output.
627 // If ODR requested, build type names.
628 if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
629 HasNewInterconnectedCUs)) {
630 assert(HasNewInterconnectedCUs &&
631 "Flag indicating new inter-connections is not set");
632 return false;
633 }
634
635 CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
636 } break;
637
638 case CompileUnit::Stage::LivenessAnalysisDone: {
639 if (InterCUProcessingStarted) {
640 if (CU.updateDependenciesCompleteness())
641 HasNewGlobalDependency = true;
642 return false;
643 } else {
644 if (Error Err = finiteLoop(Iteration: [&]() -> Expected<bool> {
645 return CU.updateDependenciesCompleteness();
646 }))
647 return std::move(Err);
648
649 CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
650 }
651 } break;
652
653 case CompileUnit::Stage::UpdateDependenciesCompleteness:
654#ifndef NDEBUG
655 CU.verifyDependencies();
656#endif
657
658 if (ArtificialTypeUnit) {
659 if (Error Err =
660 CU.assignTypeNames(TypePoolRef&: ArtificialTypeUnit->getTypePool()))
661 return std::move(Err);
662 }
663 CU.setStage(CompileUnit::Stage::TypeNamesAssigned);
664 break;
665
666 case CompileUnit::Stage::TypeNamesAssigned:
667 // Clone input compile unit.
668 if (CU.isClangModule() ||
669 GlobalData.getOptions().UpdateIndexTablesOnly ||
670 CU.getContaingFile().Addresses->hasValidRelocs()) {
671 if (Error Err = CU.cloneAndEmit(TargetTriple: GlobalData.getTargetTriple(),
672 ArtificialTypeUnit))
673 return std::move(Err);
674 }
675
676 CU.setStage(CompileUnit::Stage::Cloned);
677 break;
678
679 case CompileUnit::Stage::Cloned:
680 // Update DIEs referencies.
681 CU.updateDieRefPatchesWithClonedOffsets();
682 CU.setStage(CompileUnit::Stage::PatchesUpdated);
683 break;
684
685 case CompileUnit::Stage::PatchesUpdated:
686 // Cleanup resources.
687 CU.cleanupDataAfterClonning();
688 CU.setStage(CompileUnit::Stage::Cleaned);
689 break;
690
691 case CompileUnit::Stage::Cleaned:
692 assert(false);
693 break;
694
695 case CompileUnit::Stage::Skipped:
696 // Nothing to do.
697 break;
698 }
699
700 return true;
701 })) {
702 CU.error(Err: std::move(Err));
703 CU.cleanupDataAfterClonning();
704 CU.setStage(CompileUnit::Stage::Skipped);
705 }
706}
707
708Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {
709 if (!GlobalData.getTargetTriple().has_value())
710 return Error::success();
711
712 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugLoc).OS
713 << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
714 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugLocLists).OS
715 << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
716 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugRange).OS
717 << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
718 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugRngLists).OS
719 << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
720 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugARanges).OS
721 << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
722 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugFrame).OS
723 << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
724 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugAddr).OS
725 << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
726
727 return Error::success();
728}
729
730Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() {
731 if (!GlobalData.getTargetTriple().has_value())
732 return Error::success();
733
734 if (InputDWARFFile.Dwarf == nullptr)
735 return Error::success();
736
737 const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
738
739 StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
740 if (OrigFrameData.empty())
741 return Error::success();
742
743 RangesTy AllUnitsRanges;
744 for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
745 for (auto CurRange : Unit->getFunctionRanges())
746 AllUnitsRanges.insert(Range: CurRange.Range, Value: CurRange.Value);
747 }
748
749 unsigned SrcAddrSize = InputDWARFObj.getAddressSize();
750
751 SectionDescriptor &OutSection =
752 getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugFrame);
753
754 DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);
755 uint64_t InputOffset = 0;
756
757 // Store the data of the CIEs defined in this object, keyed by their
758 // offsets.
759 DenseMap<uint64_t, StringRef> LocalCIES;
760
761 /// The CIEs that have been emitted in the output section. The actual CIE
762 /// data serves a the key to this StringMap.
763 StringMap<uint32_t> EmittedCIEs;
764
765 while (Data.isValidOffset(offset: InputOffset)) {
766 uint64_t EntryOffset = InputOffset;
767 uint32_t InitialLength = Data.getU32(offset_ptr: &InputOffset);
768 if (InitialLength == 0xFFFFFFFF)
769 return createFileError(F: InputDWARFObj.getFileName(),
770 E: createStringError(EC: std::errc::invalid_argument,
771 Fmt: "Dwarf64 bits no supported"));
772
773 uint32_t CIEId = Data.getU32(offset_ptr: &InputOffset);
774 if (CIEId == 0xFFFFFFFF) {
775 // This is a CIE, store it.
776 StringRef CIEData = OrigFrameData.substr(Start: EntryOffset, N: InitialLength + 4);
777 LocalCIES[EntryOffset] = CIEData;
778 // The -4 is to account for the CIEId we just read.
779 InputOffset += InitialLength - 4;
780 continue;
781 }
782
783 uint64_t Loc = Data.getUnsigned(offset_ptr: &InputOffset, byte_size: SrcAddrSize);
784
785 // Some compilers seem to emit frame info that doesn't start at
786 // the function entry point, thus we can't just lookup the address
787 // in the debug map. Use the AddressInfo's range map to see if the FDE
788 // describes something that we can relocate.
789 std::optional<AddressRangeValuePair> Range =
790 AllUnitsRanges.getRangeThatContains(Addr: Loc);
791 if (!Range) {
792 // The +4 is to account for the size of the InitialLength field itself.
793 InputOffset = EntryOffset + InitialLength + 4;
794 continue;
795 }
796
797 // This is an FDE, and we have a mapping.
798 // Have we already emitted a corresponding CIE?
799 StringRef CIEData = LocalCIES[CIEId];
800 if (CIEData.empty())
801 return createFileError(
802 F: InputDWARFObj.getFileName(),
803 E: createStringError(EC: std::errc::invalid_argument,
804 Fmt: "Inconsistent debug_frame content. Dropping."));
805
806 uint64_t OffsetToCIERecord = OutSection.OS.tell();
807
808 // Look if we already emitted a CIE that corresponds to the
809 // referenced one (the CIE data is the key of that lookup).
810 auto IteratorInserted =
811 EmittedCIEs.insert(KV: std::make_pair(x&: CIEData, y&: OffsetToCIERecord));
812 OffsetToCIERecord = IteratorInserted.first->getValue();
813
814 // Emit CIE for this ID if it is not emitted yet.
815 if (IteratorInserted.second)
816 OutSection.OS << CIEData;
817
818 // Remember offset to the FDE record, so that we might update
819 // field referencing CIE record(containing OffsetToCIERecord),
820 // when final offsets are known. OffsetToCIERecord(which is written later)
821 // is local to the current .debug_frame section, it should be updated
822 // with final offset of the .debug_frame section.
823 OutSection.notePatch(
824 Patch: DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});
825
826 // Emit the FDE with updated address and CIE pointer.
827 // (4 + AddrSize) is the size of the CIEId + initial_location
828 // fields that will get reconstructed by emitFDE().
829 unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
830 emitFDE(CIEOffset: OffsetToCIERecord, AddrSize: SrcAddrSize, Address: Loc + Range->Value,
831 FDEBytes: OrigFrameData.substr(Start: InputOffset, N: FDERemainingBytes), Section&: OutSection);
832 InputOffset += FDERemainingBytes;
833 }
834
835 return Error::success();
836}
837
838/// Emit a FDE into the debug_frame section. \p FDEBytes
839/// contains the FDE data without the length, CIE offset and address
840/// which will be replaced with the parameter values.
841void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset,
842 uint32_t AddrSize, uint64_t Address,
843 StringRef FDEBytes,
844 SectionDescriptor &Section) {
845 Section.emitIntVal(Val: FDEBytes.size() + 4 + AddrSize, Size: 4);
846 Section.emitIntVal(Val: CIEOffset, Size: 4);
847 Section.emitIntVal(Val: Address, Size: AddrSize);
848 Section.OS.write(Ptr: FDEBytes.data(), Size: FDEBytes.size());
849}
850
851void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {
852 if (!GlobalData.getTargetTriple().has_value())
853 return;
854 assert(SectionHandler);
855
856 // Go through all object files, all compile units and assign
857 // offsets to them.
858 assignOffsets();
859
860 // Patch size/offsets fields according to the assigned CU offsets.
861 patchOffsetsAndSizes();
862
863 // Emit common sections and write debug tables from all object files/compile
864 // units into the resulting file.
865 emitCommonSectionsAndWriteCompileUnitsToTheOutput();
866
867 if (ArtificialTypeUnit != nullptr)
868 ArtificialTypeUnit.reset();
869
870 // Write common debug sections into the resulting file.
871 writeCommonSectionsToTheOutput();
872
873 // Cleanup data.
874 cleanupDataAfterDWARFOutputIsWritten();
875
876 if (GlobalData.getOptions().Statistics)
877 printStatistic();
878}
879
880void DWARFLinkerImpl::printStatistic() {
881
882 // For each object file map how many bytes were emitted.
883 StringMap<DebugInfoSize> SizeByObject;
884
885 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
886 uint64_t AllDebugInfoSectionsSize = 0;
887
888 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
889 if (std::optional<SectionDescriptor *> DebugInfo =
890 CU->tryGetSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo))
891 AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
892
893 auto &Size = SizeByObject[Context->InputDWARFFile.FileName];
894 Size.Input = Context->OriginalDebugInfoSize;
895 Size.Output = AllDebugInfoSectionsSize;
896 }
897
898 // Create a vector sorted in descending order by output size.
899 std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
900 for (auto &E : SizeByObject)
901 Sorted.emplace_back(args: E.first(), args&: E.second);
902 llvm::sort(C&: Sorted, Comp: [](auto &LHS, auto &RHS) {
903 return LHS.second.Output > RHS.second.Output;
904 });
905
906 auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
907 const float Difference = Output - Input;
908 const float Sum = Input + Output;
909 if (Sum == 0)
910 return 0;
911 return (Difference / (Sum / 2));
912 };
913
914 int64_t InputTotal = 0;
915 int64_t OutputTotal = 0;
916 const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n";
917
918 // Print header.
919 outs() << ".debug_info section size (in bytes)\n";
920 outs() << "----------------------------------------------------------------"
921 "---------------\n";
922 outs() << "Filename Object "
923 " dSYM Change\n";
924 outs() << "----------------------------------------------------------------"
925 "---------------\n";
926
927 // Print body.
928 for (auto &E : Sorted) {
929 InputTotal += E.second.Input;
930 OutputTotal += E.second.Output;
931 llvm::outs() << formatv(
932 Fmt: FormatStr, Vals: sys::path::filename(path: E.first).take_back(N: 45), Vals&: E.second.Input,
933 Vals&: E.second.Output, Vals: ComputePercentange(E.second.Input, E.second.Output));
934 }
935 // Print total and footer.
936 outs() << "----------------------------------------------------------------"
937 "---------------\n";
938 llvm::outs() << formatv(Fmt: FormatStr, Vals: "Total", Vals&: InputTotal, Vals&: OutputTotal,
939 Vals: ComputePercentange(InputTotal, OutputTotal));
940 outs() << "----------------------------------------------------------------"
941 "---------------\n\n";
942}
943
944void DWARFLinkerImpl::assignOffsets() {
945 llvm::parallel::TaskGroup TGroup;
946 TGroup.spawn(f: [&]() { assignOffsetsToStrings(); });
947 TGroup.spawn(f: [&]() { assignOffsetsToSections(); });
948}
949
950void DWARFLinkerImpl::assignOffsetsToStrings() {
951 size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
952 uint64_t CurDebugStrOffset =
953 1; // start from 1 to take into account zero entry.
954 size_t CurDebugLineStrIndex = 0;
955 uint64_t CurDebugLineStrOffset = 0;
956
957 // Enumerates all strings, add them into the DwarfStringPoolEntry map,
958 // assign offset and index to the string if it is not indexed yet.
959 forEachOutputString(StringHandler: [&](StringDestinationKind Kind,
960 const StringEntry *String) {
961 switch (Kind) {
962 case StringDestinationKind::DebugStr: {
963 DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String);
964 assert(Entry != nullptr);
965
966 if (!Entry->isIndexed()) {
967 Entry->Offset = CurDebugStrOffset;
968 CurDebugStrOffset += Entry->String.size() + 1;
969 Entry->Index = CurDebugStrIndex++;
970 }
971 } break;
972 case StringDestinationKind::DebugLineStr: {
973 DwarfStringPoolEntryWithExtString *Entry =
974 DebugLineStrStrings.add(String);
975 assert(Entry != nullptr);
976
977 if (!Entry->isIndexed()) {
978 Entry->Offset = CurDebugLineStrOffset;
979 CurDebugLineStrOffset += Entry->String.size() + 1;
980 Entry->Index = CurDebugLineStrIndex++;
981 }
982 } break;
983 }
984 });
985}
986
987void DWARFLinkerImpl::assignOffsetsToSections() {
988 std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
989
990 forEachObjectSectionsSet(SectionsSetHandler: [&](OutputSections &UnitSections) {
991 UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
992 });
993}
994
995void DWARFLinkerImpl::forEachOutputString(
996 function_ref<void(StringDestinationKind Kind, const StringEntry *String)>
997 StringHandler) {
998 // To save space we do not create any separate string table.
999 // We use already allocated string patches and accelerator entries:
1000 // enumerate them in natural order and assign offsets.
1001 // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
1002 // sections in the same order as they were assigned offsets.
1003 forEachCompileUnit(UnitHandler: [&](CompileUnit *CU) {
1004 CU->forEach(Handler: [&](SectionDescriptor &OutSection) {
1005 OutSection.ListDebugStrPatch.forEach(Handler: [&](DebugStrPatch &Patch) {
1006 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1007 });
1008
1009 OutSection.ListDebugLineStrPatch.forEach(Handler: [&](DebugLineStrPatch &Patch) {
1010 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1011 });
1012 });
1013
1014 CU->forEachAcceleratorRecord(Handler: [&](DwarfUnit::AccelInfo &Info) {
1015 StringHandler(DebugStr, Info.String);
1016 });
1017 });
1018
1019 if (ArtificialTypeUnit != nullptr) {
1020 ArtificialTypeUnit->forEach(Handler: [&](SectionDescriptor &OutSection) {
1021 OutSection.ListDebugStrPatch.forEach(Handler: [&](DebugStrPatch &Patch) {
1022 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1023 });
1024
1025 OutSection.ListDebugLineStrPatch.forEach(Handler: [&](DebugLineStrPatch &Patch) {
1026 StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
1027 });
1028
1029 OutSection.ListDebugTypeStrPatch.forEach(Handler: [&](DebugTypeStrPatch &Patch) {
1030 if (Patch.Die == nullptr)
1031 return;
1032
1033 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1034 });
1035
1036 OutSection.ListDebugTypeLineStrPatch.forEach(
1037 Handler: [&](DebugTypeLineStrPatch &Patch) {
1038 if (Patch.Die == nullptr)
1039 return;
1040
1041 StringHandler(StringDestinationKind::DebugStr, Patch.String);
1042 });
1043 });
1044 }
1045}
1046
1047void DWARFLinkerImpl::forEachObjectSectionsSet(
1048 function_ref<void(OutputSections &)> SectionsSetHandler) {
1049 // Handle artificial type unit first.
1050 if (ArtificialTypeUnit != nullptr)
1051 SectionsSetHandler(*ArtificialTypeUnit);
1052
1053 // Then all modules(before regular compilation units).
1054 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1055 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1056 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1057 SectionsSetHandler(*ModuleUnit.Unit);
1058
1059 // Finally all compilation units.
1060 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1061 // Handle object file common sections.
1062 SectionsSetHandler(*Context);
1063
1064 // Handle compilation units.
1065 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1066 if (CU->getStage() != CompileUnit::Stage::Skipped)
1067 SectionsSetHandler(*CU);
1068 }
1069}
1070
1071void DWARFLinkerImpl::forEachCompileAndTypeUnit(
1072 function_ref<void(DwarfUnit *CU)> UnitHandler) {
1073 if (ArtificialTypeUnit != nullptr)
1074 UnitHandler(ArtificialTypeUnit.get());
1075
1076 // Enumerate module units.
1077 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1078 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1079 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1080 UnitHandler(ModuleUnit.Unit.get());
1081
1082 // Enumerate compile units.
1083 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1084 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1085 if (CU->getStage() != CompileUnit::Stage::Skipped)
1086 UnitHandler(CU.get());
1087}
1088
1089void DWARFLinkerImpl::forEachCompileUnit(
1090 function_ref<void(CompileUnit *CU)> UnitHandler) {
1091 // Enumerate module units.
1092 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1093 for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
1094 if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
1095 UnitHandler(ModuleUnit.Unit.get());
1096
1097 // Enumerate compile units.
1098 for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
1099 for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
1100 if (CU->getStage() != CompileUnit::Stage::Skipped)
1101 UnitHandler(CU.get());
1102}
1103
1104void DWARFLinkerImpl::patchOffsetsAndSizes() {
1105 forEachObjectSectionsSet(SectionsSetHandler: [&](OutputSections &SectionsSet) {
1106 SectionsSet.forEach(Handler: [&](SectionDescriptor &OutSection) {
1107 SectionsSet.applyPatches(Section&: OutSection, DebugStrStrings, DebugLineStrStrings,
1108 TypeUnitPtr: ArtificialTypeUnit.get());
1109 });
1110 });
1111}
1112
1113void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {
1114 llvm::parallel::TaskGroup TG;
1115
1116 // Create section descriptors ahead if they are not exist at the moment.
1117 // SectionDescriptors container is not thread safe. Thus we should be sure
1118 // that descriptors would not be created in following parallel tasks.
1119
1120 CommonSections.getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugStr);
1121 CommonSections.getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugLineStr);
1122
1123 if (llvm::is_contained(Range&: GlobalData.Options.AccelTables,
1124 Element: AccelTableKind::Apple)) {
1125 CommonSections.getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::AppleNames);
1126 CommonSections.getOrCreateSectionDescriptor(
1127 SectionKind: DebugSectionKind::AppleNamespaces);
1128 CommonSections.getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::AppleObjC);
1129 CommonSections.getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::AppleTypes);
1130 }
1131
1132 if (llvm::is_contained(Range&: GlobalData.Options.AccelTables,
1133 Element: AccelTableKind::DebugNames))
1134 CommonSections.getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugNames);
1135
1136 // Emit .debug_str and .debug_line_str sections.
1137 TG.spawn(f: [&]() { emitStringSections(); });
1138
1139 if (llvm::is_contained(Range&: GlobalData.Options.AccelTables,
1140 Element: AccelTableKind::Apple)) {
1141 // Emit apple accelerator sections.
1142 TG.spawn(f: [&]() {
1143 emitAppleAcceleratorSections(TargetTriple: (*GlobalData.getTargetTriple()).get());
1144 });
1145 }
1146
1147 if (llvm::is_contained(Range&: GlobalData.Options.AccelTables,
1148 Element: AccelTableKind::DebugNames)) {
1149 // Emit .debug_names section.
1150 TG.spawn(f: [&]() {
1151 emitDWARFv5DebugNamesSection(TargetTriple: (*GlobalData.getTargetTriple()).get());
1152 });
1153 }
1154
1155 // Write compile units to the output file.
1156 TG.spawn(f: [&]() { writeCompileUnitsToTheOutput(); });
1157}
1158
1159void DWARFLinkerImpl::emitStringSections() {
1160 uint64_t DebugStrNextOffset = 0;
1161 uint64_t DebugLineStrNextOffset = 0;
1162
1163 // Emit zero length string. Accelerator tables does not work correctly
1164 // if the first string is not zero length string.
1165 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::DebugStr)
1166 .emitInplaceString(String: "");
1167 DebugStrNextOffset++;
1168
1169 forEachOutputString(
1170 StringHandler: [&](StringDestinationKind Kind, const StringEntry *String) {
1171 switch (Kind) {
1172 case StringDestinationKind::DebugStr: {
1173 DwarfStringPoolEntryWithExtString *StringToEmit =
1174 DebugStrStrings.getExistingEntry(String);
1175 assert(StringToEmit->isIndexed());
1176
1177 // Strings may be repeated. Use accumulated DebugStrNextOffset
1178 // to understand whether corresponding string is already emitted.
1179 // Skip string if its offset less than accumulated offset.
1180 if (StringToEmit->Offset >= DebugStrNextOffset) {
1181 DebugStrNextOffset =
1182 StringToEmit->Offset + StringToEmit->String.size() + 1;
1183 // Emit the string itself.
1184 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::DebugStr)
1185 .emitInplaceString(String: StringToEmit->String);
1186 }
1187 } break;
1188 case StringDestinationKind::DebugLineStr: {
1189 DwarfStringPoolEntryWithExtString *StringToEmit =
1190 DebugLineStrStrings.getExistingEntry(String);
1191 assert(StringToEmit->isIndexed());
1192
1193 // Strings may be repeated. Use accumulated DebugLineStrStrings
1194 // to understand whether corresponding string is already emitted.
1195 // Skip string if its offset less than accumulated offset.
1196 if (StringToEmit->Offset >= DebugLineStrNextOffset) {
1197 DebugLineStrNextOffset =
1198 StringToEmit->Offset + StringToEmit->String.size() + 1;
1199 // Emit the string itself.
1200 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::DebugLineStr)
1201 .emitInplaceString(String: StringToEmit->String);
1202 }
1203 } break;
1204 }
1205 });
1206}
1207
1208void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
1209 AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
1210 AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
1211 AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;
1212 AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
1213
1214 forEachCompileAndTypeUnit(UnitHandler: [&](DwarfUnit *CU) {
1215 CU->forEachAcceleratorRecord(Handler: [&](const DwarfUnit::AccelInfo &Info) {
1216 uint64_t OutOffset = Info.OutOffset;
1217 switch (Info.Type) {
1218 case DwarfUnit::AccelType::None: {
1219 llvm_unreachable("Unknown accelerator record");
1220 } break;
1221 case DwarfUnit::AccelType::Namespace: {
1222 AppleNamespaces.addName(
1223 Name: *DebugStrStrings.getExistingEntry(String: Info.String),
1224 Args: CU->getSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo).StartOffset +
1225 OutOffset);
1226 } break;
1227 case DwarfUnit::AccelType::Name: {
1228 AppleNames.addName(
1229 Name: *DebugStrStrings.getExistingEntry(String: Info.String),
1230 Args: CU->getSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo).StartOffset +
1231 OutOffset);
1232 } break;
1233 case DwarfUnit::AccelType::ObjC: {
1234 AppleObjC.addName(
1235 Name: *DebugStrStrings.getExistingEntry(String: Info.String),
1236 Args: CU->getSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo).StartOffset +
1237 OutOffset);
1238 } break;
1239 case DwarfUnit::AccelType::Type: {
1240 AppleTypes.addName(
1241 Name: *DebugStrStrings.getExistingEntry(String: Info.String),
1242 Args: CU->getSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo).StartOffset +
1243 OutOffset,
1244 Args: Info.Tag,
1245 Args: Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
1246 : 0,
1247 Args: Info.QualifiedNameHash);
1248 } break;
1249 }
1250 });
1251 });
1252
1253 {
1254 // FIXME: we use AsmPrinter to emit accelerator sections.
1255 // It might be beneficial to directly emit accelerator data
1256 // to the raw_svector_ostream.
1257 SectionDescriptor &OutSection =
1258 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::AppleNamespaces);
1259 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1260 OutSection.OS);
1261 if (Error Err = Emitter.init(TheTriple: TargetTriple, Swift5ReflectionSegmentName: "__DWARF")) {
1262 consumeError(Err: std::move(Err));
1263 return;
1264 }
1265
1266 // Emit table.
1267 Emitter.emitAppleNamespaces(Table&: AppleNamespaces);
1268 Emitter.finish();
1269
1270 // Set start offset and size for output section.
1271 OutSection.setSizesForSectionCreatedByAsmPrinter();
1272 }
1273
1274 {
1275 // FIXME: we use AsmPrinter to emit accelerator sections.
1276 // It might be beneficial to directly emit accelerator data
1277 // to the raw_svector_ostream.
1278 SectionDescriptor &OutSection =
1279 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::AppleNames);
1280 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1281 OutSection.OS);
1282 if (Error Err = Emitter.init(TheTriple: TargetTriple, Swift5ReflectionSegmentName: "__DWARF")) {
1283 consumeError(Err: std::move(Err));
1284 return;
1285 }
1286
1287 // Emit table.
1288 Emitter.emitAppleNames(Table&: AppleNames);
1289 Emitter.finish();
1290
1291 // Set start offset ans size for output section.
1292 OutSection.setSizesForSectionCreatedByAsmPrinter();
1293 }
1294
1295 {
1296 // FIXME: we use AsmPrinter to emit accelerator sections.
1297 // It might be beneficial to directly emit accelerator data
1298 // to the raw_svector_ostream.
1299 SectionDescriptor &OutSection =
1300 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::AppleObjC);
1301 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1302 OutSection.OS);
1303 if (Error Err = Emitter.init(TheTriple: TargetTriple, Swift5ReflectionSegmentName: "__DWARF")) {
1304 consumeError(Err: std::move(Err));
1305 return;
1306 }
1307
1308 // Emit table.
1309 Emitter.emitAppleObjc(Table&: AppleObjC);
1310 Emitter.finish();
1311
1312 // Set start offset ans size for output section.
1313 OutSection.setSizesForSectionCreatedByAsmPrinter();
1314 }
1315
1316 {
1317 // FIXME: we use AsmPrinter to emit accelerator sections.
1318 // It might be beneficial to directly emit accelerator data
1319 // to the raw_svector_ostream.
1320 SectionDescriptor &OutSection =
1321 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::AppleTypes);
1322 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1323 OutSection.OS);
1324 if (Error Err = Emitter.init(TheTriple: TargetTriple, Swift5ReflectionSegmentName: "__DWARF")) {
1325 consumeError(Err: std::move(Err));
1326 return;
1327 }
1328
1329 // Emit table.
1330 Emitter.emitAppleTypes(Table&: AppleTypes);
1331 Emitter.finish();
1332
1333 // Set start offset ans size for output section.
1334 OutSection.setSizesForSectionCreatedByAsmPrinter();
1335 }
1336}
1337
1338void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
1339 std::unique_ptr<DWARF5AccelTable> DebugNames;
1340
1341 DebugNamesUnitsOffsets CompUnits;
1342 CompUnitIDToIdx CUidToIdx;
1343
1344 unsigned Id = 0;
1345
1346 forEachCompileAndTypeUnit(UnitHandler: [&](DwarfUnit *CU) {
1347 bool HasRecords = false;
1348 CU->forEachAcceleratorRecord(Handler: [&](const DwarfUnit::AccelInfo &Info) {
1349 if (DebugNames == nullptr)
1350 DebugNames = std::make_unique<DWARF5AccelTable>();
1351
1352 HasRecords = true;
1353 switch (Info.Type) {
1354 case DwarfUnit::AccelType::Name:
1355 case DwarfUnit::AccelType::Namespace:
1356 case DwarfUnit::AccelType::Type: {
1357 DebugNames->addName(Name: *DebugStrStrings.getExistingEntry(String: Info.String),
1358 Args: Info.OutOffset, Args: std::nullopt /*ParentDIEOffset*/,
1359 Args: Info.Tag, Args: CU->getUniqueID(),
1360 Args: CU->getTag() == dwarf::DW_TAG_type_unit);
1361 } break;
1362
1363 default:
1364 break; // Nothing to do.
1365 };
1366 });
1367
1368 if (HasRecords) {
1369 CompUnits.push_back(
1370 x: CU->getOrCreateSectionDescriptor(SectionKind: DebugSectionKind::DebugInfo)
1371 .StartOffset);
1372 CUidToIdx[CU->getUniqueID()] = Id++;
1373 }
1374 });
1375
1376 if (DebugNames != nullptr) {
1377 // FIXME: we use AsmPrinter to emit accelerator sections.
1378 // It might be beneficial to directly emit accelerator data
1379 // to the raw_svector_ostream.
1380 SectionDescriptor &OutSection =
1381 CommonSections.getSectionDescriptor(SectionKind: DebugSectionKind::DebugNames);
1382 DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
1383 OutSection.OS);
1384 if (Error Err = Emitter.init(TheTriple: TargetTriple, Swift5ReflectionSegmentName: "__DWARF")) {
1385 consumeError(Err: std::move(Err));
1386 return;
1387 }
1388
1389 // Emit table.
1390 Emitter.emitDebugNames(Table&: *DebugNames, CUOffsets&: CompUnits, UnitIDToIdxMap&: CUidToIdx);
1391 Emitter.finish();
1392
1393 // Set start offset ans size for output section.
1394 OutSection.setSizesForSectionCreatedByAsmPrinter();
1395 }
1396}
1397
1398void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {
1399 GlobalData.getStringPool().clear();
1400 DebugStrStrings.clear();
1401 DebugLineStrStrings.clear();
1402}
1403
1404void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {
1405 // Enumerate all sections and store them into the final emitter.
1406 forEachObjectSectionsSet(SectionsSetHandler: [&](OutputSections &Sections) {
1407 Sections.forEach(Handler: [&](std::shared_ptr<SectionDescriptor> OutSection) {
1408 // Emit section content.
1409 SectionHandler(OutSection);
1410 });
1411 });
1412}
1413
1414void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {
1415 CommonSections.forEach(Handler: [&](std::shared_ptr<SectionDescriptor> OutSection) {
1416 SectionHandler(OutSection);
1417 });
1418}
1419