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