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