xref: /llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp (revision 75bc20ff899753b100cb875ce703af2348a1d6bb)
12357e899Savl-llvm //=== DWARFLinkerImpl.cpp -------------------------------------------------===//
22357e899Savl-llvm //
32357e899Savl-llvm // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42357e899Savl-llvm // See https://llvm.org/LICENSE.txt for license information.
52357e899Savl-llvm // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62357e899Savl-llvm //
72357e899Savl-llvm //===----------------------------------------------------------------------===//
82357e899Savl-llvm 
92357e899Savl-llvm #include "DWARFLinkerImpl.h"
102357e899Savl-llvm #include "DIEGenerator.h"
112357e899Savl-llvm #include "DependencyTracker.h"
12a02c0d94Savl-llvm #include "llvm/DWARFLinker/Utils.h"
132357e899Savl-llvm #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
142357e899Savl-llvm #include "llvm/Support/FormatVariadic.h"
152357e899Savl-llvm #include "llvm/Support/Parallel.h"
162357e899Savl-llvm #include "llvm/Support/ThreadPool.h"
172357e899Savl-llvm 
182357e899Savl-llvm using namespace llvm;
192357e899Savl-llvm using namespace dwarf_linker;
202357e899Savl-llvm using namespace dwarf_linker::parallel;
212357e899Savl-llvm 
DWARFLinkerImpl(MessageHandlerTy ErrorHandler,MessageHandlerTy WarningHandler)222357e899Savl-llvm DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
2332a6e9d6SJonas Devlieghere                                  MessageHandlerTy WarningHandler)
242357e899Savl-llvm     : UniqueUnitID(0), DebugStrStrings(GlobalData),
252357e899Savl-llvm       DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {
262357e899Savl-llvm   GlobalData.setErrorHandler(ErrorHandler);
272357e899Savl-llvm   GlobalData.setWarningHandler(WarningHandler);
282357e899Savl-llvm }
292357e899Savl-llvm 
LinkContext(LinkingGlobalData & GlobalData,DWARFFile & File,StringMap<uint64_t> & ClangModules,std::atomic<size_t> & UniqueUnitID)302357e899Savl-llvm DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,
312357e899Savl-llvm                                           DWARFFile &File,
322357e899Savl-llvm                                           StringMap<uint64_t> &ClangModules,
339ff4be64SAlexey Lapshin                                           std::atomic<size_t> &UniqueUnitID)
342357e899Savl-llvm     : OutputSections(GlobalData), InputDWARFFile(File),
359ff4be64SAlexey Lapshin       ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) {
362357e899Savl-llvm 
372357e899Savl-llvm   if (File.Dwarf) {
382357e899Savl-llvm     if (!File.Dwarf->compile_units().empty())
392357e899Savl-llvm       CompileUnits.reserve(File.Dwarf->getNumCompileUnits());
402357e899Savl-llvm 
412357e899Savl-llvm     // Set context format&endianness based on the input file.
422357e899Savl-llvm     Format.Version = File.Dwarf->getMaxVersion();
432357e899Savl-llvm     Format.AddrSize = File.Dwarf->getCUAddrSize();
442357e899Savl-llvm     Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
452357e899Savl-llvm                                               : llvm::endianness::big;
462357e899Savl-llvm   }
472357e899Savl-llvm }
482357e899Savl-llvm 
RefModuleUnit(DWARFFile & File,std::unique_ptr<CompileUnit> Unit)492357e899Savl-llvm DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
502357e899Savl-llvm     DWARFFile &File, std::unique_ptr<CompileUnit> Unit)
512357e899Savl-llvm     : File(File), Unit(std::move(Unit)) {}
522357e899Savl-llvm 
RefModuleUnit(LinkContext::RefModuleUnit && Other)532357e899Savl-llvm DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
542357e899Savl-llvm     LinkContext::RefModuleUnit &&Other)
552357e899Savl-llvm     : File(Other.File), Unit(std::move(Other.Unit)) {}
562357e899Savl-llvm 
addModulesCompileUnit(LinkContext::RefModuleUnit && Unit)572357e899Savl-llvm void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(
582357e899Savl-llvm     LinkContext::RefModuleUnit &&Unit) {
592357e899Savl-llvm   ModulesCompileUnits.emplace_back(std::move(Unit));
602357e899Savl-llvm }
612357e899Savl-llvm 
addObjectFile(DWARFFile & File,ObjFileLoaderTy Loader,CompileUnitHandlerTy OnCUDieLoaded)622357e899Savl-llvm void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
632357e899Savl-llvm                                     CompileUnitHandlerTy OnCUDieLoaded) {
642357e899Savl-llvm   ObjectContexts.emplace_back(std::make_unique<LinkContext>(
659ff4be64SAlexey Lapshin       GlobalData, File, ClangModules, UniqueUnitID));
662357e899Savl-llvm 
672357e899Savl-llvm   if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
682357e899Savl-llvm     for (const std::unique_ptr<DWARFUnit> &CU :
692357e899Savl-llvm          ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
702357e899Savl-llvm       DWARFDie CUDie = CU->getUnitDIE();
712357e899Savl-llvm       OverallNumberOfCU++;
722357e899Savl-llvm 
732357e899Savl-llvm       if (!CUDie)
742357e899Savl-llvm         continue;
752357e899Savl-llvm 
762357e899Savl-llvm       OnCUDieLoaded(*CU);
772357e899Savl-llvm 
782357e899Savl-llvm       // Register mofule reference.
792357e899Savl-llvm       if (!GlobalData.getOptions().UpdateIndexTablesOnly)
802357e899Savl-llvm         ObjectContexts.back()->registerModuleReference(CUDie, Loader,
812357e899Savl-llvm                                                        OnCUDieLoaded);
822357e899Savl-llvm     }
832357e899Savl-llvm   }
842357e899Savl-llvm }
852357e899Savl-llvm 
setEstimatedObjfilesAmount(unsigned ObjFilesNum)862357e899Savl-llvm void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
872357e899Savl-llvm   ObjectContexts.reserve(ObjFilesNum);
882357e899Savl-llvm }
892357e899Savl-llvm 
link()902357e899Savl-llvm Error DWARFLinkerImpl::link() {
912357e899Savl-llvm   // reset compile unit unique ID counter.
922357e899Savl-llvm   UniqueUnitID = 0;
932357e899Savl-llvm 
942357e899Savl-llvm   if (Error Err = validateAndUpdateOptions())
952357e899Savl-llvm     return Err;
962357e899Savl-llvm 
972357e899Savl-llvm   dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
982357e899Savl-llvm                                     0, dwarf::DwarfFormat::DWARF32};
992357e899Savl-llvm   llvm::endianness GlobalEndianness = llvm::endianness::native;
1002357e899Savl-llvm 
1019ff4be64SAlexey Lapshin   if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
1029ff4be64SAlexey Lapshin           GlobalData.getTargetTriple()) {
1039ff4be64SAlexey Lapshin     GlobalEndianness = (*CurTriple).get().isLittleEndian()
1042357e899Savl-llvm                            ? llvm::endianness::little
1052357e899Savl-llvm                            : llvm::endianness::big;
1062357e899Savl-llvm   }
1072357e899Savl-llvm   std::optional<uint16_t> Language;
1082357e899Savl-llvm 
1092357e899Savl-llvm   for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
110acd7a688SKazu Hirata     if (Context->InputDWARFFile.Dwarf == nullptr) {
1112357e899Savl-llvm       Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
1122357e899Savl-llvm       continue;
1132357e899Savl-llvm     }
1142357e899Savl-llvm 
1152357e899Savl-llvm     if (GlobalData.getOptions().Verbose) {
1160ed81942SAlexey Lapshin       outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
1170ed81942SAlexey Lapshin              << "\n";
1182357e899Savl-llvm 
1192357e899Savl-llvm       for (const std::unique_ptr<DWARFUnit> &OrigCU :
1202357e899Savl-llvm            Context->InputDWARFFile.Dwarf->compile_units()) {
1212357e899Savl-llvm         outs() << "Input compilation unit:";
1222357e899Savl-llvm         DIDumpOptions DumpOpts;
1232357e899Savl-llvm         DumpOpts.ChildRecurseDepth = 0;
1242357e899Savl-llvm         DumpOpts.Verbose = GlobalData.getOptions().Verbose;
1252357e899Savl-llvm         OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
1262357e899Savl-llvm       }
1272357e899Savl-llvm     }
1282357e899Savl-llvm 
1292357e899Savl-llvm     // Verify input DWARF if requested.
1302357e899Savl-llvm     if (GlobalData.getOptions().VerifyInputDWARF)
1312357e899Savl-llvm       verifyInput(Context->InputDWARFFile);
1322357e899Savl-llvm 
1339ff4be64SAlexey Lapshin     if (!GlobalData.getTargetTriple())
1342357e899Savl-llvm       GlobalEndianness = Context->getEndianness();
1352357e899Savl-llvm     GlobalFormat.AddrSize =
1362357e899Savl-llvm         std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
1372357e899Savl-llvm 
1382357e899Savl-llvm     Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
1392357e899Savl-llvm 
1402357e899Savl-llvm     // FIXME: move creation of CompileUnits into the addObjectFile.
1412357e899Savl-llvm     // This would allow to not scan for context Language and Modules state
1422357e899Savl-llvm     // twice. And then following handling might be removed.
1432357e899Savl-llvm     for (const std::unique_ptr<DWARFUnit> &OrigCU :
1442357e899Savl-llvm          Context->InputDWARFFile.Dwarf->compile_units()) {
145*75bc20ffSKazu Hirata       DWARFDie UnitDie = OrigCU->getUnitDIE();
1462357e899Savl-llvm 
1472357e899Savl-llvm       if (!Language) {
1482357e899Savl-llvm         if (std::optional<DWARFFormValue> Val =
1492357e899Savl-llvm                 UnitDie.find(dwarf::DW_AT_language)) {
1502357e899Savl-llvm           uint16_t LangVal = dwarf::toUnsigned(Val, 0);
1512357e899Savl-llvm           if (isODRLanguage(LangVal))
1522357e899Savl-llvm             Language = LangVal;
1532357e899Savl-llvm         }
1542357e899Savl-llvm       }
1552357e899Savl-llvm     }
1562357e899Savl-llvm   }
1572357e899Savl-llvm 
1582357e899Savl-llvm   if (GlobalFormat.AddrSize == 0) {
1599ff4be64SAlexey Lapshin     if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
1609ff4be64SAlexey Lapshin             GlobalData.getTargetTriple())
1619ff4be64SAlexey Lapshin       GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
1622357e899Savl-llvm     else
1632357e899Savl-llvm       GlobalFormat.AddrSize = 8;
1642357e899Savl-llvm   }
1652357e899Savl-llvm 
1662357e899Savl-llvm   CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
1672357e899Savl-llvm 
1682357e899Savl-llvm   if (!GlobalData.Options.NoODR && Language.has_value()) {
1692357e899Savl-llvm     llvm::parallel::TaskGroup TGroup;
1702357e899Savl-llvm     TGroup.spawn([&]() {
1712357e899Savl-llvm       ArtificialTypeUnit = std::make_unique<TypeUnit>(
1722357e899Savl-llvm           GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);
1732357e899Savl-llvm     });
1742357e899Savl-llvm   }
1752357e899Savl-llvm 
1762357e899Savl-llvm   // Set parallel options.
1772357e899Savl-llvm   if (GlobalData.getOptions().Threads == 0)
1782357e899Savl-llvm     llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU);
1792357e899Savl-llvm   else
1802357e899Savl-llvm     llvm::parallel::strategy =
1812357e899Savl-llvm         hardware_concurrency(GlobalData.getOptions().Threads);
1822357e899Savl-llvm 
1832357e899Savl-llvm   // Link object files.
1842357e899Savl-llvm   if (GlobalData.getOptions().Threads == 1) {
1852357e899Savl-llvm     for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1862357e899Savl-llvm       // Link object file.
1872357e899Savl-llvm       if (Error Err = Context->link(ArtificialTypeUnit.get()))
1882357e899Savl-llvm         GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
1892357e899Savl-llvm 
1902357e899Savl-llvm       Context->InputDWARFFile.unload();
1912357e899Savl-llvm     }
1922357e899Savl-llvm   } else {
193716042a6SMehdi Amini     DefaultThreadPool Pool(llvm::parallel::strategy);
1942357e899Savl-llvm     for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
1952357e899Savl-llvm       Pool.async([&]() {
1962357e899Savl-llvm         // Link object file.
1972357e899Savl-llvm         if (Error Err = Context->link(ArtificialTypeUnit.get()))
1982357e899Savl-llvm           GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
1992357e899Savl-llvm 
2002357e899Savl-llvm         Context->InputDWARFFile.unload();
2012357e899Savl-llvm       });
2022357e899Savl-llvm 
2032357e899Savl-llvm     Pool.wait();
2042357e899Savl-llvm   }
2052357e899Savl-llvm 
206acd7a688SKazu Hirata   if (ArtificialTypeUnit != nullptr && !ArtificialTypeUnit->getTypePool()
2072357e899Savl-llvm                                             .getRoot()
2082357e899Savl-llvm                                             ->getValue()
2092357e899Savl-llvm                                             .load()
2102357e899Savl-llvm                                             ->Children.empty()) {
2119ff4be64SAlexey Lapshin     if (GlobalData.getTargetTriple().has_value())
212acd7a688SKazu Hirata       if (Error Err = ArtificialTypeUnit->finishCloningAndEmit(
2139ff4be64SAlexey Lapshin               (*GlobalData.getTargetTriple()).get()))
2142357e899Savl-llvm         return Err;
2152357e899Savl-llvm   }
2162357e899Savl-llvm 
2172357e899Savl-llvm   // At this stage each compile units are cloned to their own set of debug
2182357e899Savl-llvm   // sections. Now, update patches, assign offsets and assemble final file
2192357e899Savl-llvm   // glueing debug tables from each compile unit.
2202357e899Savl-llvm   glueCompileUnitsAndWriteToTheOutput();
2212357e899Savl-llvm 
2222357e899Savl-llvm   return Error::success();
2232357e899Savl-llvm }
2242357e899Savl-llvm 
verifyInput(const DWARFFile & File)2252357e899Savl-llvm void DWARFLinkerImpl::verifyInput(const DWARFFile &File) {
2262357e899Savl-llvm   assert(File.Dwarf);
2272357e899Savl-llvm 
2282357e899Savl-llvm   std::string Buffer;
2292357e899Savl-llvm   raw_string_ostream OS(Buffer);
2302357e899Savl-llvm   DIDumpOptions DumpOpts;
2312357e899Savl-llvm   if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
2322357e899Savl-llvm     if (GlobalData.getOptions().InputVerificationHandler)
2332357e899Savl-llvm       GlobalData.getOptions().InputVerificationHandler(File, OS.str());
2342357e899Savl-llvm   }
2352357e899Savl-llvm }
2362357e899Savl-llvm 
validateAndUpdateOptions()2372357e899Savl-llvm Error DWARFLinkerImpl::validateAndUpdateOptions() {
2382357e899Savl-llvm   if (GlobalData.getOptions().TargetDWARFVersion == 0)
2392357e899Savl-llvm     return createStringError(std::errc::invalid_argument,
2402357e899Savl-llvm                              "target DWARF version is not set");
2412357e899Savl-llvm 
2422357e899Savl-llvm   if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
2432357e899Savl-llvm     GlobalData.Options.Threads = 1;
2442357e899Savl-llvm     GlobalData.warn(
2452357e899Savl-llvm         "set number of threads to 1 to make --verbose to work properly.", "");
2462357e899Savl-llvm   }
2472357e899Savl-llvm 
2482357e899Savl-llvm   // Do not do types deduplication in case --update.
2492357e899Savl-llvm   if (GlobalData.getOptions().UpdateIndexTablesOnly &&
2502357e899Savl-llvm       !GlobalData.Options.NoODR)
2512357e899Savl-llvm     GlobalData.Options.NoODR = true;
2522357e899Savl-llvm 
2532357e899Savl-llvm   return Error::success();
2542357e899Savl-llvm }
2552357e899Savl-llvm 
2562357e899Savl-llvm /// Resolve the relative path to a build artifact referenced by DWARF by
2572357e899Savl-llvm /// applying DW_AT_comp_dir.
resolveRelativeObjectPath(SmallVectorImpl<char> & Buf,DWARFDie CU)2582357e899Savl-llvm static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
2592357e899Savl-llvm   sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
2602357e899Savl-llvm }
2612357e899Savl-llvm 
getDwoId(const DWARFDie & CUDie)2622357e899Savl-llvm static uint64_t getDwoId(const DWARFDie &CUDie) {
2632357e899Savl-llvm   auto DwoId = dwarf::toUnsigned(
2642357e899Savl-llvm       CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2652357e899Savl-llvm   if (DwoId)
2662357e899Savl-llvm     return *DwoId;
2672357e899Savl-llvm   return 0;
2682357e899Savl-llvm }
2692357e899Savl-llvm 
2702357e899Savl-llvm static std::string
remapPath(StringRef Path,const DWARFLinker::ObjectPrefixMapTy & ObjectPrefixMap)2712357e899Savl-llvm remapPath(StringRef Path,
2722357e899Savl-llvm           const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
2732357e899Savl-llvm   if (ObjectPrefixMap.empty())
2742357e899Savl-llvm     return Path.str();
2752357e899Savl-llvm 
2762357e899Savl-llvm   SmallString<256> p = Path;
2772357e899Savl-llvm   for (const auto &Entry : ObjectPrefixMap)
2782357e899Savl-llvm     if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
2792357e899Savl-llvm       break;
2802357e899Savl-llvm   return p.str().str();
2812357e899Savl-llvm }
2822357e899Savl-llvm 
getPCMFile(const DWARFDie & CUDie,DWARFLinker::ObjectPrefixMapTy * ObjectPrefixMap)2832357e899Savl-llvm static std::string getPCMFile(const DWARFDie &CUDie,
2842357e899Savl-llvm                               DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
2852357e899Savl-llvm   std::string PCMFile = dwarf::toString(
2862357e899Savl-llvm       CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
2872357e899Savl-llvm 
2882357e899Savl-llvm   if (PCMFile.empty())
2892357e899Savl-llvm     return PCMFile;
2902357e899Savl-llvm 
2912357e899Savl-llvm   if (ObjectPrefixMap)
2922357e899Savl-llvm     PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
2932357e899Savl-llvm 
2942357e899Savl-llvm   return PCMFile;
2952357e899Savl-llvm }
2962357e899Savl-llvm 
isClangModuleRef(const DWARFDie & CUDie,std::string & PCMFile,unsigned Indent,bool Quiet)2972357e899Savl-llvm std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(
2982357e899Savl-llvm     const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
2992357e899Savl-llvm   if (PCMFile.empty())
3002357e899Savl-llvm     return std::make_pair(false, false);
3012357e899Savl-llvm 
3022357e899Savl-llvm   // Clang module DWARF skeleton CUs abuse this for the path to the module.
3032357e899Savl-llvm   uint64_t DwoId = getDwoId(CUDie);
3042357e899Savl-llvm 
3052357e899Savl-llvm   std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
3062357e899Savl-llvm   if (Name.empty()) {
3072357e899Savl-llvm     if (!Quiet)
3082357e899Savl-llvm       GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
3092357e899Savl-llvm                       InputDWARFFile.FileName);
3102357e899Savl-llvm     return std::make_pair(true, true);
3112357e899Savl-llvm   }
3122357e899Savl-llvm 
3132357e899Savl-llvm   if (!Quiet && GlobalData.getOptions().Verbose) {
3142357e899Savl-llvm     outs().indent(Indent);
3152357e899Savl-llvm     outs() << "Found clang module reference " << PCMFile;
3162357e899Savl-llvm   }
3172357e899Savl-llvm 
3182357e899Savl-llvm   auto Cached = ClangModules.find(PCMFile);
3192357e899Savl-llvm   if (Cached != ClangModules.end()) {
3202357e899Savl-llvm     // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
3212357e899Savl-llvm     // fixed in clang, only warn about DWO_id mismatches in verbose mode.
3222357e899Savl-llvm     // ASTFileSignatures will change randomly when a module is rebuilt.
3232357e899Savl-llvm     if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
3242357e899Savl-llvm       GlobalData.warn(
3252357e899Savl-llvm           Twine("hash mismatch: this object file was built against a "
3262357e899Savl-llvm                 "different version of the module ") +
3272357e899Savl-llvm               PCMFile + ".",
3282357e899Savl-llvm           InputDWARFFile.FileName);
3292357e899Savl-llvm     if (!Quiet && GlobalData.getOptions().Verbose)
3302357e899Savl-llvm       outs() << " [cached].\n";
3312357e899Savl-llvm     return std::make_pair(true, true);
3322357e899Savl-llvm   }
3332357e899Savl-llvm 
3342357e899Savl-llvm   return std::make_pair(true, false);
3352357e899Savl-llvm }
3362357e899Savl-llvm 
3372357e899Savl-llvm /// If this compile unit is really a skeleton CU that points to a
3382357e899Savl-llvm /// clang module, register it in ClangModules and return true.
3392357e899Savl-llvm ///
3402357e899Savl-llvm /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
3412357e899Savl-llvm /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
3422357e899Savl-llvm /// hash.
registerModuleReference(const DWARFDie & CUDie,ObjFileLoaderTy Loader,CompileUnitHandlerTy OnCUDieLoaded,unsigned Indent)3432357e899Savl-llvm bool DWARFLinkerImpl::LinkContext::registerModuleReference(
3442357e899Savl-llvm     const DWARFDie &CUDie, ObjFileLoaderTy Loader,
3452357e899Savl-llvm     CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
3462357e899Savl-llvm   std::string PCMFile =
3472357e899Savl-llvm       getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
3482357e899Savl-llvm   std::pair<bool, bool> IsClangModuleRef =
3492357e899Savl-llvm       isClangModuleRef(CUDie, PCMFile, Indent, false);
3502357e899Savl-llvm 
3512357e899Savl-llvm   if (!IsClangModuleRef.first)
3522357e899Savl-llvm     return false;
3532357e899Savl-llvm 
3542357e899Savl-llvm   if (IsClangModuleRef.second)
3552357e899Savl-llvm     return true;
3562357e899Savl-llvm 
3572357e899Savl-llvm   if (GlobalData.getOptions().Verbose)
3582357e899Savl-llvm     outs() << " ...\n";
3592357e899Savl-llvm 
3602357e899Savl-llvm   // Cyclic dependencies are disallowed by Clang, but we still
3612357e899Savl-llvm   // shouldn't run into an infinite loop, so mark it as processed now.
3622357e899Savl-llvm   ClangModules.insert({PCMFile, getDwoId(CUDie)});
3632357e899Savl-llvm 
3642357e899Savl-llvm   if (Error E =
3652357e899Savl-llvm           loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
3662357e899Savl-llvm     consumeError(std::move(E));
3672357e899Savl-llvm     return false;
3682357e899Savl-llvm   }
3692357e899Savl-llvm   return true;
3702357e899Savl-llvm }
3712357e899Savl-llvm 
loadClangModule(ObjFileLoaderTy Loader,const DWARFDie & CUDie,const std::string & PCMFile,CompileUnitHandlerTy OnCUDieLoaded,unsigned Indent)3722357e899Savl-llvm Error DWARFLinkerImpl::LinkContext::loadClangModule(
3732357e899Savl-llvm     ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
3742357e899Savl-llvm     CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
3752357e899Savl-llvm 
3762357e899Savl-llvm   uint64_t DwoId = getDwoId(CUDie);
3772357e899Savl-llvm   std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
3782357e899Savl-llvm 
3792357e899Savl-llvm   /// Using a SmallString<0> because loadClangModule() is recursive.
3802357e899Savl-llvm   SmallString<0> Path(GlobalData.getOptions().PrependPath);
3812357e899Savl-llvm   if (sys::path::is_relative(PCMFile))
3822357e899Savl-llvm     resolveRelativeObjectPath(Path, CUDie);
3832357e899Savl-llvm   sys::path::append(Path, PCMFile);
3842357e899Savl-llvm   // Don't use the cached binary holder because we have no thread-safety
3852357e899Savl-llvm   // guarantee and the lifetime is limited.
3862357e899Savl-llvm 
3872357e899Savl-llvm   if (Loader == nullptr) {
3882357e899Savl-llvm     GlobalData.error("cann't load clang module: loader is not specified.",
3892357e899Savl-llvm                      InputDWARFFile.FileName);
3902357e899Savl-llvm     return Error::success();
3912357e899Savl-llvm   }
3922357e899Savl-llvm 
3932357e899Savl-llvm   auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
3942357e899Savl-llvm   if (!ErrOrObj)
3952357e899Savl-llvm     return Error::success();
3962357e899Savl-llvm 
3972357e899Savl-llvm   std::unique_ptr<CompileUnit> Unit;
3982357e899Savl-llvm   for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
3992357e899Savl-llvm     OnCUDieLoaded(*CU);
4002357e899Savl-llvm     // Recursively get all modules imported by this one.
4012357e899Savl-llvm     auto ChildCUDie = CU->getUnitDIE();
4022357e899Savl-llvm     if (!ChildCUDie)
4032357e899Savl-llvm       continue;
4042357e899Savl-llvm     if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
4052357e899Savl-llvm       if (Unit) {
4062357e899Savl-llvm         std::string Err =
4072357e899Savl-llvm             (PCMFile +
4082357e899Savl-llvm              ": Clang modules are expected to have exactly 1 compile unit.\n");
4092357e899Savl-llvm         GlobalData.error(Err, InputDWARFFile.FileName);
4102357e899Savl-llvm         return make_error<StringError>(Err, inconvertibleErrorCode());
4112357e899Savl-llvm       }
4122357e899Savl-llvm       // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
4132357e899Savl-llvm       // fixed in clang, only warn about DWO_id mismatches in verbose mode.
4142357e899Savl-llvm       // ASTFileSignatures will change randomly when a module is rebuilt.
4152357e899Savl-llvm       uint64_t PCMDwoId = getDwoId(ChildCUDie);
4162357e899Savl-llvm       if (PCMDwoId != DwoId) {
4172357e899Savl-llvm         if (GlobalData.getOptions().Verbose)
4182357e899Savl-llvm           GlobalData.warn(
4192357e899Savl-llvm               Twine("hash mismatch: this object file was built against a "
4202357e899Savl-llvm                     "different version of the module ") +
4212357e899Savl-llvm                   PCMFile + ".",
4222357e899Savl-llvm               InputDWARFFile.FileName);
4232357e899Savl-llvm         // Update the cache entry with the DwoId of the module loaded from disk.
4242357e899Savl-llvm         ClangModules[PCMFile] = PCMDwoId;
4252357e899Savl-llvm       }
4262357e899Savl-llvm 
4272357e899Savl-llvm       // Empty modules units should not be cloned.
4282357e899Savl-llvm       if (!ChildCUDie.hasChildren())
4292357e899Savl-llvm         continue;
4302357e899Savl-llvm 
4312357e899Savl-llvm       // Add this module.
4322357e899Savl-llvm       Unit = std::make_unique<CompileUnit>(
4332357e899Savl-llvm           GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
4342357e899Savl-llvm           getUnitForOffset, CU->getFormParams(), getEndianness());
4352357e899Savl-llvm     }
4362357e899Savl-llvm   }
4372357e899Savl-llvm 
4382357e899Savl-llvm   if (Unit) {
4392357e899Savl-llvm     ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
4402357e899Savl-llvm     // Preload line table, as it can't be loaded asynchronously.
4412357e899Savl-llvm     ModulesCompileUnits.back().Unit->loadLineTable();
4422357e899Savl-llvm   }
4432357e899Savl-llvm 
4442357e899Savl-llvm   return Error::success();
4452357e899Savl-llvm }
4462357e899Savl-llvm 
link(TypeUnit * ArtificialTypeUnit)4472357e899Savl-llvm Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
4482357e899Savl-llvm   InterCUProcessingStarted = false;
4492357e899Savl-llvm   if (!InputDWARFFile.Dwarf)
4502357e899Savl-llvm     return Error::success();
4512357e899Savl-llvm 
4522357e899Savl-llvm   // Preload macro tables, as they can't be loaded asynchronously.
4532357e899Savl-llvm   InputDWARFFile.Dwarf->getDebugMacinfo();
4542357e899Savl-llvm   InputDWARFFile.Dwarf->getDebugMacro();
4552357e899Savl-llvm 
4562357e899Savl-llvm   // Link modules compile units first.
4572357e899Savl-llvm   parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) {
4582357e899Savl-llvm     linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit);
4592357e899Savl-llvm   });
4602357e899Savl-llvm 
4612357e899Savl-llvm   // Check for live relocations. If there is no any live relocation then we
4622357e899Savl-llvm   // can skip entire object file.
4632357e899Savl-llvm   if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
4642357e899Savl-llvm       !InputDWARFFile.Addresses->hasValidRelocs()) {
4652357e899Savl-llvm     if (GlobalData.getOptions().Verbose)
4662357e899Savl-llvm       outs() << "No valid relocations found. Skipping.\n";
4672357e899Savl-llvm     return Error::success();
4682357e899Savl-llvm   }
4692357e899Savl-llvm 
4702357e899Savl-llvm   OriginalDebugInfoSize = getInputDebugInfoSize();
4712357e899Savl-llvm 
4722357e899Savl-llvm   // Create CompileUnit structures to keep information about source
4732357e899Savl-llvm   // DWARFUnit`s, load line tables.
4742357e899Savl-llvm   for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
4752357e899Savl-llvm     // Load only unit DIE at this stage.
4762357e899Savl-llvm     auto CUDie = OrigCU->getUnitDIE();
4772357e899Savl-llvm     std::string PCMFile =
4782357e899Savl-llvm         getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
4792357e899Savl-llvm 
4802357e899Savl-llvm     // The !isClangModuleRef condition effectively skips over fully resolved
4812357e899Savl-llvm     // skeleton units.
4822357e899Savl-llvm     if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
4832357e899Savl-llvm         !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
4842357e899Savl-llvm       CompileUnits.emplace_back(std::make_unique<CompileUnit>(
4852357e899Savl-llvm           GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
4862357e899Savl-llvm           getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
4872357e899Savl-llvm 
4882357e899Savl-llvm       // Preload line table, as it can't be loaded asynchronously.
4892357e899Savl-llvm       CompileUnits.back()->loadLineTable();
4902357e899Savl-llvm     }
4912357e899Savl-llvm   };
4922357e899Savl-llvm 
4932357e899Savl-llvm   HasNewInterconnectedCUs = false;
4942357e899Savl-llvm 
4952357e899Savl-llvm   // Link self-sufficient compile units and discover inter-connected compile
4962357e899Savl-llvm   // units.
4972357e899Savl-llvm   parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
4982357e899Savl-llvm     linkSingleCompileUnit(*CU, ArtificialTypeUnit);
4992357e899Savl-llvm   });
5002357e899Savl-llvm 
5012357e899Savl-llvm   // Link all inter-connected units.
5022357e899Savl-llvm   if (HasNewInterconnectedCUs) {
5032357e899Savl-llvm     InterCUProcessingStarted = true;
5042357e899Savl-llvm 
5052357e899Savl-llvm     if (Error Err = finiteLoop([&]() -> Expected<bool> {
5062357e899Savl-llvm           HasNewInterconnectedCUs = false;
5072357e899Savl-llvm 
5082357e899Savl-llvm           // Load inter-connected units.
5092357e899Savl-llvm           parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5102357e899Savl-llvm             if (CU->isInterconnectedCU()) {
5112357e899Savl-llvm               CU->maybeResetToLoadedStage();
5122357e899Savl-llvm               linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5132357e899Savl-llvm                                     CompileUnit::Stage::Loaded);
5142357e899Savl-llvm             }
5152357e899Savl-llvm           });
5162357e899Savl-llvm 
5172357e899Savl-llvm           // Do liveness analysis for inter-connected units.
5182357e899Savl-llvm           parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5192357e899Savl-llvm             linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5202357e899Savl-llvm                                   CompileUnit::Stage::LivenessAnalysisDone);
5212357e899Savl-llvm           });
5222357e899Savl-llvm 
5232357e899Savl-llvm           return HasNewInterconnectedCUs.load();
5242357e899Savl-llvm         }))
5252357e899Savl-llvm       return Err;
5262357e899Savl-llvm 
5272357e899Savl-llvm     // Update dependencies.
5282357e899Savl-llvm     if (Error Err = finiteLoop([&]() -> Expected<bool> {
5292357e899Savl-llvm           HasNewGlobalDependency = false;
5302357e899Savl-llvm           parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5312357e899Savl-llvm             linkSingleCompileUnit(
5322357e899Savl-llvm                 *CU, ArtificialTypeUnit,
5332357e899Savl-llvm                 CompileUnit::Stage::UpdateDependenciesCompleteness);
5342357e899Savl-llvm           });
5352357e899Savl-llvm           return HasNewGlobalDependency.load();
5362357e899Savl-llvm         }))
5372357e899Savl-llvm       return Err;
5382357e899Savl-llvm     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5392357e899Savl-llvm       if (CU->isInterconnectedCU() &&
5402357e899Savl-llvm           CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
5412357e899Savl-llvm         CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
5422357e899Savl-llvm     });
5432357e899Savl-llvm 
5442357e899Savl-llvm     // Assign type names.
5452357e899Savl-llvm     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5462357e899Savl-llvm       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5472357e899Savl-llvm                             CompileUnit::Stage::TypeNamesAssigned);
5482357e899Savl-llvm     });
5492357e899Savl-llvm 
5502357e899Savl-llvm     // Clone inter-connected units.
5512357e899Savl-llvm     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5522357e899Savl-llvm       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5532357e899Savl-llvm                             CompileUnit::Stage::Cloned);
5542357e899Savl-llvm     });
5552357e899Savl-llvm 
5562357e899Savl-llvm     // Update patches for inter-connected units.
5572357e899Savl-llvm     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5582357e899Savl-llvm       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5592357e899Savl-llvm                             CompileUnit::Stage::PatchesUpdated);
5602357e899Savl-llvm     });
5612357e899Savl-llvm 
5622357e899Savl-llvm     // Release data.
5632357e899Savl-llvm     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5642357e899Savl-llvm       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5652357e899Savl-llvm                             CompileUnit::Stage::Cleaned);
5662357e899Savl-llvm     });
5672357e899Savl-llvm   }
5682357e899Savl-llvm 
5692357e899Savl-llvm   if (GlobalData.getOptions().UpdateIndexTablesOnly) {
5702357e899Savl-llvm     // Emit Invariant sections.
5712357e899Savl-llvm 
5722357e899Savl-llvm     if (Error Err = emitInvariantSections())
5732357e899Savl-llvm       return Err;
5742357e899Savl-llvm   } else if (!CompileUnits.empty()) {
5752357e899Savl-llvm     // Emit .debug_frame section.
5762357e899Savl-llvm 
5772357e899Savl-llvm     Error ResultErr = Error::success();
5782357e899Savl-llvm     llvm::parallel::TaskGroup TGroup;
5792357e899Savl-llvm     // We use task group here as PerThreadBumpPtrAllocator should be called from
5802357e899Savl-llvm     // the threads created by ThreadPoolExecutor.
5812357e899Savl-llvm     TGroup.spawn([&]() {
5822357e899Savl-llvm       if (Error Err = cloneAndEmitDebugFrame())
5832357e899Savl-llvm         ResultErr = std::move(Err);
5842357e899Savl-llvm     });
5852357e899Savl-llvm     return ResultErr;
5862357e899Savl-llvm   }
5872357e899Savl-llvm 
5882357e899Savl-llvm   return Error::success();
5892357e899Savl-llvm }
5902357e899Savl-llvm 
linkSingleCompileUnit(CompileUnit & CU,TypeUnit * ArtificialTypeUnit,enum CompileUnit::Stage DoUntilStage)5912357e899Savl-llvm void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
5922357e899Savl-llvm     CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
5932357e899Savl-llvm     enum CompileUnit::Stage DoUntilStage) {
5942357e899Savl-llvm   if (InterCUProcessingStarted != CU.isInterconnectedCU())
5952357e899Savl-llvm     return;
5962357e899Savl-llvm 
5972357e899Savl-llvm   if (Error Err = finiteLoop([&]() -> Expected<bool> {
5982357e899Savl-llvm         if (CU.getStage() >= DoUntilStage)
5992357e899Savl-llvm           return false;
6002357e899Savl-llvm 
6012357e899Savl-llvm         switch (CU.getStage()) {
6022357e899Savl-llvm         case CompileUnit::Stage::CreatedNotLoaded: {
6032357e899Savl-llvm           // Load input compilation unit DIEs.
6042357e899Savl-llvm           // Analyze properties of DIEs.
6052357e899Savl-llvm           if (!CU.loadInputDIEs()) {
6062357e899Savl-llvm             // We do not need to do liveness analysis for invalid compilation
6072357e899Savl-llvm             // unit.
6082357e899Savl-llvm             CU.setStage(CompileUnit::Stage::Skipped);
6092357e899Savl-llvm           } else {
6102357e899Savl-llvm             CU.analyzeDWARFStructure();
6112357e899Savl-llvm 
6122357e899Savl-llvm             // The registerModuleReference() condition effectively skips
6132357e899Savl-llvm             // over fully resolved skeleton units. This second pass of
6142357e899Savl-llvm             // registerModuleReferences doesn't do any new work, but it
6152357e899Savl-llvm             // will collect top-level errors, which are suppressed. Module
6162357e899Savl-llvm             // warnings were already displayed in the first iteration.
6172357e899Savl-llvm             if (registerModuleReference(
6182357e899Savl-llvm                     CU.getOrigUnit().getUnitDIE(), nullptr,
6192357e899Savl-llvm                     [](const DWARFUnit &) {}, 0))
6202357e899Savl-llvm               CU.setStage(CompileUnit::Stage::PatchesUpdated);
6212357e899Savl-llvm             else
6222357e899Savl-llvm               CU.setStage(CompileUnit::Stage::Loaded);
6232357e899Savl-llvm           }
6242357e899Savl-llvm         } break;
6252357e899Savl-llvm 
6262357e899Savl-llvm         case CompileUnit::Stage::Loaded: {
6272357e899Savl-llvm           // Mark all the DIEs that need to be present in the generated output.
6282357e899Savl-llvm           // If ODR requested, build type names.
6292357e899Savl-llvm           if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
6302357e899Savl-llvm                                                      HasNewInterconnectedCUs)) {
6312357e899Savl-llvm             assert(HasNewInterconnectedCUs &&
6322357e899Savl-llvm                    "Flag indicating new inter-connections is not set");
6332357e899Savl-llvm             return false;
6342357e899Savl-llvm           }
6352357e899Savl-llvm 
6362357e899Savl-llvm           CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
6372357e899Savl-llvm         } break;
6382357e899Savl-llvm 
6392357e899Savl-llvm         case CompileUnit::Stage::LivenessAnalysisDone: {
6402357e899Savl-llvm           if (InterCUProcessingStarted) {
6412357e899Savl-llvm             if (CU.updateDependenciesCompleteness())
6422357e899Savl-llvm               HasNewGlobalDependency = true;
6432357e899Savl-llvm             return false;
6442357e899Savl-llvm           } else {
6452357e899Savl-llvm             if (Error Err = finiteLoop([&]() -> Expected<bool> {
6462357e899Savl-llvm                   return CU.updateDependenciesCompleteness();
6472357e899Savl-llvm                 }))
6482357e899Savl-llvm               return std::move(Err);
6492357e899Savl-llvm 
6502357e899Savl-llvm             CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
6512357e899Savl-llvm           }
6522357e899Savl-llvm         } break;
6532357e899Savl-llvm 
6542357e899Savl-llvm         case CompileUnit::Stage::UpdateDependenciesCompleteness:
6552357e899Savl-llvm #ifndef NDEBUG
6562357e899Savl-llvm           CU.verifyDependencies();
6572357e899Savl-llvm #endif
6582357e899Savl-llvm 
6592357e899Savl-llvm           if (ArtificialTypeUnit) {
6602357e899Savl-llvm             if (Error Err =
6612357e899Savl-llvm                     CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
6622357e899Savl-llvm               return std::move(Err);
6632357e899Savl-llvm           }
6642357e899Savl-llvm           CU.setStage(CompileUnit::Stage::TypeNamesAssigned);
6652357e899Savl-llvm           break;
6662357e899Savl-llvm 
6672357e899Savl-llvm         case CompileUnit::Stage::TypeNamesAssigned:
6682357e899Savl-llvm           // Clone input compile unit.
6692357e899Savl-llvm           if (CU.isClangModule() ||
6702357e899Savl-llvm               GlobalData.getOptions().UpdateIndexTablesOnly ||
6712357e899Savl-llvm               CU.getContaingFile().Addresses->hasValidRelocs()) {
6729ff4be64SAlexey Lapshin             if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
6739ff4be64SAlexey Lapshin                                             ArtificialTypeUnit))
6742357e899Savl-llvm               return std::move(Err);
6752357e899Savl-llvm           }
6762357e899Savl-llvm 
6772357e899Savl-llvm           CU.setStage(CompileUnit::Stage::Cloned);
6782357e899Savl-llvm           break;
6792357e899Savl-llvm 
6802357e899Savl-llvm         case CompileUnit::Stage::Cloned:
6812357e899Savl-llvm           // Update DIEs referencies.
6822357e899Savl-llvm           CU.updateDieRefPatchesWithClonedOffsets();
6832357e899Savl-llvm           CU.setStage(CompileUnit::Stage::PatchesUpdated);
6842357e899Savl-llvm           break;
6852357e899Savl-llvm 
6862357e899Savl-llvm         case CompileUnit::Stage::PatchesUpdated:
6872357e899Savl-llvm           // Cleanup resources.
6882357e899Savl-llvm           CU.cleanupDataAfterClonning();
6892357e899Savl-llvm           CU.setStage(CompileUnit::Stage::Cleaned);
6902357e899Savl-llvm           break;
6912357e899Savl-llvm 
6922357e899Savl-llvm         case CompileUnit::Stage::Cleaned:
6932357e899Savl-llvm           assert(false);
6942357e899Savl-llvm           break;
6952357e899Savl-llvm 
6962357e899Savl-llvm         case CompileUnit::Stage::Skipped:
6972357e899Savl-llvm           // Nothing to do.
6982357e899Savl-llvm           break;
6992357e899Savl-llvm         }
7002357e899Savl-llvm 
7012357e899Savl-llvm         return true;
7022357e899Savl-llvm       })) {
7032357e899Savl-llvm     CU.error(std::move(Err));
7042357e899Savl-llvm     CU.cleanupDataAfterClonning();
7052357e899Savl-llvm     CU.setStage(CompileUnit::Stage::Skipped);
7062357e899Savl-llvm   }
7072357e899Savl-llvm }
7082357e899Savl-llvm 
emitInvariantSections()7092357e899Savl-llvm Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {
7109ff4be64SAlexey Lapshin   if (!GlobalData.getTargetTriple().has_value())
7112357e899Savl-llvm     return Error::success();
7122357e899Savl-llvm 
7132357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS
7142357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
7152357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS
7162357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
7172357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS
7182357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
7192357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS
7202357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
7212357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS
7222357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
7232357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS
7242357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
7252357e899Savl-llvm   getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS
7262357e899Savl-llvm       << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
7272357e899Savl-llvm 
7282357e899Savl-llvm   return Error::success();
7292357e899Savl-llvm }
7302357e899Savl-llvm 
cloneAndEmitDebugFrame()7312357e899Savl-llvm Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() {
7329ff4be64SAlexey Lapshin   if (!GlobalData.getTargetTriple().has_value())
7332357e899Savl-llvm     return Error::success();
7342357e899Savl-llvm 
735acd7a688SKazu Hirata   if (InputDWARFFile.Dwarf == nullptr)
7362357e899Savl-llvm     return Error::success();
7372357e899Savl-llvm 
7382357e899Savl-llvm   const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
7392357e899Savl-llvm 
7402357e899Savl-llvm   StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
7412357e899Savl-llvm   if (OrigFrameData.empty())
7422357e899Savl-llvm     return Error::success();
7432357e899Savl-llvm 
7442357e899Savl-llvm   RangesTy AllUnitsRanges;
7452357e899Savl-llvm   for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
7462357e899Savl-llvm     for (auto CurRange : Unit->getFunctionRanges())
7472357e899Savl-llvm       AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
7482357e899Savl-llvm   }
7492357e899Savl-llvm 
7502357e899Savl-llvm   unsigned SrcAddrSize = InputDWARFObj.getAddressSize();
7512357e899Savl-llvm 
7522357e899Savl-llvm   SectionDescriptor &OutSection =
7532357e899Savl-llvm       getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame);
7542357e899Savl-llvm 
7552357e899Savl-llvm   DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);
7562357e899Savl-llvm   uint64_t InputOffset = 0;
7572357e899Savl-llvm 
7582357e899Savl-llvm   // Store the data of the CIEs defined in this object, keyed by their
7592357e899Savl-llvm   // offsets.
7602357e899Savl-llvm   DenseMap<uint64_t, StringRef> LocalCIES;
7612357e899Savl-llvm 
7622357e899Savl-llvm   /// The CIEs that have been emitted in the output section. The actual CIE
7632357e899Savl-llvm   /// data serves a the key to this StringMap.
7642357e899Savl-llvm   StringMap<uint32_t> EmittedCIEs;
7652357e899Savl-llvm 
7662357e899Savl-llvm   while (Data.isValidOffset(InputOffset)) {
7672357e899Savl-llvm     uint64_t EntryOffset = InputOffset;
7682357e899Savl-llvm     uint32_t InitialLength = Data.getU32(&InputOffset);
7692357e899Savl-llvm     if (InitialLength == 0xFFFFFFFF)
7702357e899Savl-llvm       return createFileError(InputDWARFObj.getFileName(),
7712357e899Savl-llvm                              createStringError(std::errc::invalid_argument,
7722357e899Savl-llvm                                                "Dwarf64 bits no supported"));
7732357e899Savl-llvm 
7742357e899Savl-llvm     uint32_t CIEId = Data.getU32(&InputOffset);
7752357e899Savl-llvm     if (CIEId == 0xFFFFFFFF) {
7762357e899Savl-llvm       // This is a CIE, store it.
7772357e899Savl-llvm       StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4);
7782357e899Savl-llvm       LocalCIES[EntryOffset] = CIEData;
7792357e899Savl-llvm       // The -4 is to account for the CIEId we just read.
7802357e899Savl-llvm       InputOffset += InitialLength - 4;
7812357e899Savl-llvm       continue;
7822357e899Savl-llvm     }
7832357e899Savl-llvm 
7842357e899Savl-llvm     uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
7852357e899Savl-llvm 
7862357e899Savl-llvm     // Some compilers seem to emit frame info that doesn't start at
7872357e899Savl-llvm     // the function entry point, thus we can't just lookup the address
7882357e899Savl-llvm     // in the debug map. Use the AddressInfo's range map to see if the FDE
7892357e899Savl-llvm     // describes something that we can relocate.
7902357e899Savl-llvm     std::optional<AddressRangeValuePair> Range =
7912357e899Savl-llvm         AllUnitsRanges.getRangeThatContains(Loc);
7922357e899Savl-llvm     if (!Range) {
7932357e899Savl-llvm       // The +4 is to account for the size of the InitialLength field itself.
7942357e899Savl-llvm       InputOffset = EntryOffset + InitialLength + 4;
7952357e899Savl-llvm       continue;
7962357e899Savl-llvm     }
7972357e899Savl-llvm 
7982357e899Savl-llvm     // This is an FDE, and we have a mapping.
7992357e899Savl-llvm     // Have we already emitted a corresponding CIE?
8002357e899Savl-llvm     StringRef CIEData = LocalCIES[CIEId];
8012357e899Savl-llvm     if (CIEData.empty())
8022357e899Savl-llvm       return createFileError(
8032357e899Savl-llvm           InputDWARFObj.getFileName(),
8042357e899Savl-llvm           createStringError(std::errc::invalid_argument,
8052357e899Savl-llvm                             "Inconsistent debug_frame content. Dropping."));
8062357e899Savl-llvm 
8072357e899Savl-llvm     uint64_t OffsetToCIERecord = OutSection.OS.tell();
8082357e899Savl-llvm 
8092357e899Savl-llvm     // Look if we already emitted a CIE that corresponds to the
8102357e899Savl-llvm     // referenced one (the CIE data is the key of that lookup).
8112357e899Savl-llvm     auto IteratorInserted =
8122357e899Savl-llvm         EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord));
8132357e899Savl-llvm     OffsetToCIERecord = IteratorInserted.first->getValue();
8142357e899Savl-llvm 
8152357e899Savl-llvm     // Emit CIE for this ID if it is not emitted yet.
8162357e899Savl-llvm     if (IteratorInserted.second)
8172357e899Savl-llvm       OutSection.OS << CIEData;
8182357e899Savl-llvm 
8192357e899Savl-llvm     // Remember offset to the FDE record, so that we might update
8202357e899Savl-llvm     // field referencing CIE record(containing OffsetToCIERecord),
8212357e899Savl-llvm     // when final offsets are known. OffsetToCIERecord(which is written later)
8222357e899Savl-llvm     // is local to the current .debug_frame section, it should be updated
8232357e899Savl-llvm     // with final offset of the .debug_frame section.
8242357e899Savl-llvm     OutSection.notePatch(
8252357e899Savl-llvm         DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});
8262357e899Savl-llvm 
8272357e899Savl-llvm     // Emit the FDE with updated address and CIE pointer.
8282357e899Savl-llvm     // (4 + AddrSize) is the size of the CIEId + initial_location
8292357e899Savl-llvm     // fields that will get reconstructed by emitFDE().
8302357e899Savl-llvm     unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
8312357e899Savl-llvm     emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value,
8322357e899Savl-llvm             OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection);
8332357e899Savl-llvm     InputOffset += FDERemainingBytes;
8342357e899Savl-llvm   }
8352357e899Savl-llvm 
8362357e899Savl-llvm   return Error::success();
8372357e899Savl-llvm }
8382357e899Savl-llvm 
8392357e899Savl-llvm /// Emit a FDE into the debug_frame section. \p FDEBytes
8402357e899Savl-llvm /// contains the FDE data without the length, CIE offset and address
8412357e899Savl-llvm /// which will be replaced with the parameter values.
emitFDE(uint32_t CIEOffset,uint32_t AddrSize,uint64_t Address,StringRef FDEBytes,SectionDescriptor & Section)8422357e899Savl-llvm void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset,
8432357e899Savl-llvm                                            uint32_t AddrSize, uint64_t Address,
8442357e899Savl-llvm                                            StringRef FDEBytes,
8452357e899Savl-llvm                                            SectionDescriptor &Section) {
8462357e899Savl-llvm   Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
8472357e899Savl-llvm   Section.emitIntVal(CIEOffset, 4);
8482357e899Savl-llvm   Section.emitIntVal(Address, AddrSize);
8492357e899Savl-llvm   Section.OS.write(FDEBytes.data(), FDEBytes.size());
8502357e899Savl-llvm }
8512357e899Savl-llvm 
glueCompileUnitsAndWriteToTheOutput()8522357e899Savl-llvm void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {
8539ff4be64SAlexey Lapshin   if (!GlobalData.getTargetTriple().has_value())
8542357e899Savl-llvm     return;
8559ff4be64SAlexey Lapshin   assert(SectionHandler);
8562357e899Savl-llvm 
8572357e899Savl-llvm   // Go through all object files, all compile units and assign
8582357e899Savl-llvm   // offsets to them.
8592357e899Savl-llvm   assignOffsets();
8602357e899Savl-llvm 
8612357e899Savl-llvm   // Patch size/offsets fields according to the assigned CU offsets.
8622357e899Savl-llvm   patchOffsetsAndSizes();
8632357e899Savl-llvm 
8642357e899Savl-llvm   // Emit common sections and write debug tables from all object files/compile
8652357e899Savl-llvm   // units into the resulting file.
8662357e899Savl-llvm   emitCommonSectionsAndWriteCompileUnitsToTheOutput();
8672357e899Savl-llvm 
868acd7a688SKazu Hirata   if (ArtificialTypeUnit != nullptr)
8692357e899Savl-llvm     ArtificialTypeUnit.reset();
8702357e899Savl-llvm 
8712357e899Savl-llvm   // Write common debug sections into the resulting file.
8722357e899Savl-llvm   writeCommonSectionsToTheOutput();
8732357e899Savl-llvm 
8742357e899Savl-llvm   // Cleanup data.
8752357e899Savl-llvm   cleanupDataAfterDWARFOutputIsWritten();
8762357e899Savl-llvm 
8772357e899Savl-llvm   if (GlobalData.getOptions().Statistics)
8782357e899Savl-llvm     printStatistic();
8792357e899Savl-llvm }
8802357e899Savl-llvm 
printStatistic()8812357e899Savl-llvm void DWARFLinkerImpl::printStatistic() {
8822357e899Savl-llvm 
8832357e899Savl-llvm   // For each object file map how many bytes were emitted.
8842357e899Savl-llvm   StringMap<DebugInfoSize> SizeByObject;
8852357e899Savl-llvm 
8862357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
8872357e899Savl-llvm     uint64_t AllDebugInfoSectionsSize = 0;
8882357e899Savl-llvm 
8892357e899Savl-llvm     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
8902357e899Savl-llvm       if (std::optional<SectionDescriptor *> DebugInfo =
8912357e899Savl-llvm               CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
8922357e899Savl-llvm         AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
8932357e899Savl-llvm 
8942357e899Savl-llvm     SizeByObject[Context->InputDWARFFile.FileName].Input =
8952357e899Savl-llvm         Context->OriginalDebugInfoSize;
8962357e899Savl-llvm     SizeByObject[Context->InputDWARFFile.FileName].Output =
8972357e899Savl-llvm         AllDebugInfoSectionsSize;
8982357e899Savl-llvm   }
8992357e899Savl-llvm 
9002357e899Savl-llvm   // Create a vector sorted in descending order by output size.
9012357e899Savl-llvm   std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
9022357e899Savl-llvm   for (auto &E : SizeByObject)
9032357e899Savl-llvm     Sorted.emplace_back(E.first(), E.second);
9042357e899Savl-llvm   llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
9052357e899Savl-llvm     return LHS.second.Output > RHS.second.Output;
9062357e899Savl-llvm   });
9072357e899Savl-llvm 
9082357e899Savl-llvm   auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
9092357e899Savl-llvm     const float Difference = Output - Input;
9102357e899Savl-llvm     const float Sum = Input + Output;
9112357e899Savl-llvm     if (Sum == 0)
9122357e899Savl-llvm       return 0;
9132357e899Savl-llvm     return (Difference / (Sum / 2));
9142357e899Savl-llvm   };
9152357e899Savl-llvm 
9162357e899Savl-llvm   int64_t InputTotal = 0;
9172357e899Savl-llvm   int64_t OutputTotal = 0;
9182357e899Savl-llvm   const char *FormatStr = "{0,-45} {1,10}b  {2,10}b {3,8:P}\n";
9192357e899Savl-llvm 
9202357e899Savl-llvm   // Print header.
9212357e899Savl-llvm   outs() << ".debug_info section size (in bytes)\n";
9222357e899Savl-llvm   outs() << "----------------------------------------------------------------"
9232357e899Savl-llvm             "---------------\n";
9242357e899Savl-llvm   outs() << "Filename                                           Object       "
9252357e899Savl-llvm             "  dSYM   Change\n";
9262357e899Savl-llvm   outs() << "----------------------------------------------------------------"
9272357e899Savl-llvm             "---------------\n";
9282357e899Savl-llvm 
9292357e899Savl-llvm   // Print body.
9302357e899Savl-llvm   for (auto &E : Sorted) {
9312357e899Savl-llvm     InputTotal += E.second.Input;
9322357e899Savl-llvm     OutputTotal += E.second.Output;
9332357e899Savl-llvm     llvm::outs() << formatv(
9342357e899Savl-llvm         FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
9352357e899Savl-llvm         E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
9362357e899Savl-llvm   }
9372357e899Savl-llvm   // Print total and footer.
9382357e899Savl-llvm   outs() << "----------------------------------------------------------------"
9392357e899Savl-llvm             "---------------\n";
9402357e899Savl-llvm   llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
9412357e899Savl-llvm                           ComputePercentange(InputTotal, OutputTotal));
9422357e899Savl-llvm   outs() << "----------------------------------------------------------------"
9432357e899Savl-llvm             "---------------\n\n";
9442357e899Savl-llvm }
9452357e899Savl-llvm 
assignOffsets()9462357e899Savl-llvm void DWARFLinkerImpl::assignOffsets() {
9472357e899Savl-llvm   llvm::parallel::TaskGroup TGroup;
9482357e899Savl-llvm   TGroup.spawn([&]() { assignOffsetsToStrings(); });
9492357e899Savl-llvm   TGroup.spawn([&]() { assignOffsetsToSections(); });
9502357e899Savl-llvm }
9512357e899Savl-llvm 
assignOffsetsToStrings()9522357e899Savl-llvm void DWARFLinkerImpl::assignOffsetsToStrings() {
9532357e899Savl-llvm   size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
9542357e899Savl-llvm   uint64_t CurDebugStrOffset =
9552357e899Savl-llvm       1; // start from 1 to take into account zero entry.
9562357e899Savl-llvm   size_t CurDebugLineStrIndex = 0;
9572357e899Savl-llvm   uint64_t CurDebugLineStrOffset = 0;
9582357e899Savl-llvm 
9592357e899Savl-llvm   // Enumerates all strings, add them into the DwarfStringPoolEntry map,
9602357e899Savl-llvm   // assign offset and index to the string if it is not indexed yet.
9612357e899Savl-llvm   forEachOutputString([&](StringDestinationKind Kind,
9622357e899Savl-llvm                           const StringEntry *String) {
9632357e899Savl-llvm     switch (Kind) {
9642357e899Savl-llvm     case StringDestinationKind::DebugStr: {
9652357e899Savl-llvm       DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String);
9662357e899Savl-llvm       assert(Entry != nullptr);
9672357e899Savl-llvm 
9682357e899Savl-llvm       if (!Entry->isIndexed()) {
9692357e899Savl-llvm         Entry->Offset = CurDebugStrOffset;
9702357e899Savl-llvm         CurDebugStrOffset += Entry->String.size() + 1;
9712357e899Savl-llvm         Entry->Index = CurDebugStrIndex++;
9722357e899Savl-llvm       }
9732357e899Savl-llvm     } break;
9742357e899Savl-llvm     case StringDestinationKind::DebugLineStr: {
9752357e899Savl-llvm       DwarfStringPoolEntryWithExtString *Entry =
9762357e899Savl-llvm           DebugLineStrStrings.add(String);
9772357e899Savl-llvm       assert(Entry != nullptr);
9782357e899Savl-llvm 
9792357e899Savl-llvm       if (!Entry->isIndexed()) {
9802357e899Savl-llvm         Entry->Offset = CurDebugLineStrOffset;
9812357e899Savl-llvm         CurDebugLineStrOffset += Entry->String.size() + 1;
9822357e899Savl-llvm         Entry->Index = CurDebugLineStrIndex++;
9832357e899Savl-llvm       }
9842357e899Savl-llvm     } break;
9852357e899Savl-llvm     }
9862357e899Savl-llvm   });
9872357e899Savl-llvm }
9882357e899Savl-llvm 
assignOffsetsToSections()9892357e899Savl-llvm void DWARFLinkerImpl::assignOffsetsToSections() {
9902357e899Savl-llvm   std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
9912357e899Savl-llvm 
9922357e899Savl-llvm   forEachObjectSectionsSet([&](OutputSections &UnitSections) {
9932357e899Savl-llvm     UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
9942357e899Savl-llvm   });
9952357e899Savl-llvm }
9962357e899Savl-llvm 
forEachOutputString(function_ref<void (StringDestinationKind Kind,const StringEntry * String)> StringHandler)9972357e899Savl-llvm void DWARFLinkerImpl::forEachOutputString(
9982357e899Savl-llvm     function_ref<void(StringDestinationKind Kind, const StringEntry *String)>
9992357e899Savl-llvm         StringHandler) {
10002357e899Savl-llvm   // To save space we do not create any separate string table.
10012357e899Savl-llvm   // We use already allocated string patches and accelerator entries:
10022357e899Savl-llvm   // enumerate them in natural order and assign offsets.
10032357e899Savl-llvm   // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
10042357e899Savl-llvm   // sections in the same order as they were assigned offsets.
10052357e899Savl-llvm   forEachCompileUnit([&](CompileUnit *CU) {
10062357e899Savl-llvm     CU->forEach([&](SectionDescriptor &OutSection) {
10072357e899Savl-llvm       OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
10082357e899Savl-llvm         StringHandler(StringDestinationKind::DebugStr, Patch.String);
10092357e899Savl-llvm       });
10102357e899Savl-llvm 
10112357e899Savl-llvm       OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
10122357e899Savl-llvm         StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
10132357e899Savl-llvm       });
10142357e899Savl-llvm     });
10152357e899Savl-llvm 
10162357e899Savl-llvm     CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
10172357e899Savl-llvm       StringHandler(DebugStr, Info.String);
10182357e899Savl-llvm     });
10192357e899Savl-llvm   });
10202357e899Savl-llvm 
1021acd7a688SKazu Hirata   if (ArtificialTypeUnit != nullptr) {
10222357e899Savl-llvm     ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
10232357e899Savl-llvm       OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
10242357e899Savl-llvm         StringHandler(StringDestinationKind::DebugStr, Patch.String);
10252357e899Savl-llvm       });
10262357e899Savl-llvm 
10272357e899Savl-llvm       OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
10282357e899Savl-llvm         StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
10292357e899Savl-llvm       });
10302357e899Savl-llvm 
10312357e899Savl-llvm       OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
10322357e899Savl-llvm         if (Patch.Die == nullptr)
10332357e899Savl-llvm           return;
10342357e899Savl-llvm 
10352357e899Savl-llvm         StringHandler(StringDestinationKind::DebugStr, Patch.String);
10362357e899Savl-llvm       });
10372357e899Savl-llvm 
10382357e899Savl-llvm       OutSection.ListDebugTypeLineStrPatch.forEach(
10392357e899Savl-llvm           [&](DebugTypeLineStrPatch &Patch) {
10402357e899Savl-llvm             if (Patch.Die == nullptr)
10412357e899Savl-llvm               return;
10422357e899Savl-llvm 
10432357e899Savl-llvm             StringHandler(StringDestinationKind::DebugStr, Patch.String);
10442357e899Savl-llvm           });
10452357e899Savl-llvm     });
10462357e899Savl-llvm   }
10472357e899Savl-llvm }
10482357e899Savl-llvm 
forEachObjectSectionsSet(function_ref<void (OutputSections &)> SectionsSetHandler)10492357e899Savl-llvm void DWARFLinkerImpl::forEachObjectSectionsSet(
10502357e899Savl-llvm     function_ref<void(OutputSections &)> SectionsSetHandler) {
10512357e899Savl-llvm   // Handle artificial type unit first.
1052acd7a688SKazu Hirata   if (ArtificialTypeUnit != nullptr)
10532357e899Savl-llvm     SectionsSetHandler(*ArtificialTypeUnit);
10542357e899Savl-llvm 
10552357e899Savl-llvm   // Then all modules(before regular compilation units).
10562357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10572357e899Savl-llvm     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
10582357e899Savl-llvm       if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
10592357e899Savl-llvm         SectionsSetHandler(*ModuleUnit.Unit);
10602357e899Savl-llvm 
10612357e899Savl-llvm   // Finally all compilation units.
10622357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
10632357e899Savl-llvm     // Handle object file common sections.
10642357e899Savl-llvm     SectionsSetHandler(*Context);
10652357e899Savl-llvm 
10662357e899Savl-llvm     // Handle compilation units.
10672357e899Savl-llvm     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
10682357e899Savl-llvm       if (CU->getStage() != CompileUnit::Stage::Skipped)
10692357e899Savl-llvm         SectionsSetHandler(*CU);
10702357e899Savl-llvm   }
10712357e899Savl-llvm }
10722357e899Savl-llvm 
forEachCompileAndTypeUnit(function_ref<void (DwarfUnit * CU)> UnitHandler)10732357e899Savl-llvm void DWARFLinkerImpl::forEachCompileAndTypeUnit(
10742357e899Savl-llvm     function_ref<void(DwarfUnit *CU)> UnitHandler) {
1075acd7a688SKazu Hirata   if (ArtificialTypeUnit != nullptr)
10762357e899Savl-llvm     UnitHandler(ArtificialTypeUnit.get());
10772357e899Savl-llvm 
10782357e899Savl-llvm   // Enumerate module units.
10792357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10802357e899Savl-llvm     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
10812357e899Savl-llvm       if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
10822357e899Savl-llvm         UnitHandler(ModuleUnit.Unit.get());
10832357e899Savl-llvm 
10842357e899Savl-llvm   // Enumerate compile units.
10852357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10862357e899Savl-llvm     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
10872357e899Savl-llvm       if (CU->getStage() != CompileUnit::Stage::Skipped)
10882357e899Savl-llvm         UnitHandler(CU.get());
10892357e899Savl-llvm }
10902357e899Savl-llvm 
forEachCompileUnit(function_ref<void (CompileUnit * CU)> UnitHandler)10912357e899Savl-llvm void DWARFLinkerImpl::forEachCompileUnit(
10922357e899Savl-llvm     function_ref<void(CompileUnit *CU)> UnitHandler) {
10932357e899Savl-llvm   // Enumerate module units.
10942357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10952357e899Savl-llvm     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
10962357e899Savl-llvm       if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
10972357e899Savl-llvm         UnitHandler(ModuleUnit.Unit.get());
10982357e899Savl-llvm 
10992357e899Savl-llvm   // Enumerate compile units.
11002357e899Savl-llvm   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
11012357e899Savl-llvm     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
11022357e899Savl-llvm       if (CU->getStage() != CompileUnit::Stage::Skipped)
11032357e899Savl-llvm         UnitHandler(CU.get());
11042357e899Savl-llvm }
11052357e899Savl-llvm 
patchOffsetsAndSizes()11062357e899Savl-llvm void DWARFLinkerImpl::patchOffsetsAndSizes() {
11072357e899Savl-llvm   forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
11082357e899Savl-llvm     SectionsSet.forEach([&](SectionDescriptor &OutSection) {
11092357e899Savl-llvm       SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
11102357e899Savl-llvm                                ArtificialTypeUnit.get());
11112357e899Savl-llvm     });
11122357e899Savl-llvm   });
11132357e899Savl-llvm }
11142357e899Savl-llvm 
emitCommonSectionsAndWriteCompileUnitsToTheOutput()11152357e899Savl-llvm void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {
11162357e899Savl-llvm   llvm::parallel::TaskGroup TG;
11172357e899Savl-llvm 
11182357e899Savl-llvm   // Create section descriptors ahead if they are not exist at the moment.
11192357e899Savl-llvm   // SectionDescriptors container is not thread safe. Thus we should be sure
11202357e899Savl-llvm   // that descriptors would not be created in following parallel tasks.
11212357e899Savl-llvm 
11222357e899Savl-llvm   CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
11232357e899Savl-llvm   CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
11242357e899Savl-llvm 
11252357e899Savl-llvm   if (llvm::is_contained(GlobalData.Options.AccelTables,
11262357e899Savl-llvm                          AccelTableKind::Apple)) {
11272357e899Savl-llvm     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
11282357e899Savl-llvm     CommonSections.getOrCreateSectionDescriptor(
11292357e899Savl-llvm         DebugSectionKind::AppleNamespaces);
11302357e899Savl-llvm     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
11312357e899Savl-llvm     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
11322357e899Savl-llvm   }
11332357e899Savl-llvm 
11342357e899Savl-llvm   if (llvm::is_contained(GlobalData.Options.AccelTables,
11352357e899Savl-llvm                          AccelTableKind::DebugNames))
11362357e899Savl-llvm     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
11372357e899Savl-llvm 
11382357e899Savl-llvm   // Emit .debug_str and .debug_line_str sections.
11392357e899Savl-llvm   TG.spawn([&]() { emitStringSections(); });
11402357e899Savl-llvm 
11412357e899Savl-llvm   if (llvm::is_contained(GlobalData.Options.AccelTables,
11422357e899Savl-llvm                          AccelTableKind::Apple)) {
11432357e899Savl-llvm     // Emit apple accelerator sections.
11449ff4be64SAlexey Lapshin     TG.spawn([&]() {
11459ff4be64SAlexey Lapshin       emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
11469ff4be64SAlexey Lapshin     });
11472357e899Savl-llvm   }
11482357e899Savl-llvm 
11492357e899Savl-llvm   if (llvm::is_contained(GlobalData.Options.AccelTables,
11502357e899Savl-llvm                          AccelTableKind::DebugNames)) {
11512357e899Savl-llvm     // Emit .debug_names section.
11529ff4be64SAlexey Lapshin     TG.spawn([&]() {
11539ff4be64SAlexey Lapshin       emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
11549ff4be64SAlexey Lapshin     });
11552357e899Savl-llvm   }
11562357e899Savl-llvm 
11572357e899Savl-llvm   // Write compile units to the output file.
11582357e899Savl-llvm   TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
11592357e899Savl-llvm }
11602357e899Savl-llvm 
emitStringSections()11612357e899Savl-llvm void DWARFLinkerImpl::emitStringSections() {
11622357e899Savl-llvm   uint64_t DebugStrNextOffset = 0;
11632357e899Savl-llvm   uint64_t DebugLineStrNextOffset = 0;
11642357e899Savl-llvm 
11652357e899Savl-llvm   // Emit zero length string. Accelerator tables does not work correctly
11662357e899Savl-llvm   // if the first string is not zero length string.
11672357e899Savl-llvm   CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
11682357e899Savl-llvm       .emitInplaceString("");
11692357e899Savl-llvm   DebugStrNextOffset++;
11702357e899Savl-llvm 
11712357e899Savl-llvm   forEachOutputString(
11722357e899Savl-llvm       [&](StringDestinationKind Kind, const StringEntry *String) {
11732357e899Savl-llvm         switch (Kind) {
11742357e899Savl-llvm         case StringDestinationKind::DebugStr: {
11752357e899Savl-llvm           DwarfStringPoolEntryWithExtString *StringToEmit =
11762357e899Savl-llvm               DebugStrStrings.getExistingEntry(String);
11772357e899Savl-llvm           assert(StringToEmit->isIndexed());
11782357e899Savl-llvm 
11792357e899Savl-llvm           // Strings may be repeated. Use accumulated DebugStrNextOffset
11802357e899Savl-llvm           // to understand whether corresponding string is already emitted.
11812357e899Savl-llvm           // Skip string if its offset less than accumulated offset.
11822357e899Savl-llvm           if (StringToEmit->Offset >= DebugStrNextOffset) {
11832357e899Savl-llvm             DebugStrNextOffset =
11842357e899Savl-llvm                 StringToEmit->Offset + StringToEmit->String.size() + 1;
11852357e899Savl-llvm             // Emit the string itself.
11862357e899Savl-llvm             CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
11872357e899Savl-llvm                 .emitInplaceString(StringToEmit->String);
11882357e899Savl-llvm           }
11892357e899Savl-llvm         } break;
11902357e899Savl-llvm         case StringDestinationKind::DebugLineStr: {
11912357e899Savl-llvm           DwarfStringPoolEntryWithExtString *StringToEmit =
11922357e899Savl-llvm               DebugLineStrStrings.getExistingEntry(String);
11932357e899Savl-llvm           assert(StringToEmit->isIndexed());
11942357e899Savl-llvm 
11952357e899Savl-llvm           // Strings may be repeated. Use accumulated DebugLineStrStrings
11962357e899Savl-llvm           // to understand whether corresponding string is already emitted.
11972357e899Savl-llvm           // Skip string if its offset less than accumulated offset.
11982357e899Savl-llvm           if (StringToEmit->Offset >= DebugLineStrNextOffset) {
11992357e899Savl-llvm             DebugLineStrNextOffset =
12002357e899Savl-llvm                 StringToEmit->Offset + StringToEmit->String.size() + 1;
12012357e899Savl-llvm             // Emit the string itself.
12022357e899Savl-llvm             CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr)
12032357e899Savl-llvm                 .emitInplaceString(StringToEmit->String);
12042357e899Savl-llvm           }
12052357e899Savl-llvm         } break;
12062357e899Savl-llvm         }
12072357e899Savl-llvm       });
12082357e899Savl-llvm }
12092357e899Savl-llvm 
emitAppleAcceleratorSections(const Triple & TargetTriple)12102357e899Savl-llvm void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
12112357e899Savl-llvm   AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
12122357e899Savl-llvm   AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
12132357e899Savl-llvm   AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;
12142357e899Savl-llvm   AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
12152357e899Savl-llvm 
12162357e899Savl-llvm   forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
12172357e899Savl-llvm     CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
12182357e899Savl-llvm       uint64_t OutOffset = Info.OutOffset;
12192357e899Savl-llvm       switch (Info.Type) {
12202357e899Savl-llvm       case DwarfUnit::AccelType::None: {
12212357e899Savl-llvm         llvm_unreachable("Unknown accelerator record");
12222357e899Savl-llvm       } break;
12232357e899Savl-llvm       case DwarfUnit::AccelType::Namespace: {
12242357e899Savl-llvm         AppleNamespaces.addName(
12252357e899Savl-llvm             *DebugStrStrings.getExistingEntry(Info.String),
12262357e899Savl-llvm             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12272357e899Savl-llvm                 OutOffset);
12282357e899Savl-llvm       } break;
12292357e899Savl-llvm       case DwarfUnit::AccelType::Name: {
12302357e899Savl-llvm         AppleNames.addName(
12312357e899Savl-llvm             *DebugStrStrings.getExistingEntry(Info.String),
12322357e899Savl-llvm             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12332357e899Savl-llvm                 OutOffset);
12342357e899Savl-llvm       } break;
12352357e899Savl-llvm       case DwarfUnit::AccelType::ObjC: {
12362357e899Savl-llvm         AppleObjC.addName(
12372357e899Savl-llvm             *DebugStrStrings.getExistingEntry(Info.String),
12382357e899Savl-llvm             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12392357e899Savl-llvm                 OutOffset);
12402357e899Savl-llvm       } break;
12412357e899Savl-llvm       case DwarfUnit::AccelType::Type: {
12422357e899Savl-llvm         AppleTypes.addName(
12432357e899Savl-llvm             *DebugStrStrings.getExistingEntry(Info.String),
12442357e899Savl-llvm             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12452357e899Savl-llvm                 OutOffset,
12462357e899Savl-llvm             Info.Tag,
12472357e899Savl-llvm             Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
12482357e899Savl-llvm                                          : 0,
12492357e899Savl-llvm             Info.QualifiedNameHash);
12502357e899Savl-llvm       } break;
12512357e899Savl-llvm       }
12522357e899Savl-llvm     });
12532357e899Savl-llvm   });
12542357e899Savl-llvm 
12552357e899Savl-llvm   {
12562357e899Savl-llvm     // FIXME: we use AsmPrinter to emit accelerator sections.
12572357e899Savl-llvm     // It might be beneficial to directly emit accelerator data
12582357e899Savl-llvm     // to the raw_svector_ostream.
12592357e899Savl-llvm     SectionDescriptor &OutSection =
12602357e899Savl-llvm         CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces);
12612357e899Savl-llvm     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
12622357e899Savl-llvm                              OutSection.OS);
12632357e899Savl-llvm     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
12642357e899Savl-llvm       consumeError(std::move(Err));
12652357e899Savl-llvm       return;
12662357e899Savl-llvm     }
12672357e899Savl-llvm 
12682357e899Savl-llvm     // Emit table.
12692357e899Savl-llvm     Emitter.emitAppleNamespaces(AppleNamespaces);
12702357e899Savl-llvm     Emitter.finish();
12712357e899Savl-llvm 
12722357e899Savl-llvm     // Set start offset and size for output section.
12732357e899Savl-llvm     OutSection.setSizesForSectionCreatedByAsmPrinter();
12742357e899Savl-llvm   }
12752357e899Savl-llvm 
12762357e899Savl-llvm   {
12772357e899Savl-llvm     // FIXME: we use AsmPrinter to emit accelerator sections.
12782357e899Savl-llvm     // It might be beneficial to directly emit accelerator data
12792357e899Savl-llvm     // to the raw_svector_ostream.
12802357e899Savl-llvm     SectionDescriptor &OutSection =
12812357e899Savl-llvm         CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
12822357e899Savl-llvm     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
12832357e899Savl-llvm                              OutSection.OS);
12842357e899Savl-llvm     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
12852357e899Savl-llvm       consumeError(std::move(Err));
12862357e899Savl-llvm       return;
12872357e899Savl-llvm     }
12882357e899Savl-llvm 
12892357e899Savl-llvm     // Emit table.
12902357e899Savl-llvm     Emitter.emitAppleNames(AppleNames);
12912357e899Savl-llvm     Emitter.finish();
12922357e899Savl-llvm 
12932357e899Savl-llvm     // Set start offset ans size for output section.
12942357e899Savl-llvm     OutSection.setSizesForSectionCreatedByAsmPrinter();
12952357e899Savl-llvm   }
12962357e899Savl-llvm 
12972357e899Savl-llvm   {
12982357e899Savl-llvm     // FIXME: we use AsmPrinter to emit accelerator sections.
12992357e899Savl-llvm     // It might be beneficial to directly emit accelerator data
13002357e899Savl-llvm     // to the raw_svector_ostream.
13012357e899Savl-llvm     SectionDescriptor &OutSection =
13022357e899Savl-llvm         CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
13032357e899Savl-llvm     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
13042357e899Savl-llvm                              OutSection.OS);
13052357e899Savl-llvm     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
13062357e899Savl-llvm       consumeError(std::move(Err));
13072357e899Savl-llvm       return;
13082357e899Savl-llvm     }
13092357e899Savl-llvm 
13102357e899Savl-llvm     // Emit table.
13112357e899Savl-llvm     Emitter.emitAppleObjc(AppleObjC);
13122357e899Savl-llvm     Emitter.finish();
13132357e899Savl-llvm 
13142357e899Savl-llvm     // Set start offset ans size for output section.
13152357e899Savl-llvm     OutSection.setSizesForSectionCreatedByAsmPrinter();
13162357e899Savl-llvm   }
13172357e899Savl-llvm 
13182357e899Savl-llvm   {
13192357e899Savl-llvm     // FIXME: we use AsmPrinter to emit accelerator sections.
13202357e899Savl-llvm     // It might be beneficial to directly emit accelerator data
13212357e899Savl-llvm     // to the raw_svector_ostream.
13222357e899Savl-llvm     SectionDescriptor &OutSection =
13232357e899Savl-llvm         CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
13242357e899Savl-llvm     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
13252357e899Savl-llvm                              OutSection.OS);
13262357e899Savl-llvm     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
13272357e899Savl-llvm       consumeError(std::move(Err));
13282357e899Savl-llvm       return;
13292357e899Savl-llvm     }
13302357e899Savl-llvm 
13312357e899Savl-llvm     // Emit table.
13322357e899Savl-llvm     Emitter.emitAppleTypes(AppleTypes);
13332357e899Savl-llvm     Emitter.finish();
13342357e899Savl-llvm 
13352357e899Savl-llvm     // Set start offset ans size for output section.
13362357e899Savl-llvm     OutSection.setSizesForSectionCreatedByAsmPrinter();
13372357e899Savl-llvm   }
13382357e899Savl-llvm }
13392357e899Savl-llvm 
emitDWARFv5DebugNamesSection(const Triple & TargetTriple)13402357e899Savl-llvm void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
13412357e899Savl-llvm   std::unique_ptr<DWARF5AccelTable> DebugNames;
13422357e899Savl-llvm 
13432357e899Savl-llvm   DebugNamesUnitsOffsets CompUnits;
13442357e899Savl-llvm   CompUnitIDToIdx CUidToIdx;
13452357e899Savl-llvm 
13462357e899Savl-llvm   unsigned Id = 0;
13472357e899Savl-llvm 
13482357e899Savl-llvm   forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
13492357e899Savl-llvm     bool HasRecords = false;
13502357e899Savl-llvm     CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
1351acd7a688SKazu Hirata       if (DebugNames == nullptr)
13522357e899Savl-llvm         DebugNames = std::make_unique<DWARF5AccelTable>();
13532357e899Savl-llvm 
13542357e899Savl-llvm       HasRecords = true;
13552357e899Savl-llvm       switch (Info.Type) {
13562357e899Savl-llvm       case DwarfUnit::AccelType::Name:
13572357e899Savl-llvm       case DwarfUnit::AccelType::Namespace:
13582357e899Savl-llvm       case DwarfUnit::AccelType::Type: {
13590cb2ae33SFlorian Mayer         DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
13600cb2ae33SFlorian Mayer                             Info.OutOffset, std::nullopt /*ParentDIEOffset*/,
13619b7b1beeSAlexander Yermolovich                             Info.Tag, CU->getUniqueID(),
13629b7b1beeSAlexander Yermolovich                             CU->getTag() == dwarf::DW_TAG_type_unit);
13632357e899Savl-llvm       } break;
13642357e899Savl-llvm 
13652357e899Savl-llvm       default:
13662357e899Savl-llvm         break; // Nothing to do.
13672357e899Savl-llvm       };
13682357e899Savl-llvm     });
13692357e899Savl-llvm 
13702357e899Savl-llvm     if (HasRecords) {
13712357e899Savl-llvm       CompUnits.push_back(
13722357e899Savl-llvm           CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
13732357e899Savl-llvm               .StartOffset);
13742357e899Savl-llvm       CUidToIdx[CU->getUniqueID()] = Id++;
13752357e899Savl-llvm     }
13762357e899Savl-llvm   });
13772357e899Savl-llvm 
1378acd7a688SKazu Hirata   if (DebugNames != nullptr) {
13792357e899Savl-llvm     // FIXME: we use AsmPrinter to emit accelerator sections.
13802357e899Savl-llvm     // It might be beneficial to directly emit accelerator data
13812357e899Savl-llvm     // to the raw_svector_ostream.
13822357e899Savl-llvm     SectionDescriptor &OutSection =
13832357e899Savl-llvm         CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
13842357e899Savl-llvm     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
13852357e899Savl-llvm                              OutSection.OS);
13862357e899Savl-llvm     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
13872357e899Savl-llvm       consumeError(std::move(Err));
13882357e899Savl-llvm       return;
13892357e899Savl-llvm     }
13902357e899Savl-llvm 
13912357e899Savl-llvm     // Emit table.
13922357e899Savl-llvm     Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
13932357e899Savl-llvm     Emitter.finish();
13942357e899Savl-llvm 
13952357e899Savl-llvm     // Set start offset ans size for output section.
13962357e899Savl-llvm     OutSection.setSizesForSectionCreatedByAsmPrinter();
13972357e899Savl-llvm   }
13982357e899Savl-llvm }
13992357e899Savl-llvm 
cleanupDataAfterDWARFOutputIsWritten()14002357e899Savl-llvm void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {
14012357e899Savl-llvm   GlobalData.getStringPool().clear();
14022357e899Savl-llvm   DebugStrStrings.clear();
14032357e899Savl-llvm   DebugLineStrStrings.clear();
14042357e899Savl-llvm }
14052357e899Savl-llvm 
writeCompileUnitsToTheOutput()14062357e899Savl-llvm void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {
14072357e899Savl-llvm   // Enumerate all sections and store them into the final emitter.
14082357e899Savl-llvm   forEachObjectSectionsSet([&](OutputSections &Sections) {
14099ff4be64SAlexey Lapshin     Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
14102357e899Savl-llvm       // Emit section content.
14119ff4be64SAlexey Lapshin       SectionHandler(OutSection);
14122357e899Savl-llvm     });
14132357e899Savl-llvm   });
14142357e899Savl-llvm }
14152357e899Savl-llvm 
writeCommonSectionsToTheOutput()14162357e899Savl-llvm void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {
14179ff4be64SAlexey Lapshin   CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
14189ff4be64SAlexey Lapshin     SectionHandler(OutSection);
14192357e899Savl-llvm   });
14202357e899Savl-llvm }
1421