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