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