11db9f3b2SDimitry Andric //=== DWARFLinkerImpl.cpp -------------------------------------------------===// 21db9f3b2SDimitry Andric // 31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61db9f3b2SDimitry Andric // 71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 81db9f3b2SDimitry Andric 91db9f3b2SDimitry Andric #include "DWARFLinkerImpl.h" 101db9f3b2SDimitry Andric #include "DIEGenerator.h" 111db9f3b2SDimitry Andric #include "DependencyTracker.h" 12297eecfbSDimitry Andric #include "llvm/DWARFLinker/Utils.h" 131db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 141db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h" 151db9f3b2SDimitry Andric #include "llvm/Support/Parallel.h" 161db9f3b2SDimitry Andric #include "llvm/Support/ThreadPool.h" 171db9f3b2SDimitry Andric 181db9f3b2SDimitry Andric using namespace llvm; 191db9f3b2SDimitry Andric using namespace dwarf_linker; 201db9f3b2SDimitry Andric using namespace dwarf_linker::parallel; 211db9f3b2SDimitry Andric 221db9f3b2SDimitry Andric DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler, 231db9f3b2SDimitry Andric MessageHandlerTy WarningHandler, 241db9f3b2SDimitry Andric TranslatorFuncTy StringsTranslator) 251db9f3b2SDimitry Andric : UniqueUnitID(0), DebugStrStrings(GlobalData), 261db9f3b2SDimitry Andric DebugLineStrStrings(GlobalData), CommonSections(GlobalData) { 271db9f3b2SDimitry Andric GlobalData.setTranslator(StringsTranslator); 281db9f3b2SDimitry Andric GlobalData.setErrorHandler(ErrorHandler); 291db9f3b2SDimitry Andric GlobalData.setWarningHandler(WarningHandler); 301db9f3b2SDimitry Andric } 311db9f3b2SDimitry Andric 321db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData, 331db9f3b2SDimitry Andric DWARFFile &File, 341db9f3b2SDimitry Andric StringMap<uint64_t> &ClangModules, 35*7a6dacacSDimitry Andric std::atomic<size_t> &UniqueUnitID) 361db9f3b2SDimitry Andric : OutputSections(GlobalData), InputDWARFFile(File), 37*7a6dacacSDimitry Andric ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) { 381db9f3b2SDimitry Andric 391db9f3b2SDimitry Andric if (File.Dwarf) { 401db9f3b2SDimitry Andric if (!File.Dwarf->compile_units().empty()) 411db9f3b2SDimitry Andric CompileUnits.reserve(File.Dwarf->getNumCompileUnits()); 421db9f3b2SDimitry Andric 431db9f3b2SDimitry Andric // Set context format&endianness based on the input file. 441db9f3b2SDimitry Andric Format.Version = File.Dwarf->getMaxVersion(); 451db9f3b2SDimitry Andric Format.AddrSize = File.Dwarf->getCUAddrSize(); 461db9f3b2SDimitry Andric Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little 471db9f3b2SDimitry Andric : llvm::endianness::big; 481db9f3b2SDimitry Andric } 491db9f3b2SDimitry Andric } 501db9f3b2SDimitry Andric 511db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit( 521db9f3b2SDimitry Andric DWARFFile &File, std::unique_ptr<CompileUnit> Unit) 531db9f3b2SDimitry Andric : File(File), Unit(std::move(Unit)) {} 541db9f3b2SDimitry Andric 551db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit( 561db9f3b2SDimitry Andric LinkContext::RefModuleUnit &&Other) 571db9f3b2SDimitry Andric : File(Other.File), Unit(std::move(Other.Unit)) {} 581db9f3b2SDimitry Andric 591db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::addModulesCompileUnit( 601db9f3b2SDimitry Andric LinkContext::RefModuleUnit &&Unit) { 611db9f3b2SDimitry Andric ModulesCompileUnits.emplace_back(std::move(Unit)); 621db9f3b2SDimitry Andric } 631db9f3b2SDimitry Andric 641db9f3b2SDimitry Andric void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader, 651db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded) { 661db9f3b2SDimitry Andric ObjectContexts.emplace_back(std::make_unique<LinkContext>( 67*7a6dacacSDimitry Andric GlobalData, File, ClangModules, UniqueUnitID)); 681db9f3b2SDimitry Andric 691db9f3b2SDimitry Andric if (ObjectContexts.back()->InputDWARFFile.Dwarf) { 701db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &CU : 711db9f3b2SDimitry Andric ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) { 721db9f3b2SDimitry Andric DWARFDie CUDie = CU->getUnitDIE(); 731db9f3b2SDimitry Andric OverallNumberOfCU++; 741db9f3b2SDimitry Andric 751db9f3b2SDimitry Andric if (!CUDie) 761db9f3b2SDimitry Andric continue; 771db9f3b2SDimitry Andric 781db9f3b2SDimitry Andric OnCUDieLoaded(*CU); 791db9f3b2SDimitry Andric 801db9f3b2SDimitry Andric // Register mofule reference. 811db9f3b2SDimitry Andric if (!GlobalData.getOptions().UpdateIndexTablesOnly) 821db9f3b2SDimitry Andric ObjectContexts.back()->registerModuleReference(CUDie, Loader, 831db9f3b2SDimitry Andric OnCUDieLoaded); 841db9f3b2SDimitry Andric } 851db9f3b2SDimitry Andric } 861db9f3b2SDimitry Andric } 871db9f3b2SDimitry Andric 881db9f3b2SDimitry Andric void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) { 891db9f3b2SDimitry Andric ObjectContexts.reserve(ObjFilesNum); 901db9f3b2SDimitry Andric } 911db9f3b2SDimitry Andric 921db9f3b2SDimitry Andric Error DWARFLinkerImpl::link() { 931db9f3b2SDimitry Andric // reset compile unit unique ID counter. 941db9f3b2SDimitry Andric UniqueUnitID = 0; 951db9f3b2SDimitry Andric 961db9f3b2SDimitry Andric if (Error Err = validateAndUpdateOptions()) 971db9f3b2SDimitry Andric return Err; 981db9f3b2SDimitry Andric 991db9f3b2SDimitry Andric dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion, 1001db9f3b2SDimitry Andric 0, dwarf::DwarfFormat::DWARF32}; 1011db9f3b2SDimitry Andric llvm::endianness GlobalEndianness = llvm::endianness::native; 1021db9f3b2SDimitry Andric 103*7a6dacacSDimitry Andric if (std::optional<std::reference_wrapper<const Triple>> CurTriple = 104*7a6dacacSDimitry Andric GlobalData.getTargetTriple()) { 105*7a6dacacSDimitry Andric GlobalEndianness = (*CurTriple).get().isLittleEndian() 1061db9f3b2SDimitry Andric ? llvm::endianness::little 1071db9f3b2SDimitry Andric : llvm::endianness::big; 1081db9f3b2SDimitry Andric } 1091db9f3b2SDimitry Andric std::optional<uint16_t> Language; 1101db9f3b2SDimitry Andric 1111db9f3b2SDimitry Andric for (std::unique_ptr<LinkContext> &Context : ObjectContexts) { 1121db9f3b2SDimitry Andric if (Context->InputDWARFFile.Dwarf.get() == nullptr) { 1131db9f3b2SDimitry Andric Context->setOutputFormat(Context->getFormParams(), GlobalEndianness); 1141db9f3b2SDimitry Andric continue; 1151db9f3b2SDimitry Andric } 1161db9f3b2SDimitry Andric 1171db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) { 118*7a6dacacSDimitry Andric outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName 119*7a6dacacSDimitry Andric << "\n"; 1201db9f3b2SDimitry Andric 1211db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &OrigCU : 1221db9f3b2SDimitry Andric Context->InputDWARFFile.Dwarf->compile_units()) { 1231db9f3b2SDimitry Andric outs() << "Input compilation unit:"; 1241db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 1251db9f3b2SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 1261db9f3b2SDimitry Andric DumpOpts.Verbose = GlobalData.getOptions().Verbose; 1271db9f3b2SDimitry Andric OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts); 1281db9f3b2SDimitry Andric } 1291db9f3b2SDimitry Andric } 1301db9f3b2SDimitry Andric 1311db9f3b2SDimitry Andric // Verify input DWARF if requested. 1321db9f3b2SDimitry Andric if (GlobalData.getOptions().VerifyInputDWARF) 1331db9f3b2SDimitry Andric verifyInput(Context->InputDWARFFile); 1341db9f3b2SDimitry Andric 135*7a6dacacSDimitry Andric if (!GlobalData.getTargetTriple()) 1361db9f3b2SDimitry Andric GlobalEndianness = Context->getEndianness(); 1371db9f3b2SDimitry Andric GlobalFormat.AddrSize = 1381db9f3b2SDimitry Andric std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize); 1391db9f3b2SDimitry Andric 1401db9f3b2SDimitry Andric Context->setOutputFormat(Context->getFormParams(), GlobalEndianness); 1411db9f3b2SDimitry Andric 1421db9f3b2SDimitry Andric // FIXME: move creation of CompileUnits into the addObjectFile. 1431db9f3b2SDimitry Andric // This would allow to not scan for context Language and Modules state 1441db9f3b2SDimitry Andric // twice. And then following handling might be removed. 1451db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &OrigCU : 1461db9f3b2SDimitry Andric Context->InputDWARFFile.Dwarf->compile_units()) { 1471db9f3b2SDimitry Andric DWARFDie UnitDie = OrigCU.get()->getUnitDIE(); 1481db9f3b2SDimitry Andric 1491db9f3b2SDimitry Andric if (!Language) { 1501db9f3b2SDimitry Andric if (std::optional<DWARFFormValue> Val = 1511db9f3b2SDimitry Andric UnitDie.find(dwarf::DW_AT_language)) { 1521db9f3b2SDimitry Andric uint16_t LangVal = dwarf::toUnsigned(Val, 0); 1531db9f3b2SDimitry Andric if (isODRLanguage(LangVal)) 1541db9f3b2SDimitry Andric Language = LangVal; 1551db9f3b2SDimitry Andric } 1561db9f3b2SDimitry Andric } 1571db9f3b2SDimitry Andric } 1581db9f3b2SDimitry Andric } 1591db9f3b2SDimitry Andric 1601db9f3b2SDimitry Andric if (GlobalFormat.AddrSize == 0) { 161*7a6dacacSDimitry Andric if (std::optional<std::reference_wrapper<const Triple>> TargetTriple = 162*7a6dacacSDimitry Andric GlobalData.getTargetTriple()) 163*7a6dacacSDimitry Andric GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8; 1641db9f3b2SDimitry Andric else 1651db9f3b2SDimitry Andric GlobalFormat.AddrSize = 8; 1661db9f3b2SDimitry Andric } 1671db9f3b2SDimitry Andric 1681db9f3b2SDimitry Andric CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness); 1691db9f3b2SDimitry Andric 1701db9f3b2SDimitry Andric if (!GlobalData.Options.NoODR && Language.has_value()) { 1711db9f3b2SDimitry Andric llvm::parallel::TaskGroup TGroup; 1721db9f3b2SDimitry Andric TGroup.spawn([&]() { 1731db9f3b2SDimitry Andric ArtificialTypeUnit = std::make_unique<TypeUnit>( 1741db9f3b2SDimitry Andric GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness); 1751db9f3b2SDimitry Andric }); 1761db9f3b2SDimitry Andric } 1771db9f3b2SDimitry Andric 1781db9f3b2SDimitry Andric // Set parallel options. 1791db9f3b2SDimitry Andric if (GlobalData.getOptions().Threads == 0) 1801db9f3b2SDimitry Andric llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU); 1811db9f3b2SDimitry Andric else 1821db9f3b2SDimitry Andric llvm::parallel::strategy = 1831db9f3b2SDimitry Andric hardware_concurrency(GlobalData.getOptions().Threads); 1841db9f3b2SDimitry Andric 1851db9f3b2SDimitry Andric // Link object files. 1861db9f3b2SDimitry Andric if (GlobalData.getOptions().Threads == 1) { 1871db9f3b2SDimitry Andric for (std::unique_ptr<LinkContext> &Context : ObjectContexts) { 1881db9f3b2SDimitry Andric // Link object file. 1891db9f3b2SDimitry Andric if (Error Err = Context->link(ArtificialTypeUnit.get())) 1901db9f3b2SDimitry Andric GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName); 1911db9f3b2SDimitry Andric 1921db9f3b2SDimitry Andric Context->InputDWARFFile.unload(); 1931db9f3b2SDimitry Andric } 1941db9f3b2SDimitry Andric } else { 1951db9f3b2SDimitry Andric ThreadPool Pool(llvm::parallel::strategy); 1961db9f3b2SDimitry Andric for (std::unique_ptr<LinkContext> &Context : ObjectContexts) 1971db9f3b2SDimitry Andric Pool.async([&]() { 1981db9f3b2SDimitry Andric // Link object file. 1991db9f3b2SDimitry Andric if (Error Err = Context->link(ArtificialTypeUnit.get())) 2001db9f3b2SDimitry Andric GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName); 2011db9f3b2SDimitry Andric 2021db9f3b2SDimitry Andric Context->InputDWARFFile.unload(); 2031db9f3b2SDimitry Andric }); 2041db9f3b2SDimitry Andric 2051db9f3b2SDimitry Andric Pool.wait(); 2061db9f3b2SDimitry Andric } 2071db9f3b2SDimitry Andric 2081db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr && !ArtificialTypeUnit->getTypePool() 2091db9f3b2SDimitry Andric .getRoot() 2101db9f3b2SDimitry Andric ->getValue() 2111db9f3b2SDimitry Andric .load() 2121db9f3b2SDimitry Andric ->Children.empty()) { 213*7a6dacacSDimitry Andric if (GlobalData.getTargetTriple().has_value()) 214*7a6dacacSDimitry Andric if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit( 215*7a6dacacSDimitry Andric (*GlobalData.getTargetTriple()).get())) 2161db9f3b2SDimitry Andric return Err; 2171db9f3b2SDimitry Andric } 2181db9f3b2SDimitry Andric 2191db9f3b2SDimitry Andric // At this stage each compile units are cloned to their own set of debug 2201db9f3b2SDimitry Andric // sections. Now, update patches, assign offsets and assemble final file 2211db9f3b2SDimitry Andric // glueing debug tables from each compile unit. 2221db9f3b2SDimitry Andric glueCompileUnitsAndWriteToTheOutput(); 2231db9f3b2SDimitry Andric 2241db9f3b2SDimitry Andric return Error::success(); 2251db9f3b2SDimitry Andric } 2261db9f3b2SDimitry Andric 2271db9f3b2SDimitry Andric void DWARFLinkerImpl::verifyInput(const DWARFFile &File) { 2281db9f3b2SDimitry Andric assert(File.Dwarf); 2291db9f3b2SDimitry Andric 2301db9f3b2SDimitry Andric std::string Buffer; 2311db9f3b2SDimitry Andric raw_string_ostream OS(Buffer); 2321db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 2331db9f3b2SDimitry Andric if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) { 2341db9f3b2SDimitry Andric if (GlobalData.getOptions().InputVerificationHandler) 2351db9f3b2SDimitry Andric GlobalData.getOptions().InputVerificationHandler(File, OS.str()); 2361db9f3b2SDimitry Andric } 2371db9f3b2SDimitry Andric } 2381db9f3b2SDimitry Andric 2391db9f3b2SDimitry Andric Error DWARFLinkerImpl::validateAndUpdateOptions() { 2401db9f3b2SDimitry Andric if (GlobalData.getOptions().TargetDWARFVersion == 0) 2411db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 2421db9f3b2SDimitry Andric "target DWARF version is not set"); 2431db9f3b2SDimitry Andric 2441db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) { 2451db9f3b2SDimitry Andric GlobalData.Options.Threads = 1; 2461db9f3b2SDimitry Andric GlobalData.warn( 2471db9f3b2SDimitry Andric "set number of threads to 1 to make --verbose to work properly.", ""); 2481db9f3b2SDimitry Andric } 2491db9f3b2SDimitry Andric 2501db9f3b2SDimitry Andric // Do not do types deduplication in case --update. 2511db9f3b2SDimitry Andric if (GlobalData.getOptions().UpdateIndexTablesOnly && 2521db9f3b2SDimitry Andric !GlobalData.Options.NoODR) 2531db9f3b2SDimitry Andric GlobalData.Options.NoODR = true; 2541db9f3b2SDimitry Andric 2551db9f3b2SDimitry Andric return Error::success(); 2561db9f3b2SDimitry Andric } 2571db9f3b2SDimitry Andric 2581db9f3b2SDimitry Andric /// Resolve the relative path to a build artifact referenced by DWARF by 2591db9f3b2SDimitry Andric /// applying DW_AT_comp_dir. 2601db9f3b2SDimitry Andric static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { 2611db9f3b2SDimitry Andric sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), "")); 2621db9f3b2SDimitry Andric } 2631db9f3b2SDimitry Andric 2641db9f3b2SDimitry Andric static uint64_t getDwoId(const DWARFDie &CUDie) { 2651db9f3b2SDimitry Andric auto DwoId = dwarf::toUnsigned( 2661db9f3b2SDimitry Andric CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id})); 2671db9f3b2SDimitry Andric if (DwoId) 2681db9f3b2SDimitry Andric return *DwoId; 2691db9f3b2SDimitry Andric return 0; 2701db9f3b2SDimitry Andric } 2711db9f3b2SDimitry Andric 2721db9f3b2SDimitry Andric static std::string 2731db9f3b2SDimitry Andric remapPath(StringRef Path, 2741db9f3b2SDimitry Andric const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) { 2751db9f3b2SDimitry Andric if (ObjectPrefixMap.empty()) 2761db9f3b2SDimitry Andric return Path.str(); 2771db9f3b2SDimitry Andric 2781db9f3b2SDimitry Andric SmallString<256> p = Path; 2791db9f3b2SDimitry Andric for (const auto &Entry : ObjectPrefixMap) 2801db9f3b2SDimitry Andric if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second)) 2811db9f3b2SDimitry Andric break; 2821db9f3b2SDimitry Andric return p.str().str(); 2831db9f3b2SDimitry Andric } 2841db9f3b2SDimitry Andric 2851db9f3b2SDimitry Andric static std::string getPCMFile(const DWARFDie &CUDie, 2861db9f3b2SDimitry Andric DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) { 2871db9f3b2SDimitry Andric std::string PCMFile = dwarf::toString( 2881db9f3b2SDimitry Andric CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); 2891db9f3b2SDimitry Andric 2901db9f3b2SDimitry Andric if (PCMFile.empty()) 2911db9f3b2SDimitry Andric return PCMFile; 2921db9f3b2SDimitry Andric 2931db9f3b2SDimitry Andric if (ObjectPrefixMap) 2941db9f3b2SDimitry Andric PCMFile = remapPath(PCMFile, *ObjectPrefixMap); 2951db9f3b2SDimitry Andric 2961db9f3b2SDimitry Andric return PCMFile; 2971db9f3b2SDimitry Andric } 2981db9f3b2SDimitry Andric 2991db9f3b2SDimitry Andric std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef( 3001db9f3b2SDimitry Andric const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) { 3011db9f3b2SDimitry Andric if (PCMFile.empty()) 3021db9f3b2SDimitry Andric return std::make_pair(false, false); 3031db9f3b2SDimitry Andric 3041db9f3b2SDimitry Andric // Clang module DWARF skeleton CUs abuse this for the path to the module. 3051db9f3b2SDimitry Andric uint64_t DwoId = getDwoId(CUDie); 3061db9f3b2SDimitry Andric 3071db9f3b2SDimitry Andric std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 3081db9f3b2SDimitry Andric if (Name.empty()) { 3091db9f3b2SDimitry Andric if (!Quiet) 3101db9f3b2SDimitry Andric GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".", 3111db9f3b2SDimitry Andric InputDWARFFile.FileName); 3121db9f3b2SDimitry Andric return std::make_pair(true, true); 3131db9f3b2SDimitry Andric } 3141db9f3b2SDimitry Andric 3151db9f3b2SDimitry Andric if (!Quiet && GlobalData.getOptions().Verbose) { 3161db9f3b2SDimitry Andric outs().indent(Indent); 3171db9f3b2SDimitry Andric outs() << "Found clang module reference " << PCMFile; 3181db9f3b2SDimitry Andric } 3191db9f3b2SDimitry Andric 3201db9f3b2SDimitry Andric auto Cached = ClangModules.find(PCMFile); 3211db9f3b2SDimitry Andric if (Cached != ClangModules.end()) { 3221db9f3b2SDimitry Andric // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 3231db9f3b2SDimitry Andric // fixed in clang, only warn about DWO_id mismatches in verbose mode. 3241db9f3b2SDimitry Andric // ASTFileSignatures will change randomly when a module is rebuilt. 3251db9f3b2SDimitry Andric if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId)) 3261db9f3b2SDimitry Andric GlobalData.warn( 3271db9f3b2SDimitry Andric Twine("hash mismatch: this object file was built against a " 3281db9f3b2SDimitry Andric "different version of the module ") + 3291db9f3b2SDimitry Andric PCMFile + ".", 3301db9f3b2SDimitry Andric InputDWARFFile.FileName); 3311db9f3b2SDimitry Andric if (!Quiet && GlobalData.getOptions().Verbose) 3321db9f3b2SDimitry Andric outs() << " [cached].\n"; 3331db9f3b2SDimitry Andric return std::make_pair(true, true); 3341db9f3b2SDimitry Andric } 3351db9f3b2SDimitry Andric 3361db9f3b2SDimitry Andric return std::make_pair(true, false); 3371db9f3b2SDimitry Andric } 3381db9f3b2SDimitry Andric 3391db9f3b2SDimitry Andric /// If this compile unit is really a skeleton CU that points to a 3401db9f3b2SDimitry Andric /// clang module, register it in ClangModules and return true. 3411db9f3b2SDimitry Andric /// 3421db9f3b2SDimitry Andric /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name 3431db9f3b2SDimitry Andric /// pointing to the module, and a DW_AT_gnu_dwo_id with the module 3441db9f3b2SDimitry Andric /// hash. 3451db9f3b2SDimitry Andric bool DWARFLinkerImpl::LinkContext::registerModuleReference( 3461db9f3b2SDimitry Andric const DWARFDie &CUDie, ObjFileLoaderTy Loader, 3471db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 3481db9f3b2SDimitry Andric std::string PCMFile = 3491db9f3b2SDimitry Andric getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap); 3501db9f3b2SDimitry Andric std::pair<bool, bool> IsClangModuleRef = 3511db9f3b2SDimitry Andric isClangModuleRef(CUDie, PCMFile, Indent, false); 3521db9f3b2SDimitry Andric 3531db9f3b2SDimitry Andric if (!IsClangModuleRef.first) 3541db9f3b2SDimitry Andric return false; 3551db9f3b2SDimitry Andric 3561db9f3b2SDimitry Andric if (IsClangModuleRef.second) 3571db9f3b2SDimitry Andric return true; 3581db9f3b2SDimitry Andric 3591db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) 3601db9f3b2SDimitry Andric outs() << " ...\n"; 3611db9f3b2SDimitry Andric 3621db9f3b2SDimitry Andric // Cyclic dependencies are disallowed by Clang, but we still 3631db9f3b2SDimitry Andric // shouldn't run into an infinite loop, so mark it as processed now. 3641db9f3b2SDimitry Andric ClangModules.insert({PCMFile, getDwoId(CUDie)}); 3651db9f3b2SDimitry Andric 3661db9f3b2SDimitry Andric if (Error E = 3671db9f3b2SDimitry Andric loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) { 3681db9f3b2SDimitry Andric consumeError(std::move(E)); 3691db9f3b2SDimitry Andric return false; 3701db9f3b2SDimitry Andric } 3711db9f3b2SDimitry Andric return true; 3721db9f3b2SDimitry Andric } 3731db9f3b2SDimitry Andric 3741db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::loadClangModule( 3751db9f3b2SDimitry Andric ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile, 3761db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 3771db9f3b2SDimitry Andric 3781db9f3b2SDimitry Andric uint64_t DwoId = getDwoId(CUDie); 3791db9f3b2SDimitry Andric std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 3801db9f3b2SDimitry Andric 3811db9f3b2SDimitry Andric /// Using a SmallString<0> because loadClangModule() is recursive. 3821db9f3b2SDimitry Andric SmallString<0> Path(GlobalData.getOptions().PrependPath); 3831db9f3b2SDimitry Andric if (sys::path::is_relative(PCMFile)) 3841db9f3b2SDimitry Andric resolveRelativeObjectPath(Path, CUDie); 3851db9f3b2SDimitry Andric sys::path::append(Path, PCMFile); 3861db9f3b2SDimitry Andric // Don't use the cached binary holder because we have no thread-safety 3871db9f3b2SDimitry Andric // guarantee and the lifetime is limited. 3881db9f3b2SDimitry Andric 3891db9f3b2SDimitry Andric if (Loader == nullptr) { 3901db9f3b2SDimitry Andric GlobalData.error("cann't load clang module: loader is not specified.", 3911db9f3b2SDimitry Andric InputDWARFFile.FileName); 3921db9f3b2SDimitry Andric return Error::success(); 3931db9f3b2SDimitry Andric } 3941db9f3b2SDimitry Andric 3951db9f3b2SDimitry Andric auto ErrOrObj = Loader(InputDWARFFile.FileName, Path); 3961db9f3b2SDimitry Andric if (!ErrOrObj) 3971db9f3b2SDimitry Andric return Error::success(); 3981db9f3b2SDimitry Andric 3991db9f3b2SDimitry Andric std::unique_ptr<CompileUnit> Unit; 4001db9f3b2SDimitry Andric for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { 4011db9f3b2SDimitry Andric OnCUDieLoaded(*CU); 4021db9f3b2SDimitry Andric // Recursively get all modules imported by this one. 4031db9f3b2SDimitry Andric auto ChildCUDie = CU->getUnitDIE(); 4041db9f3b2SDimitry Andric if (!ChildCUDie) 4051db9f3b2SDimitry Andric continue; 4061db9f3b2SDimitry Andric if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) { 4071db9f3b2SDimitry Andric if (Unit) { 4081db9f3b2SDimitry Andric std::string Err = 4091db9f3b2SDimitry Andric (PCMFile + 4101db9f3b2SDimitry Andric ": Clang modules are expected to have exactly 1 compile unit.\n"); 4111db9f3b2SDimitry Andric GlobalData.error(Err, InputDWARFFile.FileName); 4121db9f3b2SDimitry Andric return make_error<StringError>(Err, inconvertibleErrorCode()); 4131db9f3b2SDimitry Andric } 4141db9f3b2SDimitry Andric // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 4151db9f3b2SDimitry Andric // fixed in clang, only warn about DWO_id mismatches in verbose mode. 4161db9f3b2SDimitry Andric // ASTFileSignatures will change randomly when a module is rebuilt. 4171db9f3b2SDimitry Andric uint64_t PCMDwoId = getDwoId(ChildCUDie); 4181db9f3b2SDimitry Andric if (PCMDwoId != DwoId) { 4191db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) 4201db9f3b2SDimitry Andric GlobalData.warn( 4211db9f3b2SDimitry Andric Twine("hash mismatch: this object file was built against a " 4221db9f3b2SDimitry Andric "different version of the module ") + 4231db9f3b2SDimitry Andric PCMFile + ".", 4241db9f3b2SDimitry Andric InputDWARFFile.FileName); 4251db9f3b2SDimitry Andric // Update the cache entry with the DwoId of the module loaded from disk. 4261db9f3b2SDimitry Andric ClangModules[PCMFile] = PCMDwoId; 4271db9f3b2SDimitry Andric } 4281db9f3b2SDimitry Andric 4291db9f3b2SDimitry Andric // Empty modules units should not be cloned. 4301db9f3b2SDimitry Andric if (!ChildCUDie.hasChildren()) 4311db9f3b2SDimitry Andric continue; 4321db9f3b2SDimitry Andric 4331db9f3b2SDimitry Andric // Add this module. 4341db9f3b2SDimitry Andric Unit = std::make_unique<CompileUnit>( 4351db9f3b2SDimitry Andric GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj, 4361db9f3b2SDimitry Andric getUnitForOffset, CU->getFormParams(), getEndianness()); 4371db9f3b2SDimitry Andric } 4381db9f3b2SDimitry Andric } 4391db9f3b2SDimitry Andric 4401db9f3b2SDimitry Andric if (Unit) { 4411db9f3b2SDimitry Andric ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)}); 4421db9f3b2SDimitry Andric // Preload line table, as it can't be loaded asynchronously. 4431db9f3b2SDimitry Andric ModulesCompileUnits.back().Unit->loadLineTable(); 4441db9f3b2SDimitry Andric } 4451db9f3b2SDimitry Andric 4461db9f3b2SDimitry Andric return Error::success(); 4471db9f3b2SDimitry Andric } 4481db9f3b2SDimitry Andric 4491db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) { 4501db9f3b2SDimitry Andric InterCUProcessingStarted = false; 4511db9f3b2SDimitry Andric if (!InputDWARFFile.Dwarf) 4521db9f3b2SDimitry Andric return Error::success(); 4531db9f3b2SDimitry Andric 4541db9f3b2SDimitry Andric // Preload macro tables, as they can't be loaded asynchronously. 4551db9f3b2SDimitry Andric InputDWARFFile.Dwarf->getDebugMacinfo(); 4561db9f3b2SDimitry Andric InputDWARFFile.Dwarf->getDebugMacro(); 4571db9f3b2SDimitry Andric 4581db9f3b2SDimitry Andric // Link modules compile units first. 4591db9f3b2SDimitry Andric parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) { 4601db9f3b2SDimitry Andric linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit); 4611db9f3b2SDimitry Andric }); 4621db9f3b2SDimitry Andric 4631db9f3b2SDimitry Andric // Check for live relocations. If there is no any live relocation then we 4641db9f3b2SDimitry Andric // can skip entire object file. 4651db9f3b2SDimitry Andric if (!GlobalData.getOptions().UpdateIndexTablesOnly && 4661db9f3b2SDimitry Andric !InputDWARFFile.Addresses->hasValidRelocs()) { 4671db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) 4681db9f3b2SDimitry Andric outs() << "No valid relocations found. Skipping.\n"; 4691db9f3b2SDimitry Andric return Error::success(); 4701db9f3b2SDimitry Andric } 4711db9f3b2SDimitry Andric 4721db9f3b2SDimitry Andric OriginalDebugInfoSize = getInputDebugInfoSize(); 4731db9f3b2SDimitry Andric 4741db9f3b2SDimitry Andric // Create CompileUnit structures to keep information about source 4751db9f3b2SDimitry Andric // DWARFUnit`s, load line tables. 4761db9f3b2SDimitry Andric for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) { 4771db9f3b2SDimitry Andric // Load only unit DIE at this stage. 4781db9f3b2SDimitry Andric auto CUDie = OrigCU->getUnitDIE(); 4791db9f3b2SDimitry Andric std::string PCMFile = 4801db9f3b2SDimitry Andric getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap); 4811db9f3b2SDimitry Andric 4821db9f3b2SDimitry Andric // The !isClangModuleRef condition effectively skips over fully resolved 4831db9f3b2SDimitry Andric // skeleton units. 4841db9f3b2SDimitry Andric if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly || 4851db9f3b2SDimitry Andric !isClangModuleRef(CUDie, PCMFile, 0, true).first) { 4861db9f3b2SDimitry Andric CompileUnits.emplace_back(std::make_unique<CompileUnit>( 4871db9f3b2SDimitry Andric GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile, 4881db9f3b2SDimitry Andric getUnitForOffset, OrigCU->getFormParams(), getEndianness())); 4891db9f3b2SDimitry Andric 4901db9f3b2SDimitry Andric // Preload line table, as it can't be loaded asynchronously. 4911db9f3b2SDimitry Andric CompileUnits.back()->loadLineTable(); 4921db9f3b2SDimitry Andric } 4931db9f3b2SDimitry Andric }; 4941db9f3b2SDimitry Andric 4951db9f3b2SDimitry Andric HasNewInterconnectedCUs = false; 4961db9f3b2SDimitry Andric 4971db9f3b2SDimitry Andric // Link self-sufficient compile units and discover inter-connected compile 4981db9f3b2SDimitry Andric // units. 4991db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5001db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit); 5011db9f3b2SDimitry Andric }); 5021db9f3b2SDimitry Andric 5031db9f3b2SDimitry Andric // Link all inter-connected units. 5041db9f3b2SDimitry Andric if (HasNewInterconnectedCUs) { 5051db9f3b2SDimitry Andric InterCUProcessingStarted = true; 5061db9f3b2SDimitry Andric 5071db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 5081db9f3b2SDimitry Andric HasNewInterconnectedCUs = false; 5091db9f3b2SDimitry Andric 5101db9f3b2SDimitry Andric // Load inter-connected units. 5111db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5121db9f3b2SDimitry Andric if (CU->isInterconnectedCU()) { 5131db9f3b2SDimitry Andric CU->maybeResetToLoadedStage(); 5141db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 5151db9f3b2SDimitry Andric CompileUnit::Stage::Loaded); 5161db9f3b2SDimitry Andric } 5171db9f3b2SDimitry Andric }); 5181db9f3b2SDimitry Andric 5191db9f3b2SDimitry Andric // Do liveness analysis for inter-connected units. 5201db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5211db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 5221db9f3b2SDimitry Andric CompileUnit::Stage::LivenessAnalysisDone); 5231db9f3b2SDimitry Andric }); 5241db9f3b2SDimitry Andric 5251db9f3b2SDimitry Andric return HasNewInterconnectedCUs.load(); 5261db9f3b2SDimitry Andric })) 5271db9f3b2SDimitry Andric return Err; 5281db9f3b2SDimitry Andric 5291db9f3b2SDimitry Andric // Update dependencies. 5301db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 5311db9f3b2SDimitry Andric HasNewGlobalDependency = false; 5321db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5331db9f3b2SDimitry Andric linkSingleCompileUnit( 5341db9f3b2SDimitry Andric *CU, ArtificialTypeUnit, 5351db9f3b2SDimitry Andric CompileUnit::Stage::UpdateDependenciesCompleteness); 5361db9f3b2SDimitry Andric }); 5371db9f3b2SDimitry Andric return HasNewGlobalDependency.load(); 5381db9f3b2SDimitry Andric })) 5391db9f3b2SDimitry Andric return Err; 5401db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5411db9f3b2SDimitry Andric if (CU->isInterconnectedCU() && 5421db9f3b2SDimitry Andric CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone) 5431db9f3b2SDimitry Andric CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness); 5441db9f3b2SDimitry Andric }); 5451db9f3b2SDimitry Andric 5461db9f3b2SDimitry Andric // Assign type names. 5471db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5481db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 5491db9f3b2SDimitry Andric CompileUnit::Stage::TypeNamesAssigned); 5501db9f3b2SDimitry Andric }); 5511db9f3b2SDimitry Andric 5521db9f3b2SDimitry Andric // Clone inter-connected units. 5531db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5541db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 5551db9f3b2SDimitry Andric CompileUnit::Stage::Cloned); 5561db9f3b2SDimitry Andric }); 5571db9f3b2SDimitry Andric 5581db9f3b2SDimitry Andric // Update patches for inter-connected units. 5591db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5601db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 5611db9f3b2SDimitry Andric CompileUnit::Stage::PatchesUpdated); 5621db9f3b2SDimitry Andric }); 5631db9f3b2SDimitry Andric 5641db9f3b2SDimitry Andric // Release data. 5651db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 5661db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 5671db9f3b2SDimitry Andric CompileUnit::Stage::Cleaned); 5681db9f3b2SDimitry Andric }); 5691db9f3b2SDimitry Andric } 5701db9f3b2SDimitry Andric 5711db9f3b2SDimitry Andric if (GlobalData.getOptions().UpdateIndexTablesOnly) { 5721db9f3b2SDimitry Andric // Emit Invariant sections. 5731db9f3b2SDimitry Andric 5741db9f3b2SDimitry Andric if (Error Err = emitInvariantSections()) 5751db9f3b2SDimitry Andric return Err; 5761db9f3b2SDimitry Andric } else if (!CompileUnits.empty()) { 5771db9f3b2SDimitry Andric // Emit .debug_frame section. 5781db9f3b2SDimitry Andric 5791db9f3b2SDimitry Andric Error ResultErr = Error::success(); 5801db9f3b2SDimitry Andric llvm::parallel::TaskGroup TGroup; 5811db9f3b2SDimitry Andric // We use task group here as PerThreadBumpPtrAllocator should be called from 5821db9f3b2SDimitry Andric // the threads created by ThreadPoolExecutor. 5831db9f3b2SDimitry Andric TGroup.spawn([&]() { 5841db9f3b2SDimitry Andric if (Error Err = cloneAndEmitDebugFrame()) 5851db9f3b2SDimitry Andric ResultErr = std::move(Err); 5861db9f3b2SDimitry Andric }); 5871db9f3b2SDimitry Andric return ResultErr; 5881db9f3b2SDimitry Andric } 5891db9f3b2SDimitry Andric 5901db9f3b2SDimitry Andric return Error::success(); 5911db9f3b2SDimitry Andric } 5921db9f3b2SDimitry Andric 5931db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit( 5941db9f3b2SDimitry Andric CompileUnit &CU, TypeUnit *ArtificialTypeUnit, 5951db9f3b2SDimitry Andric enum CompileUnit::Stage DoUntilStage) { 5961db9f3b2SDimitry Andric if (InterCUProcessingStarted != CU.isInterconnectedCU()) 5971db9f3b2SDimitry Andric return; 5981db9f3b2SDimitry Andric 5991db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 6001db9f3b2SDimitry Andric if (CU.getStage() >= DoUntilStage) 6011db9f3b2SDimitry Andric return false; 6021db9f3b2SDimitry Andric 6031db9f3b2SDimitry Andric switch (CU.getStage()) { 6041db9f3b2SDimitry Andric case CompileUnit::Stage::CreatedNotLoaded: { 6051db9f3b2SDimitry Andric // Load input compilation unit DIEs. 6061db9f3b2SDimitry Andric // Analyze properties of DIEs. 6071db9f3b2SDimitry Andric if (!CU.loadInputDIEs()) { 6081db9f3b2SDimitry Andric // We do not need to do liveness analysis for invalid compilation 6091db9f3b2SDimitry Andric // unit. 6101db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Skipped); 6111db9f3b2SDimitry Andric } else { 6121db9f3b2SDimitry Andric CU.analyzeDWARFStructure(); 6131db9f3b2SDimitry Andric 6141db9f3b2SDimitry Andric // The registerModuleReference() condition effectively skips 6151db9f3b2SDimitry Andric // over fully resolved skeleton units. This second pass of 6161db9f3b2SDimitry Andric // registerModuleReferences doesn't do any new work, but it 6171db9f3b2SDimitry Andric // will collect top-level errors, which are suppressed. Module 6181db9f3b2SDimitry Andric // warnings were already displayed in the first iteration. 6191db9f3b2SDimitry Andric if (registerModuleReference( 6201db9f3b2SDimitry Andric CU.getOrigUnit().getUnitDIE(), nullptr, 6211db9f3b2SDimitry Andric [](const DWARFUnit &) {}, 0)) 6221db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::PatchesUpdated); 6231db9f3b2SDimitry Andric else 6241db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Loaded); 6251db9f3b2SDimitry Andric } 6261db9f3b2SDimitry Andric } break; 6271db9f3b2SDimitry Andric 6281db9f3b2SDimitry Andric case CompileUnit::Stage::Loaded: { 6291db9f3b2SDimitry Andric // Mark all the DIEs that need to be present in the generated output. 6301db9f3b2SDimitry Andric // If ODR requested, build type names. 6311db9f3b2SDimitry Andric if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted, 6321db9f3b2SDimitry Andric HasNewInterconnectedCUs)) { 6331db9f3b2SDimitry Andric assert(HasNewInterconnectedCUs && 6341db9f3b2SDimitry Andric "Flag indicating new inter-connections is not set"); 6351db9f3b2SDimitry Andric return false; 6361db9f3b2SDimitry Andric } 6371db9f3b2SDimitry Andric 6381db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::LivenessAnalysisDone); 6391db9f3b2SDimitry Andric } break; 6401db9f3b2SDimitry Andric 6411db9f3b2SDimitry Andric case CompileUnit::Stage::LivenessAnalysisDone: { 6421db9f3b2SDimitry Andric if (InterCUProcessingStarted) { 6431db9f3b2SDimitry Andric if (CU.updateDependenciesCompleteness()) 6441db9f3b2SDimitry Andric HasNewGlobalDependency = true; 6451db9f3b2SDimitry Andric return false; 6461db9f3b2SDimitry Andric } else { 6471db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 6481db9f3b2SDimitry Andric return CU.updateDependenciesCompleteness(); 6491db9f3b2SDimitry Andric })) 6501db9f3b2SDimitry Andric return std::move(Err); 6511db9f3b2SDimitry Andric 6521db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness); 6531db9f3b2SDimitry Andric } 6541db9f3b2SDimitry Andric } break; 6551db9f3b2SDimitry Andric 6561db9f3b2SDimitry Andric case CompileUnit::Stage::UpdateDependenciesCompleteness: 6571db9f3b2SDimitry Andric #ifndef NDEBUG 6581db9f3b2SDimitry Andric CU.verifyDependencies(); 6591db9f3b2SDimitry Andric #endif 6601db9f3b2SDimitry Andric 6611db9f3b2SDimitry Andric if (ArtificialTypeUnit) { 6621db9f3b2SDimitry Andric if (Error Err = 6631db9f3b2SDimitry Andric CU.assignTypeNames(ArtificialTypeUnit->getTypePool())) 6641db9f3b2SDimitry Andric return std::move(Err); 6651db9f3b2SDimitry Andric } 6661db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::TypeNamesAssigned); 6671db9f3b2SDimitry Andric break; 6681db9f3b2SDimitry Andric 6691db9f3b2SDimitry Andric case CompileUnit::Stage::TypeNamesAssigned: 6701db9f3b2SDimitry Andric // Clone input compile unit. 6711db9f3b2SDimitry Andric if (CU.isClangModule() || 6721db9f3b2SDimitry Andric GlobalData.getOptions().UpdateIndexTablesOnly || 6731db9f3b2SDimitry Andric CU.getContaingFile().Addresses->hasValidRelocs()) { 674*7a6dacacSDimitry Andric if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(), 675*7a6dacacSDimitry Andric ArtificialTypeUnit)) 6761db9f3b2SDimitry Andric return std::move(Err); 6771db9f3b2SDimitry Andric } 6781db9f3b2SDimitry Andric 6791db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Cloned); 6801db9f3b2SDimitry Andric break; 6811db9f3b2SDimitry Andric 6821db9f3b2SDimitry Andric case CompileUnit::Stage::Cloned: 6831db9f3b2SDimitry Andric // Update DIEs referencies. 6841db9f3b2SDimitry Andric CU.updateDieRefPatchesWithClonedOffsets(); 6851db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::PatchesUpdated); 6861db9f3b2SDimitry Andric break; 6871db9f3b2SDimitry Andric 6881db9f3b2SDimitry Andric case CompileUnit::Stage::PatchesUpdated: 6891db9f3b2SDimitry Andric // Cleanup resources. 6901db9f3b2SDimitry Andric CU.cleanupDataAfterClonning(); 6911db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Cleaned); 6921db9f3b2SDimitry Andric break; 6931db9f3b2SDimitry Andric 6941db9f3b2SDimitry Andric case CompileUnit::Stage::Cleaned: 6951db9f3b2SDimitry Andric assert(false); 6961db9f3b2SDimitry Andric break; 6971db9f3b2SDimitry Andric 6981db9f3b2SDimitry Andric case CompileUnit::Stage::Skipped: 6991db9f3b2SDimitry Andric // Nothing to do. 7001db9f3b2SDimitry Andric break; 7011db9f3b2SDimitry Andric } 7021db9f3b2SDimitry Andric 7031db9f3b2SDimitry Andric return true; 7041db9f3b2SDimitry Andric })) { 7051db9f3b2SDimitry Andric CU.error(std::move(Err)); 7061db9f3b2SDimitry Andric CU.cleanupDataAfterClonning(); 7071db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Skipped); 7081db9f3b2SDimitry Andric } 7091db9f3b2SDimitry Andric } 7101db9f3b2SDimitry Andric 7111db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::emitInvariantSections() { 712*7a6dacacSDimitry Andric if (!GlobalData.getTargetTriple().has_value()) 7131db9f3b2SDimitry Andric return Error::success(); 7141db9f3b2SDimitry Andric 7151db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS 7161db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data; 7171db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS 7181db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data; 7191db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS 7201db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data; 7211db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS 7221db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data; 7231db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS 7241db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection(); 7251db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS 7261db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data; 7271db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS 7281db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data; 7291db9f3b2SDimitry Andric 7301db9f3b2SDimitry Andric return Error::success(); 7311db9f3b2SDimitry Andric } 7321db9f3b2SDimitry Andric 7331db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() { 734*7a6dacacSDimitry Andric if (!GlobalData.getTargetTriple().has_value()) 7351db9f3b2SDimitry Andric return Error::success(); 7361db9f3b2SDimitry Andric 7371db9f3b2SDimitry Andric if (InputDWARFFile.Dwarf.get() == nullptr) 7381db9f3b2SDimitry Andric return Error::success(); 7391db9f3b2SDimitry Andric 7401db9f3b2SDimitry Andric const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj(); 7411db9f3b2SDimitry Andric 7421db9f3b2SDimitry Andric StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data; 7431db9f3b2SDimitry Andric if (OrigFrameData.empty()) 7441db9f3b2SDimitry Andric return Error::success(); 7451db9f3b2SDimitry Andric 7461db9f3b2SDimitry Andric RangesTy AllUnitsRanges; 7471db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) { 7481db9f3b2SDimitry Andric for (auto CurRange : Unit->getFunctionRanges()) 7491db9f3b2SDimitry Andric AllUnitsRanges.insert(CurRange.Range, CurRange.Value); 7501db9f3b2SDimitry Andric } 7511db9f3b2SDimitry Andric 7521db9f3b2SDimitry Andric unsigned SrcAddrSize = InputDWARFObj.getAddressSize(); 7531db9f3b2SDimitry Andric 7541db9f3b2SDimitry Andric SectionDescriptor &OutSection = 7551db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame); 7561db9f3b2SDimitry Andric 7571db9f3b2SDimitry Andric DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0); 7581db9f3b2SDimitry Andric uint64_t InputOffset = 0; 7591db9f3b2SDimitry Andric 7601db9f3b2SDimitry Andric // Store the data of the CIEs defined in this object, keyed by their 7611db9f3b2SDimitry Andric // offsets. 7621db9f3b2SDimitry Andric DenseMap<uint64_t, StringRef> LocalCIES; 7631db9f3b2SDimitry Andric 7641db9f3b2SDimitry Andric /// The CIEs that have been emitted in the output section. The actual CIE 7651db9f3b2SDimitry Andric /// data serves a the key to this StringMap. 7661db9f3b2SDimitry Andric StringMap<uint32_t> EmittedCIEs; 7671db9f3b2SDimitry Andric 7681db9f3b2SDimitry Andric while (Data.isValidOffset(InputOffset)) { 7691db9f3b2SDimitry Andric uint64_t EntryOffset = InputOffset; 7701db9f3b2SDimitry Andric uint32_t InitialLength = Data.getU32(&InputOffset); 7711db9f3b2SDimitry Andric if (InitialLength == 0xFFFFFFFF) 7721db9f3b2SDimitry Andric return createFileError(InputDWARFObj.getFileName(), 7731db9f3b2SDimitry Andric createStringError(std::errc::invalid_argument, 7741db9f3b2SDimitry Andric "Dwarf64 bits no supported")); 7751db9f3b2SDimitry Andric 7761db9f3b2SDimitry Andric uint32_t CIEId = Data.getU32(&InputOffset); 7771db9f3b2SDimitry Andric if (CIEId == 0xFFFFFFFF) { 7781db9f3b2SDimitry Andric // This is a CIE, store it. 7791db9f3b2SDimitry Andric StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4); 7801db9f3b2SDimitry Andric LocalCIES[EntryOffset] = CIEData; 7811db9f3b2SDimitry Andric // The -4 is to account for the CIEId we just read. 7821db9f3b2SDimitry Andric InputOffset += InitialLength - 4; 7831db9f3b2SDimitry Andric continue; 7841db9f3b2SDimitry Andric } 7851db9f3b2SDimitry Andric 7861db9f3b2SDimitry Andric uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize); 7871db9f3b2SDimitry Andric 7881db9f3b2SDimitry Andric // Some compilers seem to emit frame info that doesn't start at 7891db9f3b2SDimitry Andric // the function entry point, thus we can't just lookup the address 7901db9f3b2SDimitry Andric // in the debug map. Use the AddressInfo's range map to see if the FDE 7911db9f3b2SDimitry Andric // describes something that we can relocate. 7921db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> Range = 7931db9f3b2SDimitry Andric AllUnitsRanges.getRangeThatContains(Loc); 7941db9f3b2SDimitry Andric if (!Range) { 7951db9f3b2SDimitry Andric // The +4 is to account for the size of the InitialLength field itself. 7961db9f3b2SDimitry Andric InputOffset = EntryOffset + InitialLength + 4; 7971db9f3b2SDimitry Andric continue; 7981db9f3b2SDimitry Andric } 7991db9f3b2SDimitry Andric 8001db9f3b2SDimitry Andric // This is an FDE, and we have a mapping. 8011db9f3b2SDimitry Andric // Have we already emitted a corresponding CIE? 8021db9f3b2SDimitry Andric StringRef CIEData = LocalCIES[CIEId]; 8031db9f3b2SDimitry Andric if (CIEData.empty()) 8041db9f3b2SDimitry Andric return createFileError( 8051db9f3b2SDimitry Andric InputDWARFObj.getFileName(), 8061db9f3b2SDimitry Andric createStringError(std::errc::invalid_argument, 8071db9f3b2SDimitry Andric "Inconsistent debug_frame content. Dropping.")); 8081db9f3b2SDimitry Andric 8091db9f3b2SDimitry Andric uint64_t OffsetToCIERecord = OutSection.OS.tell(); 8101db9f3b2SDimitry Andric 8111db9f3b2SDimitry Andric // Look if we already emitted a CIE that corresponds to the 8121db9f3b2SDimitry Andric // referenced one (the CIE data is the key of that lookup). 8131db9f3b2SDimitry Andric auto IteratorInserted = 8141db9f3b2SDimitry Andric EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord)); 8151db9f3b2SDimitry Andric OffsetToCIERecord = IteratorInserted.first->getValue(); 8161db9f3b2SDimitry Andric 8171db9f3b2SDimitry Andric // Emit CIE for this ID if it is not emitted yet. 8181db9f3b2SDimitry Andric if (IteratorInserted.second) 8191db9f3b2SDimitry Andric OutSection.OS << CIEData; 8201db9f3b2SDimitry Andric 8211db9f3b2SDimitry Andric // Remember offset to the FDE record, so that we might update 8221db9f3b2SDimitry Andric // field referencing CIE record(containing OffsetToCIERecord), 8231db9f3b2SDimitry Andric // when final offsets are known. OffsetToCIERecord(which is written later) 8241db9f3b2SDimitry Andric // is local to the current .debug_frame section, it should be updated 8251db9f3b2SDimitry Andric // with final offset of the .debug_frame section. 8261db9f3b2SDimitry Andric OutSection.notePatch( 8271db9f3b2SDimitry Andric DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true}); 8281db9f3b2SDimitry Andric 8291db9f3b2SDimitry Andric // Emit the FDE with updated address and CIE pointer. 8301db9f3b2SDimitry Andric // (4 + AddrSize) is the size of the CIEId + initial_location 8311db9f3b2SDimitry Andric // fields that will get reconstructed by emitFDE(). 8321db9f3b2SDimitry Andric unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize); 8331db9f3b2SDimitry Andric emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value, 8341db9f3b2SDimitry Andric OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection); 8351db9f3b2SDimitry Andric InputOffset += FDERemainingBytes; 8361db9f3b2SDimitry Andric } 8371db9f3b2SDimitry Andric 8381db9f3b2SDimitry Andric return Error::success(); 8391db9f3b2SDimitry Andric } 8401db9f3b2SDimitry Andric 8411db9f3b2SDimitry Andric /// Emit a FDE into the debug_frame section. \p FDEBytes 8421db9f3b2SDimitry Andric /// contains the FDE data without the length, CIE offset and address 8431db9f3b2SDimitry Andric /// which will be replaced with the parameter values. 8441db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset, 8451db9f3b2SDimitry Andric uint32_t AddrSize, uint64_t Address, 8461db9f3b2SDimitry Andric StringRef FDEBytes, 8471db9f3b2SDimitry Andric SectionDescriptor &Section) { 8481db9f3b2SDimitry Andric Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4); 8491db9f3b2SDimitry Andric Section.emitIntVal(CIEOffset, 4); 8501db9f3b2SDimitry Andric Section.emitIntVal(Address, AddrSize); 8511db9f3b2SDimitry Andric Section.OS.write(FDEBytes.data(), FDEBytes.size()); 8521db9f3b2SDimitry Andric } 8531db9f3b2SDimitry Andric 8541db9f3b2SDimitry Andric void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() { 855*7a6dacacSDimitry Andric if (!GlobalData.getTargetTriple().has_value()) 8561db9f3b2SDimitry Andric return; 857*7a6dacacSDimitry Andric assert(SectionHandler); 8581db9f3b2SDimitry Andric 8591db9f3b2SDimitry Andric // Go through all object files, all compile units and assign 8601db9f3b2SDimitry Andric // offsets to them. 8611db9f3b2SDimitry Andric assignOffsets(); 8621db9f3b2SDimitry Andric 8631db9f3b2SDimitry Andric // Patch size/offsets fields according to the assigned CU offsets. 8641db9f3b2SDimitry Andric patchOffsetsAndSizes(); 8651db9f3b2SDimitry Andric 8661db9f3b2SDimitry Andric // Emit common sections and write debug tables from all object files/compile 8671db9f3b2SDimitry Andric // units into the resulting file. 8681db9f3b2SDimitry Andric emitCommonSectionsAndWriteCompileUnitsToTheOutput(); 8691db9f3b2SDimitry Andric 8701db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) 8711db9f3b2SDimitry Andric ArtificialTypeUnit.reset(); 8721db9f3b2SDimitry Andric 8731db9f3b2SDimitry Andric // Write common debug sections into the resulting file. 8741db9f3b2SDimitry Andric writeCommonSectionsToTheOutput(); 8751db9f3b2SDimitry Andric 8761db9f3b2SDimitry Andric // Cleanup data. 8771db9f3b2SDimitry Andric cleanupDataAfterDWARFOutputIsWritten(); 8781db9f3b2SDimitry Andric 8791db9f3b2SDimitry Andric if (GlobalData.getOptions().Statistics) 8801db9f3b2SDimitry Andric printStatistic(); 8811db9f3b2SDimitry Andric } 8821db9f3b2SDimitry Andric 8831db9f3b2SDimitry Andric void DWARFLinkerImpl::printStatistic() { 8841db9f3b2SDimitry Andric 8851db9f3b2SDimitry Andric // For each object file map how many bytes were emitted. 8861db9f3b2SDimitry Andric StringMap<DebugInfoSize> SizeByObject; 8871db9f3b2SDimitry Andric 8881db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) { 8891db9f3b2SDimitry Andric uint64_t AllDebugInfoSectionsSize = 0; 8901db9f3b2SDimitry Andric 8911db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 8921db9f3b2SDimitry Andric if (std::optional<SectionDescriptor *> DebugInfo = 8931db9f3b2SDimitry Andric CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) 8941db9f3b2SDimitry Andric AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size(); 8951db9f3b2SDimitry Andric 8961db9f3b2SDimitry Andric SizeByObject[Context->InputDWARFFile.FileName].Input = 8971db9f3b2SDimitry Andric Context->OriginalDebugInfoSize; 8981db9f3b2SDimitry Andric SizeByObject[Context->InputDWARFFile.FileName].Output = 8991db9f3b2SDimitry Andric AllDebugInfoSectionsSize; 9001db9f3b2SDimitry Andric } 9011db9f3b2SDimitry Andric 9021db9f3b2SDimitry Andric // Create a vector sorted in descending order by output size. 9031db9f3b2SDimitry Andric std::vector<std::pair<StringRef, DebugInfoSize>> Sorted; 9041db9f3b2SDimitry Andric for (auto &E : SizeByObject) 9051db9f3b2SDimitry Andric Sorted.emplace_back(E.first(), E.second); 9061db9f3b2SDimitry Andric llvm::sort(Sorted, [](auto &LHS, auto &RHS) { 9071db9f3b2SDimitry Andric return LHS.second.Output > RHS.second.Output; 9081db9f3b2SDimitry Andric }); 9091db9f3b2SDimitry Andric 9101db9f3b2SDimitry Andric auto ComputePercentange = [](int64_t Input, int64_t Output) -> float { 9111db9f3b2SDimitry Andric const float Difference = Output - Input; 9121db9f3b2SDimitry Andric const float Sum = Input + Output; 9131db9f3b2SDimitry Andric if (Sum == 0) 9141db9f3b2SDimitry Andric return 0; 9151db9f3b2SDimitry Andric return (Difference / (Sum / 2)); 9161db9f3b2SDimitry Andric }; 9171db9f3b2SDimitry Andric 9181db9f3b2SDimitry Andric int64_t InputTotal = 0; 9191db9f3b2SDimitry Andric int64_t OutputTotal = 0; 9201db9f3b2SDimitry Andric const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n"; 9211db9f3b2SDimitry Andric 9221db9f3b2SDimitry Andric // Print header. 9231db9f3b2SDimitry Andric outs() << ".debug_info section size (in bytes)\n"; 9241db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 9251db9f3b2SDimitry Andric "---------------\n"; 9261db9f3b2SDimitry Andric outs() << "Filename Object " 9271db9f3b2SDimitry Andric " dSYM Change\n"; 9281db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 9291db9f3b2SDimitry Andric "---------------\n"; 9301db9f3b2SDimitry Andric 9311db9f3b2SDimitry Andric // Print body. 9321db9f3b2SDimitry Andric for (auto &E : Sorted) { 9331db9f3b2SDimitry Andric InputTotal += E.second.Input; 9341db9f3b2SDimitry Andric OutputTotal += E.second.Output; 9351db9f3b2SDimitry Andric llvm::outs() << formatv( 9361db9f3b2SDimitry Andric FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input, 9371db9f3b2SDimitry Andric E.second.Output, ComputePercentange(E.second.Input, E.second.Output)); 9381db9f3b2SDimitry Andric } 9391db9f3b2SDimitry Andric // Print total and footer. 9401db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 9411db9f3b2SDimitry Andric "---------------\n"; 9421db9f3b2SDimitry Andric llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal, 9431db9f3b2SDimitry Andric ComputePercentange(InputTotal, OutputTotal)); 9441db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 9451db9f3b2SDimitry Andric "---------------\n\n"; 9461db9f3b2SDimitry Andric } 9471db9f3b2SDimitry Andric 9481db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsets() { 9491db9f3b2SDimitry Andric llvm::parallel::TaskGroup TGroup; 9501db9f3b2SDimitry Andric TGroup.spawn([&]() { assignOffsetsToStrings(); }); 9511db9f3b2SDimitry Andric TGroup.spawn([&]() { assignOffsetsToSections(); }); 9521db9f3b2SDimitry Andric } 9531db9f3b2SDimitry Andric 9541db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsetsToStrings() { 9551db9f3b2SDimitry Andric size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry. 9561db9f3b2SDimitry Andric uint64_t CurDebugStrOffset = 9571db9f3b2SDimitry Andric 1; // start from 1 to take into account zero entry. 9581db9f3b2SDimitry Andric size_t CurDebugLineStrIndex = 0; 9591db9f3b2SDimitry Andric uint64_t CurDebugLineStrOffset = 0; 9601db9f3b2SDimitry Andric 9611db9f3b2SDimitry Andric // Enumerates all strings, add them into the DwarfStringPoolEntry map, 9621db9f3b2SDimitry Andric // assign offset and index to the string if it is not indexed yet. 9631db9f3b2SDimitry Andric forEachOutputString([&](StringDestinationKind Kind, 9641db9f3b2SDimitry Andric const StringEntry *String) { 9651db9f3b2SDimitry Andric switch (Kind) { 9661db9f3b2SDimitry Andric case StringDestinationKind::DebugStr: { 9671db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String); 9681db9f3b2SDimitry Andric assert(Entry != nullptr); 9691db9f3b2SDimitry Andric 9701db9f3b2SDimitry Andric if (!Entry->isIndexed()) { 9711db9f3b2SDimitry Andric Entry->Offset = CurDebugStrOffset; 9721db9f3b2SDimitry Andric CurDebugStrOffset += Entry->String.size() + 1; 9731db9f3b2SDimitry Andric Entry->Index = CurDebugStrIndex++; 9741db9f3b2SDimitry Andric } 9751db9f3b2SDimitry Andric } break; 9761db9f3b2SDimitry Andric case StringDestinationKind::DebugLineStr: { 9771db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *Entry = 9781db9f3b2SDimitry Andric DebugLineStrStrings.add(String); 9791db9f3b2SDimitry Andric assert(Entry != nullptr); 9801db9f3b2SDimitry Andric 9811db9f3b2SDimitry Andric if (!Entry->isIndexed()) { 9821db9f3b2SDimitry Andric Entry->Offset = CurDebugLineStrOffset; 9831db9f3b2SDimitry Andric CurDebugLineStrOffset += Entry->String.size() + 1; 9841db9f3b2SDimitry Andric Entry->Index = CurDebugLineStrIndex++; 9851db9f3b2SDimitry Andric } 9861db9f3b2SDimitry Andric } break; 9871db9f3b2SDimitry Andric } 9881db9f3b2SDimitry Andric }); 9891db9f3b2SDimitry Andric } 9901db9f3b2SDimitry Andric 9911db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsetsToSections() { 9921db9f3b2SDimitry Andric std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0}; 9931db9f3b2SDimitry Andric 9941db9f3b2SDimitry Andric forEachObjectSectionsSet([&](OutputSections &UnitSections) { 9951db9f3b2SDimitry Andric UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator); 9961db9f3b2SDimitry Andric }); 9971db9f3b2SDimitry Andric } 9981db9f3b2SDimitry Andric 9991db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachOutputString( 10001db9f3b2SDimitry Andric function_ref<void(StringDestinationKind Kind, const StringEntry *String)> 10011db9f3b2SDimitry Andric StringHandler) { 10021db9f3b2SDimitry Andric // To save space we do not create any separate string table. 10031db9f3b2SDimitry Andric // We use already allocated string patches and accelerator entries: 10041db9f3b2SDimitry Andric // enumerate them in natural order and assign offsets. 10051db9f3b2SDimitry Andric // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str 10061db9f3b2SDimitry Andric // sections in the same order as they were assigned offsets. 10071db9f3b2SDimitry Andric forEachCompileUnit([&](CompileUnit *CU) { 10081db9f3b2SDimitry Andric CU->forEach([&](SectionDescriptor &OutSection) { 10091db9f3b2SDimitry Andric OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) { 10101db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 10111db9f3b2SDimitry Andric }); 10121db9f3b2SDimitry Andric 10131db9f3b2SDimitry Andric OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) { 10141db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugLineStr, Patch.String); 10151db9f3b2SDimitry Andric }); 10161db9f3b2SDimitry Andric }); 10171db9f3b2SDimitry Andric 10181db9f3b2SDimitry Andric CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) { 10191db9f3b2SDimitry Andric StringHandler(DebugStr, Info.String); 10201db9f3b2SDimitry Andric }); 10211db9f3b2SDimitry Andric }); 10221db9f3b2SDimitry Andric 10231db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) { 10241db9f3b2SDimitry Andric ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) { 10251db9f3b2SDimitry Andric OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) { 10261db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 10271db9f3b2SDimitry Andric }); 10281db9f3b2SDimitry Andric 10291db9f3b2SDimitry Andric OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) { 10301db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugLineStr, Patch.String); 10311db9f3b2SDimitry Andric }); 10321db9f3b2SDimitry Andric 10331db9f3b2SDimitry Andric OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) { 10341db9f3b2SDimitry Andric if (Patch.Die == nullptr) 10351db9f3b2SDimitry Andric return; 10361db9f3b2SDimitry Andric 10371db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 10381db9f3b2SDimitry Andric }); 10391db9f3b2SDimitry Andric 10401db9f3b2SDimitry Andric OutSection.ListDebugTypeLineStrPatch.forEach( 10411db9f3b2SDimitry Andric [&](DebugTypeLineStrPatch &Patch) { 10421db9f3b2SDimitry Andric if (Patch.Die == nullptr) 10431db9f3b2SDimitry Andric return; 10441db9f3b2SDimitry Andric 10451db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 10461db9f3b2SDimitry Andric }); 10471db9f3b2SDimitry Andric }); 10481db9f3b2SDimitry Andric } 10491db9f3b2SDimitry Andric } 10501db9f3b2SDimitry Andric 10511db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachObjectSectionsSet( 10521db9f3b2SDimitry Andric function_ref<void(OutputSections &)> SectionsSetHandler) { 10531db9f3b2SDimitry Andric // Handle artificial type unit first. 10541db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) 10551db9f3b2SDimitry Andric SectionsSetHandler(*ArtificialTypeUnit); 10561db9f3b2SDimitry Andric 10571db9f3b2SDimitry Andric // Then all modules(before regular compilation units). 10581db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 10591db9f3b2SDimitry Andric for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 10601db9f3b2SDimitry Andric if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 10611db9f3b2SDimitry Andric SectionsSetHandler(*ModuleUnit.Unit); 10621db9f3b2SDimitry Andric 10631db9f3b2SDimitry Andric // Finally all compilation units. 10641db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) { 10651db9f3b2SDimitry Andric // Handle object file common sections. 10661db9f3b2SDimitry Andric SectionsSetHandler(*Context); 10671db9f3b2SDimitry Andric 10681db9f3b2SDimitry Andric // Handle compilation units. 10691db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 10701db9f3b2SDimitry Andric if (CU->getStage() != CompileUnit::Stage::Skipped) 10711db9f3b2SDimitry Andric SectionsSetHandler(*CU); 10721db9f3b2SDimitry Andric } 10731db9f3b2SDimitry Andric } 10741db9f3b2SDimitry Andric 10751db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachCompileAndTypeUnit( 10761db9f3b2SDimitry Andric function_ref<void(DwarfUnit *CU)> UnitHandler) { 10771db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) 10781db9f3b2SDimitry Andric UnitHandler(ArtificialTypeUnit.get()); 10791db9f3b2SDimitry Andric 10801db9f3b2SDimitry Andric // Enumerate module units. 10811db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 10821db9f3b2SDimitry Andric for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 10831db9f3b2SDimitry Andric if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 10841db9f3b2SDimitry Andric UnitHandler(ModuleUnit.Unit.get()); 10851db9f3b2SDimitry Andric 10861db9f3b2SDimitry Andric // Enumerate compile units. 10871db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 10881db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 10891db9f3b2SDimitry Andric if (CU->getStage() != CompileUnit::Stage::Skipped) 10901db9f3b2SDimitry Andric UnitHandler(CU.get()); 10911db9f3b2SDimitry Andric } 10921db9f3b2SDimitry Andric 10931db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachCompileUnit( 10941db9f3b2SDimitry Andric function_ref<void(CompileUnit *CU)> UnitHandler) { 10951db9f3b2SDimitry Andric // Enumerate module units. 10961db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 10971db9f3b2SDimitry Andric for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 10981db9f3b2SDimitry Andric if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 10991db9f3b2SDimitry Andric UnitHandler(ModuleUnit.Unit.get()); 11001db9f3b2SDimitry Andric 11011db9f3b2SDimitry Andric // Enumerate compile units. 11021db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 11031db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 11041db9f3b2SDimitry Andric if (CU->getStage() != CompileUnit::Stage::Skipped) 11051db9f3b2SDimitry Andric UnitHandler(CU.get()); 11061db9f3b2SDimitry Andric } 11071db9f3b2SDimitry Andric 11081db9f3b2SDimitry Andric void DWARFLinkerImpl::patchOffsetsAndSizes() { 11091db9f3b2SDimitry Andric forEachObjectSectionsSet([&](OutputSections &SectionsSet) { 11101db9f3b2SDimitry Andric SectionsSet.forEach([&](SectionDescriptor &OutSection) { 11111db9f3b2SDimitry Andric SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings, 11121db9f3b2SDimitry Andric ArtificialTypeUnit.get()); 11131db9f3b2SDimitry Andric }); 11141db9f3b2SDimitry Andric }); 11151db9f3b2SDimitry Andric } 11161db9f3b2SDimitry Andric 11171db9f3b2SDimitry Andric void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() { 11181db9f3b2SDimitry Andric llvm::parallel::TaskGroup TG; 11191db9f3b2SDimitry Andric 11201db9f3b2SDimitry Andric // Create section descriptors ahead if they are not exist at the moment. 11211db9f3b2SDimitry Andric // SectionDescriptors container is not thread safe. Thus we should be sure 11221db9f3b2SDimitry Andric // that descriptors would not be created in following parallel tasks. 11231db9f3b2SDimitry Andric 11241db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr); 11251db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr); 11261db9f3b2SDimitry Andric 11271db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 11281db9f3b2SDimitry Andric AccelTableKind::Apple)) { 11291db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames); 11301db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor( 11311db9f3b2SDimitry Andric DebugSectionKind::AppleNamespaces); 11321db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC); 11331db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes); 11341db9f3b2SDimitry Andric } 11351db9f3b2SDimitry Andric 11361db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 11371db9f3b2SDimitry Andric AccelTableKind::DebugNames)) 11381db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames); 11391db9f3b2SDimitry Andric 11401db9f3b2SDimitry Andric // Emit .debug_str and .debug_line_str sections. 11411db9f3b2SDimitry Andric TG.spawn([&]() { emitStringSections(); }); 11421db9f3b2SDimitry Andric 11431db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 11441db9f3b2SDimitry Andric AccelTableKind::Apple)) { 11451db9f3b2SDimitry Andric // Emit apple accelerator sections. 1146*7a6dacacSDimitry Andric TG.spawn([&]() { 1147*7a6dacacSDimitry Andric emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get()); 1148*7a6dacacSDimitry Andric }); 11491db9f3b2SDimitry Andric } 11501db9f3b2SDimitry Andric 11511db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 11521db9f3b2SDimitry Andric AccelTableKind::DebugNames)) { 11531db9f3b2SDimitry Andric // Emit .debug_names section. 1154*7a6dacacSDimitry Andric TG.spawn([&]() { 1155*7a6dacacSDimitry Andric emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get()); 1156*7a6dacacSDimitry Andric }); 11571db9f3b2SDimitry Andric } 11581db9f3b2SDimitry Andric 11591db9f3b2SDimitry Andric // Write compile units to the output file. 11601db9f3b2SDimitry Andric TG.spawn([&]() { writeCompileUnitsToTheOutput(); }); 11611db9f3b2SDimitry Andric } 11621db9f3b2SDimitry Andric 11631db9f3b2SDimitry Andric void DWARFLinkerImpl::emitStringSections() { 11641db9f3b2SDimitry Andric uint64_t DebugStrNextOffset = 0; 11651db9f3b2SDimitry Andric uint64_t DebugLineStrNextOffset = 0; 11661db9f3b2SDimitry Andric 11671db9f3b2SDimitry Andric // Emit zero length string. Accelerator tables does not work correctly 11681db9f3b2SDimitry Andric // if the first string is not zero length string. 11691db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr) 11701db9f3b2SDimitry Andric .emitInplaceString(""); 11711db9f3b2SDimitry Andric DebugStrNextOffset++; 11721db9f3b2SDimitry Andric 11731db9f3b2SDimitry Andric forEachOutputString( 11741db9f3b2SDimitry Andric [&](StringDestinationKind Kind, const StringEntry *String) { 11751db9f3b2SDimitry Andric switch (Kind) { 11761db9f3b2SDimitry Andric case StringDestinationKind::DebugStr: { 11771db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *StringToEmit = 11781db9f3b2SDimitry Andric DebugStrStrings.getExistingEntry(String); 11791db9f3b2SDimitry Andric assert(StringToEmit->isIndexed()); 11801db9f3b2SDimitry Andric 11811db9f3b2SDimitry Andric // Strings may be repeated. Use accumulated DebugStrNextOffset 11821db9f3b2SDimitry Andric // to understand whether corresponding string is already emitted. 11831db9f3b2SDimitry Andric // Skip string if its offset less than accumulated offset. 11841db9f3b2SDimitry Andric if (StringToEmit->Offset >= DebugStrNextOffset) { 11851db9f3b2SDimitry Andric DebugStrNextOffset = 11861db9f3b2SDimitry Andric StringToEmit->Offset + StringToEmit->String.size() + 1; 11871db9f3b2SDimitry Andric // Emit the string itself. 11881db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr) 11891db9f3b2SDimitry Andric .emitInplaceString(StringToEmit->String); 11901db9f3b2SDimitry Andric } 11911db9f3b2SDimitry Andric } break; 11921db9f3b2SDimitry Andric case StringDestinationKind::DebugLineStr: { 11931db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *StringToEmit = 11941db9f3b2SDimitry Andric DebugLineStrStrings.getExistingEntry(String); 11951db9f3b2SDimitry Andric assert(StringToEmit->isIndexed()); 11961db9f3b2SDimitry Andric 11971db9f3b2SDimitry Andric // Strings may be repeated. Use accumulated DebugLineStrStrings 11981db9f3b2SDimitry Andric // to understand whether corresponding string is already emitted. 11991db9f3b2SDimitry Andric // Skip string if its offset less than accumulated offset. 12001db9f3b2SDimitry Andric if (StringToEmit->Offset >= DebugLineStrNextOffset) { 12011db9f3b2SDimitry Andric DebugLineStrNextOffset = 12021db9f3b2SDimitry Andric StringToEmit->Offset + StringToEmit->String.size() + 1; 12031db9f3b2SDimitry Andric // Emit the string itself. 12041db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr) 12051db9f3b2SDimitry Andric .emitInplaceString(StringToEmit->String); 12061db9f3b2SDimitry Andric } 12071db9f3b2SDimitry Andric } break; 12081db9f3b2SDimitry Andric } 12091db9f3b2SDimitry Andric }); 12101db9f3b2SDimitry Andric } 12111db9f3b2SDimitry Andric 12121db9f3b2SDimitry Andric void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) { 12131db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces; 12141db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> AppleNames; 12151db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> AppleObjC; 12161db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticTypeData> AppleTypes; 12171db9f3b2SDimitry Andric 12181db9f3b2SDimitry Andric forEachCompileAndTypeUnit([&](DwarfUnit *CU) { 12191db9f3b2SDimitry Andric CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 12201db9f3b2SDimitry Andric uint64_t OutOffset = Info.OutOffset; 12211db9f3b2SDimitry Andric switch (Info.Type) { 12221db9f3b2SDimitry Andric case DwarfUnit::AccelType::None: { 12231db9f3b2SDimitry Andric llvm_unreachable("Unknown accelerator record"); 12241db9f3b2SDimitry Andric } break; 12251db9f3b2SDimitry Andric case DwarfUnit::AccelType::Namespace: { 12261db9f3b2SDimitry Andric AppleNamespaces.addName( 12271db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 12281db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 12291db9f3b2SDimitry Andric OutOffset); 12301db9f3b2SDimitry Andric } break; 12311db9f3b2SDimitry Andric case DwarfUnit::AccelType::Name: { 12321db9f3b2SDimitry Andric AppleNames.addName( 12331db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 12341db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 12351db9f3b2SDimitry Andric OutOffset); 12361db9f3b2SDimitry Andric } break; 12371db9f3b2SDimitry Andric case DwarfUnit::AccelType::ObjC: { 12381db9f3b2SDimitry Andric AppleObjC.addName( 12391db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 12401db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 12411db9f3b2SDimitry Andric OutOffset); 12421db9f3b2SDimitry Andric } break; 12431db9f3b2SDimitry Andric case DwarfUnit::AccelType::Type: { 12441db9f3b2SDimitry Andric AppleTypes.addName( 12451db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 12461db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 12471db9f3b2SDimitry Andric OutOffset, 12481db9f3b2SDimitry Andric Info.Tag, 12491db9f3b2SDimitry Andric Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation 12501db9f3b2SDimitry Andric : 0, 12511db9f3b2SDimitry Andric Info.QualifiedNameHash); 12521db9f3b2SDimitry Andric } break; 12531db9f3b2SDimitry Andric } 12541db9f3b2SDimitry Andric }); 12551db9f3b2SDimitry Andric }); 12561db9f3b2SDimitry Andric 12571db9f3b2SDimitry Andric { 12581db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 12591db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 12601db9f3b2SDimitry Andric // to the raw_svector_ostream. 12611db9f3b2SDimitry Andric SectionDescriptor &OutSection = 12621db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces); 12631db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 12641db9f3b2SDimitry Andric OutSection.OS); 12651db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 12661db9f3b2SDimitry Andric consumeError(std::move(Err)); 12671db9f3b2SDimitry Andric return; 12681db9f3b2SDimitry Andric } 12691db9f3b2SDimitry Andric 12701db9f3b2SDimitry Andric // Emit table. 12711db9f3b2SDimitry Andric Emitter.emitAppleNamespaces(AppleNamespaces); 12721db9f3b2SDimitry Andric Emitter.finish(); 12731db9f3b2SDimitry Andric 12741db9f3b2SDimitry Andric // Set start offset and size for output section. 12751db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 12761db9f3b2SDimitry Andric } 12771db9f3b2SDimitry Andric 12781db9f3b2SDimitry Andric { 12791db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 12801db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 12811db9f3b2SDimitry Andric // to the raw_svector_ostream. 12821db9f3b2SDimitry Andric SectionDescriptor &OutSection = 12831db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames); 12841db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 12851db9f3b2SDimitry Andric OutSection.OS); 12861db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 12871db9f3b2SDimitry Andric consumeError(std::move(Err)); 12881db9f3b2SDimitry Andric return; 12891db9f3b2SDimitry Andric } 12901db9f3b2SDimitry Andric 12911db9f3b2SDimitry Andric // Emit table. 12921db9f3b2SDimitry Andric Emitter.emitAppleNames(AppleNames); 12931db9f3b2SDimitry Andric Emitter.finish(); 12941db9f3b2SDimitry Andric 12951db9f3b2SDimitry Andric // Set start offset ans size for output section. 12961db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 12971db9f3b2SDimitry Andric } 12981db9f3b2SDimitry Andric 12991db9f3b2SDimitry Andric { 13001db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 13011db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 13021db9f3b2SDimitry Andric // to the raw_svector_ostream. 13031db9f3b2SDimitry Andric SectionDescriptor &OutSection = 13041db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC); 13051db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 13061db9f3b2SDimitry Andric OutSection.OS); 13071db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 13081db9f3b2SDimitry Andric consumeError(std::move(Err)); 13091db9f3b2SDimitry Andric return; 13101db9f3b2SDimitry Andric } 13111db9f3b2SDimitry Andric 13121db9f3b2SDimitry Andric // Emit table. 13131db9f3b2SDimitry Andric Emitter.emitAppleObjc(AppleObjC); 13141db9f3b2SDimitry Andric Emitter.finish(); 13151db9f3b2SDimitry Andric 13161db9f3b2SDimitry Andric // Set start offset ans size for output section. 13171db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 13181db9f3b2SDimitry Andric } 13191db9f3b2SDimitry Andric 13201db9f3b2SDimitry Andric { 13211db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 13221db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 13231db9f3b2SDimitry Andric // to the raw_svector_ostream. 13241db9f3b2SDimitry Andric SectionDescriptor &OutSection = 13251db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes); 13261db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 13271db9f3b2SDimitry Andric OutSection.OS); 13281db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 13291db9f3b2SDimitry Andric consumeError(std::move(Err)); 13301db9f3b2SDimitry Andric return; 13311db9f3b2SDimitry Andric } 13321db9f3b2SDimitry Andric 13331db9f3b2SDimitry Andric // Emit table. 13341db9f3b2SDimitry Andric Emitter.emitAppleTypes(AppleTypes); 13351db9f3b2SDimitry Andric Emitter.finish(); 13361db9f3b2SDimitry Andric 13371db9f3b2SDimitry Andric // Set start offset ans size for output section. 13381db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 13391db9f3b2SDimitry Andric } 13401db9f3b2SDimitry Andric } 13411db9f3b2SDimitry Andric 13421db9f3b2SDimitry Andric void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) { 13431db9f3b2SDimitry Andric std::unique_ptr<DWARF5AccelTable> DebugNames; 13441db9f3b2SDimitry Andric 13451db9f3b2SDimitry Andric DebugNamesUnitsOffsets CompUnits; 13461db9f3b2SDimitry Andric CompUnitIDToIdx CUidToIdx; 13471db9f3b2SDimitry Andric 13481db9f3b2SDimitry Andric unsigned Id = 0; 13491db9f3b2SDimitry Andric 13501db9f3b2SDimitry Andric forEachCompileAndTypeUnit([&](DwarfUnit *CU) { 13511db9f3b2SDimitry Andric bool HasRecords = false; 13521db9f3b2SDimitry Andric CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 13531db9f3b2SDimitry Andric if (DebugNames.get() == nullptr) 13541db9f3b2SDimitry Andric DebugNames = std::make_unique<DWARF5AccelTable>(); 13551db9f3b2SDimitry Andric 13561db9f3b2SDimitry Andric HasRecords = true; 13571db9f3b2SDimitry Andric switch (Info.Type) { 13581db9f3b2SDimitry Andric case DwarfUnit::AccelType::Name: 13591db9f3b2SDimitry Andric case DwarfUnit::AccelType::Namespace: 13601db9f3b2SDimitry Andric case DwarfUnit::AccelType::Type: { 13611db9f3b2SDimitry Andric DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String), 1362*7a6dacacSDimitry Andric Info.OutOffset, std::nullopt /*ParentDIEOffset*/, 1363*7a6dacacSDimitry Andric Info.Tag, CU->getUniqueID()); 13641db9f3b2SDimitry Andric } break; 13651db9f3b2SDimitry Andric 13661db9f3b2SDimitry Andric default: 13671db9f3b2SDimitry Andric break; // Nothing to do. 13681db9f3b2SDimitry Andric }; 13691db9f3b2SDimitry Andric }); 13701db9f3b2SDimitry Andric 13711db9f3b2SDimitry Andric if (HasRecords) { 13721db9f3b2SDimitry Andric CompUnits.push_back( 13731db9f3b2SDimitry Andric CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo) 13741db9f3b2SDimitry Andric .StartOffset); 13751db9f3b2SDimitry Andric CUidToIdx[CU->getUniqueID()] = Id++; 13761db9f3b2SDimitry Andric } 13771db9f3b2SDimitry Andric }); 13781db9f3b2SDimitry Andric 13791db9f3b2SDimitry Andric if (DebugNames.get() != nullptr) { 13801db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 13811db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 13821db9f3b2SDimitry Andric // to the raw_svector_ostream. 13831db9f3b2SDimitry Andric SectionDescriptor &OutSection = 13841db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames); 13851db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 13861db9f3b2SDimitry Andric OutSection.OS); 13871db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 13881db9f3b2SDimitry Andric consumeError(std::move(Err)); 13891db9f3b2SDimitry Andric return; 13901db9f3b2SDimitry Andric } 13911db9f3b2SDimitry Andric 13921db9f3b2SDimitry Andric // Emit table. 13931db9f3b2SDimitry Andric Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx); 13941db9f3b2SDimitry Andric Emitter.finish(); 13951db9f3b2SDimitry Andric 13961db9f3b2SDimitry Andric // Set start offset ans size for output section. 13971db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 13981db9f3b2SDimitry Andric } 13991db9f3b2SDimitry Andric } 14001db9f3b2SDimitry Andric 14011db9f3b2SDimitry Andric void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() { 14021db9f3b2SDimitry Andric GlobalData.getStringPool().clear(); 14031db9f3b2SDimitry Andric DebugStrStrings.clear(); 14041db9f3b2SDimitry Andric DebugLineStrStrings.clear(); 14051db9f3b2SDimitry Andric } 14061db9f3b2SDimitry Andric 14071db9f3b2SDimitry Andric void DWARFLinkerImpl::writeCompileUnitsToTheOutput() { 14081db9f3b2SDimitry Andric // Enumerate all sections and store them into the final emitter. 14091db9f3b2SDimitry Andric forEachObjectSectionsSet([&](OutputSections &Sections) { 1410*7a6dacacSDimitry Andric Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) { 14111db9f3b2SDimitry Andric // Emit section content. 1412*7a6dacacSDimitry Andric SectionHandler(OutSection); 14131db9f3b2SDimitry Andric }); 14141db9f3b2SDimitry Andric }); 14151db9f3b2SDimitry Andric } 14161db9f3b2SDimitry Andric 14171db9f3b2SDimitry Andric void DWARFLinkerImpl::writeCommonSectionsToTheOutput() { 1418*7a6dacacSDimitry Andric CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) { 1419*7a6dacacSDimitry Andric SectionHandler(OutSection); 14201db9f3b2SDimitry Andric }); 14211db9f3b2SDimitry Andric } 1422