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