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