1*1db9f3b2SDimitry Andric //=== DWARFLinkerImpl.cpp -------------------------------------------------===// 2*1db9f3b2SDimitry Andric // 3*1db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*1db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*1db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*1db9f3b2SDimitry Andric // 7*1db9f3b2SDimitry Andric //===----------------------------------------------------------------------===// 8*1db9f3b2SDimitry Andric 9*1db9f3b2SDimitry Andric #include "DWARFLinkerImpl.h" 10*1db9f3b2SDimitry Andric #include "DIEGenerator.h" 11*1db9f3b2SDimitry Andric #include "DependencyTracker.h" 12*1db9f3b2SDimitry Andric #include "Utils.h" 13*1db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 14*1db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h" 15*1db9f3b2SDimitry Andric #include "llvm/Support/Parallel.h" 16*1db9f3b2SDimitry Andric #include "llvm/Support/ThreadPool.h" 17*1db9f3b2SDimitry Andric 18*1db9f3b2SDimitry Andric using namespace llvm; 19*1db9f3b2SDimitry Andric using namespace dwarf_linker; 20*1db9f3b2SDimitry Andric using namespace dwarf_linker::parallel; 21*1db9f3b2SDimitry Andric 22*1db9f3b2SDimitry Andric DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler, 23*1db9f3b2SDimitry Andric MessageHandlerTy WarningHandler, 24*1db9f3b2SDimitry Andric TranslatorFuncTy StringsTranslator) 25*1db9f3b2SDimitry Andric : UniqueUnitID(0), DebugStrStrings(GlobalData), 26*1db9f3b2SDimitry Andric DebugLineStrStrings(GlobalData), CommonSections(GlobalData) { 27*1db9f3b2SDimitry Andric GlobalData.setTranslator(StringsTranslator); 28*1db9f3b2SDimitry Andric GlobalData.setErrorHandler(ErrorHandler); 29*1db9f3b2SDimitry Andric GlobalData.setWarningHandler(WarningHandler); 30*1db9f3b2SDimitry Andric } 31*1db9f3b2SDimitry Andric 32*1db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData, 33*1db9f3b2SDimitry Andric DWARFFile &File, 34*1db9f3b2SDimitry Andric StringMap<uint64_t> &ClangModules, 35*1db9f3b2SDimitry Andric std::atomic<size_t> &UniqueUnitID, 36*1db9f3b2SDimitry Andric std::optional<Triple> TargetTriple) 37*1db9f3b2SDimitry Andric : OutputSections(GlobalData), InputDWARFFile(File), 38*1db9f3b2SDimitry Andric ClangModules(ClangModules), TargetTriple(TargetTriple), 39*1db9f3b2SDimitry Andric UniqueUnitID(UniqueUnitID) { 40*1db9f3b2SDimitry Andric 41*1db9f3b2SDimitry Andric if (File.Dwarf) { 42*1db9f3b2SDimitry Andric if (!File.Dwarf->compile_units().empty()) 43*1db9f3b2SDimitry Andric CompileUnits.reserve(File.Dwarf->getNumCompileUnits()); 44*1db9f3b2SDimitry Andric 45*1db9f3b2SDimitry Andric // Set context format&endianness based on the input file. 46*1db9f3b2SDimitry Andric Format.Version = File.Dwarf->getMaxVersion(); 47*1db9f3b2SDimitry Andric Format.AddrSize = File.Dwarf->getCUAddrSize(); 48*1db9f3b2SDimitry Andric Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little 49*1db9f3b2SDimitry Andric : llvm::endianness::big; 50*1db9f3b2SDimitry Andric } 51*1db9f3b2SDimitry Andric } 52*1db9f3b2SDimitry Andric 53*1db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit( 54*1db9f3b2SDimitry Andric DWARFFile &File, std::unique_ptr<CompileUnit> Unit) 55*1db9f3b2SDimitry Andric : File(File), Unit(std::move(Unit)) {} 56*1db9f3b2SDimitry Andric 57*1db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit( 58*1db9f3b2SDimitry Andric LinkContext::RefModuleUnit &&Other) 59*1db9f3b2SDimitry Andric : File(Other.File), Unit(std::move(Other.Unit)) {} 60*1db9f3b2SDimitry Andric 61*1db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::addModulesCompileUnit( 62*1db9f3b2SDimitry Andric LinkContext::RefModuleUnit &&Unit) { 63*1db9f3b2SDimitry Andric ModulesCompileUnits.emplace_back(std::move(Unit)); 64*1db9f3b2SDimitry Andric } 65*1db9f3b2SDimitry Andric 66*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::createEmitter(const Triple &TheTriple, 67*1db9f3b2SDimitry Andric OutputFileType FileType, 68*1db9f3b2SDimitry Andric raw_pwrite_stream &OutFile) { 69*1db9f3b2SDimitry Andric 70*1db9f3b2SDimitry Andric TheDwarfEmitter = std::make_unique<DwarfEmitterImpl>(FileType, OutFile); 71*1db9f3b2SDimitry Andric 72*1db9f3b2SDimitry Andric return TheDwarfEmitter->init(TheTriple, "__DWARF"); 73*1db9f3b2SDimitry Andric } 74*1db9f3b2SDimitry Andric 75*1db9f3b2SDimitry Andric ExtraDwarfEmitter *DWARFLinkerImpl::getEmitter() { 76*1db9f3b2SDimitry Andric return TheDwarfEmitter.get(); 77*1db9f3b2SDimitry Andric } 78*1db9f3b2SDimitry Andric 79*1db9f3b2SDimitry Andric void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader, 80*1db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded) { 81*1db9f3b2SDimitry Andric ObjectContexts.emplace_back(std::make_unique<LinkContext>( 82*1db9f3b2SDimitry Andric GlobalData, File, ClangModules, UniqueUnitID, 83*1db9f3b2SDimitry Andric (TheDwarfEmitter.get() == nullptr ? std::optional<Triple>(std::nullopt) 84*1db9f3b2SDimitry Andric : TheDwarfEmitter->getTargetTriple()))); 85*1db9f3b2SDimitry Andric 86*1db9f3b2SDimitry Andric if (ObjectContexts.back()->InputDWARFFile.Dwarf) { 87*1db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &CU : 88*1db9f3b2SDimitry Andric ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) { 89*1db9f3b2SDimitry Andric DWARFDie CUDie = CU->getUnitDIE(); 90*1db9f3b2SDimitry Andric OverallNumberOfCU++; 91*1db9f3b2SDimitry Andric 92*1db9f3b2SDimitry Andric if (!CUDie) 93*1db9f3b2SDimitry Andric continue; 94*1db9f3b2SDimitry Andric 95*1db9f3b2SDimitry Andric OnCUDieLoaded(*CU); 96*1db9f3b2SDimitry Andric 97*1db9f3b2SDimitry Andric // Register mofule reference. 98*1db9f3b2SDimitry Andric if (!GlobalData.getOptions().UpdateIndexTablesOnly) 99*1db9f3b2SDimitry Andric ObjectContexts.back()->registerModuleReference(CUDie, Loader, 100*1db9f3b2SDimitry Andric OnCUDieLoaded); 101*1db9f3b2SDimitry Andric } 102*1db9f3b2SDimitry Andric } 103*1db9f3b2SDimitry Andric } 104*1db9f3b2SDimitry Andric 105*1db9f3b2SDimitry Andric void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) { 106*1db9f3b2SDimitry Andric ObjectContexts.reserve(ObjFilesNum); 107*1db9f3b2SDimitry Andric } 108*1db9f3b2SDimitry Andric 109*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::link() { 110*1db9f3b2SDimitry Andric // reset compile unit unique ID counter. 111*1db9f3b2SDimitry Andric UniqueUnitID = 0; 112*1db9f3b2SDimitry Andric 113*1db9f3b2SDimitry Andric if (Error Err = validateAndUpdateOptions()) 114*1db9f3b2SDimitry Andric return Err; 115*1db9f3b2SDimitry Andric 116*1db9f3b2SDimitry Andric dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion, 117*1db9f3b2SDimitry Andric 0, dwarf::DwarfFormat::DWARF32}; 118*1db9f3b2SDimitry Andric llvm::endianness GlobalEndianness = llvm::endianness::native; 119*1db9f3b2SDimitry Andric 120*1db9f3b2SDimitry Andric if (TheDwarfEmitter) { 121*1db9f3b2SDimitry Andric GlobalEndianness = TheDwarfEmitter->getTargetTriple().isLittleEndian() 122*1db9f3b2SDimitry Andric ? llvm::endianness::little 123*1db9f3b2SDimitry Andric : llvm::endianness::big; 124*1db9f3b2SDimitry Andric } 125*1db9f3b2SDimitry Andric std::optional<uint16_t> Language; 126*1db9f3b2SDimitry Andric 127*1db9f3b2SDimitry Andric for (std::unique_ptr<LinkContext> &Context : ObjectContexts) { 128*1db9f3b2SDimitry Andric if (Context->InputDWARFFile.Dwarf.get() == nullptr) { 129*1db9f3b2SDimitry Andric Context->setOutputFormat(Context->getFormParams(), GlobalEndianness); 130*1db9f3b2SDimitry Andric continue; 131*1db9f3b2SDimitry Andric } 132*1db9f3b2SDimitry Andric 133*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) { 134*1db9f3b2SDimitry Andric outs() << "OBJECT: " << Context->InputDWARFFile.FileName << "\n"; 135*1db9f3b2SDimitry Andric 136*1db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &OrigCU : 137*1db9f3b2SDimitry Andric Context->InputDWARFFile.Dwarf->compile_units()) { 138*1db9f3b2SDimitry Andric outs() << "Input compilation unit:"; 139*1db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 140*1db9f3b2SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 141*1db9f3b2SDimitry Andric DumpOpts.Verbose = GlobalData.getOptions().Verbose; 142*1db9f3b2SDimitry Andric OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts); 143*1db9f3b2SDimitry Andric } 144*1db9f3b2SDimitry Andric } 145*1db9f3b2SDimitry Andric 146*1db9f3b2SDimitry Andric // Verify input DWARF if requested. 147*1db9f3b2SDimitry Andric if (GlobalData.getOptions().VerifyInputDWARF) 148*1db9f3b2SDimitry Andric verifyInput(Context->InputDWARFFile); 149*1db9f3b2SDimitry Andric 150*1db9f3b2SDimitry Andric if (!TheDwarfEmitter) 151*1db9f3b2SDimitry Andric GlobalEndianness = Context->getEndianness(); 152*1db9f3b2SDimitry Andric GlobalFormat.AddrSize = 153*1db9f3b2SDimitry Andric std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize); 154*1db9f3b2SDimitry Andric 155*1db9f3b2SDimitry Andric Context->setOutputFormat(Context->getFormParams(), GlobalEndianness); 156*1db9f3b2SDimitry Andric 157*1db9f3b2SDimitry Andric // FIXME: move creation of CompileUnits into the addObjectFile. 158*1db9f3b2SDimitry Andric // This would allow to not scan for context Language and Modules state 159*1db9f3b2SDimitry Andric // twice. And then following handling might be removed. 160*1db9f3b2SDimitry Andric for (const std::unique_ptr<DWARFUnit> &OrigCU : 161*1db9f3b2SDimitry Andric Context->InputDWARFFile.Dwarf->compile_units()) { 162*1db9f3b2SDimitry Andric DWARFDie UnitDie = OrigCU.get()->getUnitDIE(); 163*1db9f3b2SDimitry Andric 164*1db9f3b2SDimitry Andric if (!Language) { 165*1db9f3b2SDimitry Andric if (std::optional<DWARFFormValue> Val = 166*1db9f3b2SDimitry Andric UnitDie.find(dwarf::DW_AT_language)) { 167*1db9f3b2SDimitry Andric uint16_t LangVal = dwarf::toUnsigned(Val, 0); 168*1db9f3b2SDimitry Andric if (isODRLanguage(LangVal)) 169*1db9f3b2SDimitry Andric Language = LangVal; 170*1db9f3b2SDimitry Andric } 171*1db9f3b2SDimitry Andric } 172*1db9f3b2SDimitry Andric } 173*1db9f3b2SDimitry Andric } 174*1db9f3b2SDimitry Andric 175*1db9f3b2SDimitry Andric if (GlobalFormat.AddrSize == 0) { 176*1db9f3b2SDimitry Andric if (TheDwarfEmitter) 177*1db9f3b2SDimitry Andric GlobalFormat.AddrSize = 178*1db9f3b2SDimitry Andric TheDwarfEmitter->getTargetTriple().isArch32Bit() ? 4 : 8; 179*1db9f3b2SDimitry Andric else 180*1db9f3b2SDimitry Andric GlobalFormat.AddrSize = 8; 181*1db9f3b2SDimitry Andric } 182*1db9f3b2SDimitry Andric 183*1db9f3b2SDimitry Andric CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness); 184*1db9f3b2SDimitry Andric 185*1db9f3b2SDimitry Andric if (!GlobalData.Options.NoODR && Language.has_value()) { 186*1db9f3b2SDimitry Andric llvm::parallel::TaskGroup TGroup; 187*1db9f3b2SDimitry Andric TGroup.spawn([&]() { 188*1db9f3b2SDimitry Andric ArtificialTypeUnit = std::make_unique<TypeUnit>( 189*1db9f3b2SDimitry Andric GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness); 190*1db9f3b2SDimitry Andric }); 191*1db9f3b2SDimitry Andric } 192*1db9f3b2SDimitry Andric 193*1db9f3b2SDimitry Andric // Set parallel options. 194*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Threads == 0) 195*1db9f3b2SDimitry Andric llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU); 196*1db9f3b2SDimitry Andric else 197*1db9f3b2SDimitry Andric llvm::parallel::strategy = 198*1db9f3b2SDimitry Andric hardware_concurrency(GlobalData.getOptions().Threads); 199*1db9f3b2SDimitry Andric 200*1db9f3b2SDimitry Andric // Link object files. 201*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Threads == 1) { 202*1db9f3b2SDimitry Andric for (std::unique_ptr<LinkContext> &Context : ObjectContexts) { 203*1db9f3b2SDimitry Andric // Link object file. 204*1db9f3b2SDimitry Andric if (Error Err = Context->link(ArtificialTypeUnit.get())) 205*1db9f3b2SDimitry Andric GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName); 206*1db9f3b2SDimitry Andric 207*1db9f3b2SDimitry Andric Context->InputDWARFFile.unload(); 208*1db9f3b2SDimitry Andric } 209*1db9f3b2SDimitry Andric } else { 210*1db9f3b2SDimitry Andric ThreadPool Pool(llvm::parallel::strategy); 211*1db9f3b2SDimitry Andric for (std::unique_ptr<LinkContext> &Context : ObjectContexts) 212*1db9f3b2SDimitry Andric Pool.async([&]() { 213*1db9f3b2SDimitry Andric // Link object file. 214*1db9f3b2SDimitry Andric if (Error Err = Context->link(ArtificialTypeUnit.get())) 215*1db9f3b2SDimitry Andric GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName); 216*1db9f3b2SDimitry Andric 217*1db9f3b2SDimitry Andric Context->InputDWARFFile.unload(); 218*1db9f3b2SDimitry Andric }); 219*1db9f3b2SDimitry Andric 220*1db9f3b2SDimitry Andric Pool.wait(); 221*1db9f3b2SDimitry Andric } 222*1db9f3b2SDimitry Andric 223*1db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr && !ArtificialTypeUnit->getTypePool() 224*1db9f3b2SDimitry Andric .getRoot() 225*1db9f3b2SDimitry Andric ->getValue() 226*1db9f3b2SDimitry Andric .load() 227*1db9f3b2SDimitry Andric ->Children.empty()) { 228*1db9f3b2SDimitry Andric std::optional<Triple> OutTriple = TheDwarfEmitter.get() == nullptr 229*1db9f3b2SDimitry Andric ? std::optional<Triple>(std::nullopt) 230*1db9f3b2SDimitry Andric : TheDwarfEmitter->getTargetTriple(); 231*1db9f3b2SDimitry Andric 232*1db9f3b2SDimitry Andric if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit(OutTriple)) 233*1db9f3b2SDimitry Andric return Err; 234*1db9f3b2SDimitry Andric } 235*1db9f3b2SDimitry Andric 236*1db9f3b2SDimitry Andric // At this stage each compile units are cloned to their own set of debug 237*1db9f3b2SDimitry Andric // sections. Now, update patches, assign offsets and assemble final file 238*1db9f3b2SDimitry Andric // glueing debug tables from each compile unit. 239*1db9f3b2SDimitry Andric glueCompileUnitsAndWriteToTheOutput(); 240*1db9f3b2SDimitry Andric 241*1db9f3b2SDimitry Andric return Error::success(); 242*1db9f3b2SDimitry Andric } 243*1db9f3b2SDimitry Andric 244*1db9f3b2SDimitry Andric void DWARFLinkerImpl::verifyInput(const DWARFFile &File) { 245*1db9f3b2SDimitry Andric assert(File.Dwarf); 246*1db9f3b2SDimitry Andric 247*1db9f3b2SDimitry Andric std::string Buffer; 248*1db9f3b2SDimitry Andric raw_string_ostream OS(Buffer); 249*1db9f3b2SDimitry Andric DIDumpOptions DumpOpts; 250*1db9f3b2SDimitry Andric if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) { 251*1db9f3b2SDimitry Andric if (GlobalData.getOptions().InputVerificationHandler) 252*1db9f3b2SDimitry Andric GlobalData.getOptions().InputVerificationHandler(File, OS.str()); 253*1db9f3b2SDimitry Andric } 254*1db9f3b2SDimitry Andric } 255*1db9f3b2SDimitry Andric 256*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::validateAndUpdateOptions() { 257*1db9f3b2SDimitry Andric if (GlobalData.getOptions().TargetDWARFVersion == 0) 258*1db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 259*1db9f3b2SDimitry Andric "target DWARF version is not set"); 260*1db9f3b2SDimitry Andric 261*1db9f3b2SDimitry Andric GlobalData.Options.NoOutput = TheDwarfEmitter.get() == nullptr; 262*1db9f3b2SDimitry Andric 263*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) { 264*1db9f3b2SDimitry Andric GlobalData.Options.Threads = 1; 265*1db9f3b2SDimitry Andric GlobalData.warn( 266*1db9f3b2SDimitry Andric "set number of threads to 1 to make --verbose to work properly.", ""); 267*1db9f3b2SDimitry Andric } 268*1db9f3b2SDimitry Andric 269*1db9f3b2SDimitry Andric // Do not do types deduplication in case --update. 270*1db9f3b2SDimitry Andric if (GlobalData.getOptions().UpdateIndexTablesOnly && 271*1db9f3b2SDimitry Andric !GlobalData.Options.NoODR) 272*1db9f3b2SDimitry Andric GlobalData.Options.NoODR = true; 273*1db9f3b2SDimitry Andric 274*1db9f3b2SDimitry Andric return Error::success(); 275*1db9f3b2SDimitry Andric } 276*1db9f3b2SDimitry Andric 277*1db9f3b2SDimitry Andric /// Resolve the relative path to a build artifact referenced by DWARF by 278*1db9f3b2SDimitry Andric /// applying DW_AT_comp_dir. 279*1db9f3b2SDimitry Andric static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { 280*1db9f3b2SDimitry Andric sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), "")); 281*1db9f3b2SDimitry Andric } 282*1db9f3b2SDimitry Andric 283*1db9f3b2SDimitry Andric static uint64_t getDwoId(const DWARFDie &CUDie) { 284*1db9f3b2SDimitry Andric auto DwoId = dwarf::toUnsigned( 285*1db9f3b2SDimitry Andric CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id})); 286*1db9f3b2SDimitry Andric if (DwoId) 287*1db9f3b2SDimitry Andric return *DwoId; 288*1db9f3b2SDimitry Andric return 0; 289*1db9f3b2SDimitry Andric } 290*1db9f3b2SDimitry Andric 291*1db9f3b2SDimitry Andric static std::string 292*1db9f3b2SDimitry Andric remapPath(StringRef Path, 293*1db9f3b2SDimitry Andric const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) { 294*1db9f3b2SDimitry Andric if (ObjectPrefixMap.empty()) 295*1db9f3b2SDimitry Andric return Path.str(); 296*1db9f3b2SDimitry Andric 297*1db9f3b2SDimitry Andric SmallString<256> p = Path; 298*1db9f3b2SDimitry Andric for (const auto &Entry : ObjectPrefixMap) 299*1db9f3b2SDimitry Andric if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second)) 300*1db9f3b2SDimitry Andric break; 301*1db9f3b2SDimitry Andric return p.str().str(); 302*1db9f3b2SDimitry Andric } 303*1db9f3b2SDimitry Andric 304*1db9f3b2SDimitry Andric static std::string getPCMFile(const DWARFDie &CUDie, 305*1db9f3b2SDimitry Andric DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) { 306*1db9f3b2SDimitry Andric std::string PCMFile = dwarf::toString( 307*1db9f3b2SDimitry Andric CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), ""); 308*1db9f3b2SDimitry Andric 309*1db9f3b2SDimitry Andric if (PCMFile.empty()) 310*1db9f3b2SDimitry Andric return PCMFile; 311*1db9f3b2SDimitry Andric 312*1db9f3b2SDimitry Andric if (ObjectPrefixMap) 313*1db9f3b2SDimitry Andric PCMFile = remapPath(PCMFile, *ObjectPrefixMap); 314*1db9f3b2SDimitry Andric 315*1db9f3b2SDimitry Andric return PCMFile; 316*1db9f3b2SDimitry Andric } 317*1db9f3b2SDimitry Andric 318*1db9f3b2SDimitry Andric std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef( 319*1db9f3b2SDimitry Andric const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) { 320*1db9f3b2SDimitry Andric if (PCMFile.empty()) 321*1db9f3b2SDimitry Andric return std::make_pair(false, false); 322*1db9f3b2SDimitry Andric 323*1db9f3b2SDimitry Andric // Clang module DWARF skeleton CUs abuse this for the path to the module. 324*1db9f3b2SDimitry Andric uint64_t DwoId = getDwoId(CUDie); 325*1db9f3b2SDimitry Andric 326*1db9f3b2SDimitry Andric std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 327*1db9f3b2SDimitry Andric if (Name.empty()) { 328*1db9f3b2SDimitry Andric if (!Quiet) 329*1db9f3b2SDimitry Andric GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".", 330*1db9f3b2SDimitry Andric InputDWARFFile.FileName); 331*1db9f3b2SDimitry Andric return std::make_pair(true, true); 332*1db9f3b2SDimitry Andric } 333*1db9f3b2SDimitry Andric 334*1db9f3b2SDimitry Andric if (!Quiet && GlobalData.getOptions().Verbose) { 335*1db9f3b2SDimitry Andric outs().indent(Indent); 336*1db9f3b2SDimitry Andric outs() << "Found clang module reference " << PCMFile; 337*1db9f3b2SDimitry Andric } 338*1db9f3b2SDimitry Andric 339*1db9f3b2SDimitry Andric auto Cached = ClangModules.find(PCMFile); 340*1db9f3b2SDimitry Andric if (Cached != ClangModules.end()) { 341*1db9f3b2SDimitry Andric // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 342*1db9f3b2SDimitry Andric // fixed in clang, only warn about DWO_id mismatches in verbose mode. 343*1db9f3b2SDimitry Andric // ASTFileSignatures will change randomly when a module is rebuilt. 344*1db9f3b2SDimitry Andric if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId)) 345*1db9f3b2SDimitry Andric GlobalData.warn( 346*1db9f3b2SDimitry Andric Twine("hash mismatch: this object file was built against a " 347*1db9f3b2SDimitry Andric "different version of the module ") + 348*1db9f3b2SDimitry Andric PCMFile + ".", 349*1db9f3b2SDimitry Andric InputDWARFFile.FileName); 350*1db9f3b2SDimitry Andric if (!Quiet && GlobalData.getOptions().Verbose) 351*1db9f3b2SDimitry Andric outs() << " [cached].\n"; 352*1db9f3b2SDimitry Andric return std::make_pair(true, true); 353*1db9f3b2SDimitry Andric } 354*1db9f3b2SDimitry Andric 355*1db9f3b2SDimitry Andric return std::make_pair(true, false); 356*1db9f3b2SDimitry Andric } 357*1db9f3b2SDimitry Andric 358*1db9f3b2SDimitry Andric /// If this compile unit is really a skeleton CU that points to a 359*1db9f3b2SDimitry Andric /// clang module, register it in ClangModules and return true. 360*1db9f3b2SDimitry Andric /// 361*1db9f3b2SDimitry Andric /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name 362*1db9f3b2SDimitry Andric /// pointing to the module, and a DW_AT_gnu_dwo_id with the module 363*1db9f3b2SDimitry Andric /// hash. 364*1db9f3b2SDimitry Andric bool DWARFLinkerImpl::LinkContext::registerModuleReference( 365*1db9f3b2SDimitry Andric const DWARFDie &CUDie, ObjFileLoaderTy Loader, 366*1db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 367*1db9f3b2SDimitry Andric std::string PCMFile = 368*1db9f3b2SDimitry Andric getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap); 369*1db9f3b2SDimitry Andric std::pair<bool, bool> IsClangModuleRef = 370*1db9f3b2SDimitry Andric isClangModuleRef(CUDie, PCMFile, Indent, false); 371*1db9f3b2SDimitry Andric 372*1db9f3b2SDimitry Andric if (!IsClangModuleRef.first) 373*1db9f3b2SDimitry Andric return false; 374*1db9f3b2SDimitry Andric 375*1db9f3b2SDimitry Andric if (IsClangModuleRef.second) 376*1db9f3b2SDimitry Andric return true; 377*1db9f3b2SDimitry Andric 378*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) 379*1db9f3b2SDimitry Andric outs() << " ...\n"; 380*1db9f3b2SDimitry Andric 381*1db9f3b2SDimitry Andric // Cyclic dependencies are disallowed by Clang, but we still 382*1db9f3b2SDimitry Andric // shouldn't run into an infinite loop, so mark it as processed now. 383*1db9f3b2SDimitry Andric ClangModules.insert({PCMFile, getDwoId(CUDie)}); 384*1db9f3b2SDimitry Andric 385*1db9f3b2SDimitry Andric if (Error E = 386*1db9f3b2SDimitry Andric loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) { 387*1db9f3b2SDimitry Andric consumeError(std::move(E)); 388*1db9f3b2SDimitry Andric return false; 389*1db9f3b2SDimitry Andric } 390*1db9f3b2SDimitry Andric return true; 391*1db9f3b2SDimitry Andric } 392*1db9f3b2SDimitry Andric 393*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::loadClangModule( 394*1db9f3b2SDimitry Andric ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile, 395*1db9f3b2SDimitry Andric CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { 396*1db9f3b2SDimitry Andric 397*1db9f3b2SDimitry Andric uint64_t DwoId = getDwoId(CUDie); 398*1db9f3b2SDimitry Andric std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), ""); 399*1db9f3b2SDimitry Andric 400*1db9f3b2SDimitry Andric /// Using a SmallString<0> because loadClangModule() is recursive. 401*1db9f3b2SDimitry Andric SmallString<0> Path(GlobalData.getOptions().PrependPath); 402*1db9f3b2SDimitry Andric if (sys::path::is_relative(PCMFile)) 403*1db9f3b2SDimitry Andric resolveRelativeObjectPath(Path, CUDie); 404*1db9f3b2SDimitry Andric sys::path::append(Path, PCMFile); 405*1db9f3b2SDimitry Andric // Don't use the cached binary holder because we have no thread-safety 406*1db9f3b2SDimitry Andric // guarantee and the lifetime is limited. 407*1db9f3b2SDimitry Andric 408*1db9f3b2SDimitry Andric if (Loader == nullptr) { 409*1db9f3b2SDimitry Andric GlobalData.error("cann't load clang module: loader is not specified.", 410*1db9f3b2SDimitry Andric InputDWARFFile.FileName); 411*1db9f3b2SDimitry Andric return Error::success(); 412*1db9f3b2SDimitry Andric } 413*1db9f3b2SDimitry Andric 414*1db9f3b2SDimitry Andric auto ErrOrObj = Loader(InputDWARFFile.FileName, Path); 415*1db9f3b2SDimitry Andric if (!ErrOrObj) 416*1db9f3b2SDimitry Andric return Error::success(); 417*1db9f3b2SDimitry Andric 418*1db9f3b2SDimitry Andric std::unique_ptr<CompileUnit> Unit; 419*1db9f3b2SDimitry Andric for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { 420*1db9f3b2SDimitry Andric OnCUDieLoaded(*CU); 421*1db9f3b2SDimitry Andric // Recursively get all modules imported by this one. 422*1db9f3b2SDimitry Andric auto ChildCUDie = CU->getUnitDIE(); 423*1db9f3b2SDimitry Andric if (!ChildCUDie) 424*1db9f3b2SDimitry Andric continue; 425*1db9f3b2SDimitry Andric if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) { 426*1db9f3b2SDimitry Andric if (Unit) { 427*1db9f3b2SDimitry Andric std::string Err = 428*1db9f3b2SDimitry Andric (PCMFile + 429*1db9f3b2SDimitry Andric ": Clang modules are expected to have exactly 1 compile unit.\n"); 430*1db9f3b2SDimitry Andric GlobalData.error(Err, InputDWARFFile.FileName); 431*1db9f3b2SDimitry Andric return make_error<StringError>(Err, inconvertibleErrorCode()); 432*1db9f3b2SDimitry Andric } 433*1db9f3b2SDimitry Andric // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is 434*1db9f3b2SDimitry Andric // fixed in clang, only warn about DWO_id mismatches in verbose mode. 435*1db9f3b2SDimitry Andric // ASTFileSignatures will change randomly when a module is rebuilt. 436*1db9f3b2SDimitry Andric uint64_t PCMDwoId = getDwoId(ChildCUDie); 437*1db9f3b2SDimitry Andric if (PCMDwoId != DwoId) { 438*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) 439*1db9f3b2SDimitry Andric GlobalData.warn( 440*1db9f3b2SDimitry Andric Twine("hash mismatch: this object file was built against a " 441*1db9f3b2SDimitry Andric "different version of the module ") + 442*1db9f3b2SDimitry Andric PCMFile + ".", 443*1db9f3b2SDimitry Andric InputDWARFFile.FileName); 444*1db9f3b2SDimitry Andric // Update the cache entry with the DwoId of the module loaded from disk. 445*1db9f3b2SDimitry Andric ClangModules[PCMFile] = PCMDwoId; 446*1db9f3b2SDimitry Andric } 447*1db9f3b2SDimitry Andric 448*1db9f3b2SDimitry Andric // Empty modules units should not be cloned. 449*1db9f3b2SDimitry Andric if (!ChildCUDie.hasChildren()) 450*1db9f3b2SDimitry Andric continue; 451*1db9f3b2SDimitry Andric 452*1db9f3b2SDimitry Andric // Add this module. 453*1db9f3b2SDimitry Andric Unit = std::make_unique<CompileUnit>( 454*1db9f3b2SDimitry Andric GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj, 455*1db9f3b2SDimitry Andric getUnitForOffset, CU->getFormParams(), getEndianness()); 456*1db9f3b2SDimitry Andric } 457*1db9f3b2SDimitry Andric } 458*1db9f3b2SDimitry Andric 459*1db9f3b2SDimitry Andric if (Unit) { 460*1db9f3b2SDimitry Andric ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)}); 461*1db9f3b2SDimitry Andric // Preload line table, as it can't be loaded asynchronously. 462*1db9f3b2SDimitry Andric ModulesCompileUnits.back().Unit->loadLineTable(); 463*1db9f3b2SDimitry Andric } 464*1db9f3b2SDimitry Andric 465*1db9f3b2SDimitry Andric return Error::success(); 466*1db9f3b2SDimitry Andric } 467*1db9f3b2SDimitry Andric 468*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) { 469*1db9f3b2SDimitry Andric InterCUProcessingStarted = false; 470*1db9f3b2SDimitry Andric if (!InputDWARFFile.Dwarf) 471*1db9f3b2SDimitry Andric return Error::success(); 472*1db9f3b2SDimitry Andric 473*1db9f3b2SDimitry Andric // Preload macro tables, as they can't be loaded asynchronously. 474*1db9f3b2SDimitry Andric InputDWARFFile.Dwarf->getDebugMacinfo(); 475*1db9f3b2SDimitry Andric InputDWARFFile.Dwarf->getDebugMacro(); 476*1db9f3b2SDimitry Andric 477*1db9f3b2SDimitry Andric // Link modules compile units first. 478*1db9f3b2SDimitry Andric parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) { 479*1db9f3b2SDimitry Andric linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit); 480*1db9f3b2SDimitry Andric }); 481*1db9f3b2SDimitry Andric 482*1db9f3b2SDimitry Andric // Check for live relocations. If there is no any live relocation then we 483*1db9f3b2SDimitry Andric // can skip entire object file. 484*1db9f3b2SDimitry Andric if (!GlobalData.getOptions().UpdateIndexTablesOnly && 485*1db9f3b2SDimitry Andric !InputDWARFFile.Addresses->hasValidRelocs()) { 486*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Verbose) 487*1db9f3b2SDimitry Andric outs() << "No valid relocations found. Skipping.\n"; 488*1db9f3b2SDimitry Andric return Error::success(); 489*1db9f3b2SDimitry Andric } 490*1db9f3b2SDimitry Andric 491*1db9f3b2SDimitry Andric OriginalDebugInfoSize = getInputDebugInfoSize(); 492*1db9f3b2SDimitry Andric 493*1db9f3b2SDimitry Andric // Create CompileUnit structures to keep information about source 494*1db9f3b2SDimitry Andric // DWARFUnit`s, load line tables. 495*1db9f3b2SDimitry Andric for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) { 496*1db9f3b2SDimitry Andric // Load only unit DIE at this stage. 497*1db9f3b2SDimitry Andric auto CUDie = OrigCU->getUnitDIE(); 498*1db9f3b2SDimitry Andric std::string PCMFile = 499*1db9f3b2SDimitry Andric getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap); 500*1db9f3b2SDimitry Andric 501*1db9f3b2SDimitry Andric // The !isClangModuleRef condition effectively skips over fully resolved 502*1db9f3b2SDimitry Andric // skeleton units. 503*1db9f3b2SDimitry Andric if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly || 504*1db9f3b2SDimitry Andric !isClangModuleRef(CUDie, PCMFile, 0, true).first) { 505*1db9f3b2SDimitry Andric CompileUnits.emplace_back(std::make_unique<CompileUnit>( 506*1db9f3b2SDimitry Andric GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile, 507*1db9f3b2SDimitry Andric getUnitForOffset, OrigCU->getFormParams(), getEndianness())); 508*1db9f3b2SDimitry Andric 509*1db9f3b2SDimitry Andric // Preload line table, as it can't be loaded asynchronously. 510*1db9f3b2SDimitry Andric CompileUnits.back()->loadLineTable(); 511*1db9f3b2SDimitry Andric } 512*1db9f3b2SDimitry Andric }; 513*1db9f3b2SDimitry Andric 514*1db9f3b2SDimitry Andric HasNewInterconnectedCUs = false; 515*1db9f3b2SDimitry Andric 516*1db9f3b2SDimitry Andric // Link self-sufficient compile units and discover inter-connected compile 517*1db9f3b2SDimitry Andric // units. 518*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 519*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit); 520*1db9f3b2SDimitry Andric }); 521*1db9f3b2SDimitry Andric 522*1db9f3b2SDimitry Andric // Link all inter-connected units. 523*1db9f3b2SDimitry Andric if (HasNewInterconnectedCUs) { 524*1db9f3b2SDimitry Andric InterCUProcessingStarted = true; 525*1db9f3b2SDimitry Andric 526*1db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 527*1db9f3b2SDimitry Andric HasNewInterconnectedCUs = false; 528*1db9f3b2SDimitry Andric 529*1db9f3b2SDimitry Andric // Load inter-connected units. 530*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 531*1db9f3b2SDimitry Andric if (CU->isInterconnectedCU()) { 532*1db9f3b2SDimitry Andric CU->maybeResetToLoadedStage(); 533*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 534*1db9f3b2SDimitry Andric CompileUnit::Stage::Loaded); 535*1db9f3b2SDimitry Andric } 536*1db9f3b2SDimitry Andric }); 537*1db9f3b2SDimitry Andric 538*1db9f3b2SDimitry Andric // Do liveness analysis for inter-connected units. 539*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 540*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 541*1db9f3b2SDimitry Andric CompileUnit::Stage::LivenessAnalysisDone); 542*1db9f3b2SDimitry Andric }); 543*1db9f3b2SDimitry Andric 544*1db9f3b2SDimitry Andric return HasNewInterconnectedCUs.load(); 545*1db9f3b2SDimitry Andric })) 546*1db9f3b2SDimitry Andric return Err; 547*1db9f3b2SDimitry Andric 548*1db9f3b2SDimitry Andric // Update dependencies. 549*1db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 550*1db9f3b2SDimitry Andric HasNewGlobalDependency = false; 551*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 552*1db9f3b2SDimitry Andric linkSingleCompileUnit( 553*1db9f3b2SDimitry Andric *CU, ArtificialTypeUnit, 554*1db9f3b2SDimitry Andric CompileUnit::Stage::UpdateDependenciesCompleteness); 555*1db9f3b2SDimitry Andric }); 556*1db9f3b2SDimitry Andric return HasNewGlobalDependency.load(); 557*1db9f3b2SDimitry Andric })) 558*1db9f3b2SDimitry Andric return Err; 559*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 560*1db9f3b2SDimitry Andric if (CU->isInterconnectedCU() && 561*1db9f3b2SDimitry Andric CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone) 562*1db9f3b2SDimitry Andric CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness); 563*1db9f3b2SDimitry Andric }); 564*1db9f3b2SDimitry Andric 565*1db9f3b2SDimitry Andric // Assign type names. 566*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 567*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 568*1db9f3b2SDimitry Andric CompileUnit::Stage::TypeNamesAssigned); 569*1db9f3b2SDimitry Andric }); 570*1db9f3b2SDimitry Andric 571*1db9f3b2SDimitry Andric // Clone inter-connected units. 572*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 573*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 574*1db9f3b2SDimitry Andric CompileUnit::Stage::Cloned); 575*1db9f3b2SDimitry Andric }); 576*1db9f3b2SDimitry Andric 577*1db9f3b2SDimitry Andric // Update patches for inter-connected units. 578*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 579*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 580*1db9f3b2SDimitry Andric CompileUnit::Stage::PatchesUpdated); 581*1db9f3b2SDimitry Andric }); 582*1db9f3b2SDimitry Andric 583*1db9f3b2SDimitry Andric // Release data. 584*1db9f3b2SDimitry Andric parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) { 585*1db9f3b2SDimitry Andric linkSingleCompileUnit(*CU, ArtificialTypeUnit, 586*1db9f3b2SDimitry Andric CompileUnit::Stage::Cleaned); 587*1db9f3b2SDimitry Andric }); 588*1db9f3b2SDimitry Andric } 589*1db9f3b2SDimitry Andric 590*1db9f3b2SDimitry Andric if (GlobalData.getOptions().UpdateIndexTablesOnly) { 591*1db9f3b2SDimitry Andric // Emit Invariant sections. 592*1db9f3b2SDimitry Andric 593*1db9f3b2SDimitry Andric if (Error Err = emitInvariantSections()) 594*1db9f3b2SDimitry Andric return Err; 595*1db9f3b2SDimitry Andric } else if (!CompileUnits.empty()) { 596*1db9f3b2SDimitry Andric // Emit .debug_frame section. 597*1db9f3b2SDimitry Andric 598*1db9f3b2SDimitry Andric Error ResultErr = Error::success(); 599*1db9f3b2SDimitry Andric llvm::parallel::TaskGroup TGroup; 600*1db9f3b2SDimitry Andric // We use task group here as PerThreadBumpPtrAllocator should be called from 601*1db9f3b2SDimitry Andric // the threads created by ThreadPoolExecutor. 602*1db9f3b2SDimitry Andric TGroup.spawn([&]() { 603*1db9f3b2SDimitry Andric if (Error Err = cloneAndEmitDebugFrame()) 604*1db9f3b2SDimitry Andric ResultErr = std::move(Err); 605*1db9f3b2SDimitry Andric }); 606*1db9f3b2SDimitry Andric return ResultErr; 607*1db9f3b2SDimitry Andric } 608*1db9f3b2SDimitry Andric 609*1db9f3b2SDimitry Andric return Error::success(); 610*1db9f3b2SDimitry Andric } 611*1db9f3b2SDimitry Andric 612*1db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit( 613*1db9f3b2SDimitry Andric CompileUnit &CU, TypeUnit *ArtificialTypeUnit, 614*1db9f3b2SDimitry Andric enum CompileUnit::Stage DoUntilStage) { 615*1db9f3b2SDimitry Andric if (InterCUProcessingStarted != CU.isInterconnectedCU()) 616*1db9f3b2SDimitry Andric return; 617*1db9f3b2SDimitry Andric 618*1db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 619*1db9f3b2SDimitry Andric if (CU.getStage() >= DoUntilStage) 620*1db9f3b2SDimitry Andric return false; 621*1db9f3b2SDimitry Andric 622*1db9f3b2SDimitry Andric switch (CU.getStage()) { 623*1db9f3b2SDimitry Andric case CompileUnit::Stage::CreatedNotLoaded: { 624*1db9f3b2SDimitry Andric // Load input compilation unit DIEs. 625*1db9f3b2SDimitry Andric // Analyze properties of DIEs. 626*1db9f3b2SDimitry Andric if (!CU.loadInputDIEs()) { 627*1db9f3b2SDimitry Andric // We do not need to do liveness analysis for invalid compilation 628*1db9f3b2SDimitry Andric // unit. 629*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Skipped); 630*1db9f3b2SDimitry Andric } else { 631*1db9f3b2SDimitry Andric CU.analyzeDWARFStructure(); 632*1db9f3b2SDimitry Andric 633*1db9f3b2SDimitry Andric // The registerModuleReference() condition effectively skips 634*1db9f3b2SDimitry Andric // over fully resolved skeleton units. This second pass of 635*1db9f3b2SDimitry Andric // registerModuleReferences doesn't do any new work, but it 636*1db9f3b2SDimitry Andric // will collect top-level errors, which are suppressed. Module 637*1db9f3b2SDimitry Andric // warnings were already displayed in the first iteration. 638*1db9f3b2SDimitry Andric if (registerModuleReference( 639*1db9f3b2SDimitry Andric CU.getOrigUnit().getUnitDIE(), nullptr, 640*1db9f3b2SDimitry Andric [](const DWARFUnit &) {}, 0)) 641*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::PatchesUpdated); 642*1db9f3b2SDimitry Andric else 643*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Loaded); 644*1db9f3b2SDimitry Andric } 645*1db9f3b2SDimitry Andric } break; 646*1db9f3b2SDimitry Andric 647*1db9f3b2SDimitry Andric case CompileUnit::Stage::Loaded: { 648*1db9f3b2SDimitry Andric // Mark all the DIEs that need to be present in the generated output. 649*1db9f3b2SDimitry Andric // If ODR requested, build type names. 650*1db9f3b2SDimitry Andric if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted, 651*1db9f3b2SDimitry Andric HasNewInterconnectedCUs)) { 652*1db9f3b2SDimitry Andric assert(HasNewInterconnectedCUs && 653*1db9f3b2SDimitry Andric "Flag indicating new inter-connections is not set"); 654*1db9f3b2SDimitry Andric return false; 655*1db9f3b2SDimitry Andric } 656*1db9f3b2SDimitry Andric 657*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::LivenessAnalysisDone); 658*1db9f3b2SDimitry Andric } break; 659*1db9f3b2SDimitry Andric 660*1db9f3b2SDimitry Andric case CompileUnit::Stage::LivenessAnalysisDone: { 661*1db9f3b2SDimitry Andric if (InterCUProcessingStarted) { 662*1db9f3b2SDimitry Andric if (CU.updateDependenciesCompleteness()) 663*1db9f3b2SDimitry Andric HasNewGlobalDependency = true; 664*1db9f3b2SDimitry Andric return false; 665*1db9f3b2SDimitry Andric } else { 666*1db9f3b2SDimitry Andric if (Error Err = finiteLoop([&]() -> Expected<bool> { 667*1db9f3b2SDimitry Andric return CU.updateDependenciesCompleteness(); 668*1db9f3b2SDimitry Andric })) 669*1db9f3b2SDimitry Andric return std::move(Err); 670*1db9f3b2SDimitry Andric 671*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness); 672*1db9f3b2SDimitry Andric } 673*1db9f3b2SDimitry Andric } break; 674*1db9f3b2SDimitry Andric 675*1db9f3b2SDimitry Andric case CompileUnit::Stage::UpdateDependenciesCompleteness: 676*1db9f3b2SDimitry Andric #ifndef NDEBUG 677*1db9f3b2SDimitry Andric CU.verifyDependencies(); 678*1db9f3b2SDimitry Andric #endif 679*1db9f3b2SDimitry Andric 680*1db9f3b2SDimitry Andric if (ArtificialTypeUnit) { 681*1db9f3b2SDimitry Andric if (Error Err = 682*1db9f3b2SDimitry Andric CU.assignTypeNames(ArtificialTypeUnit->getTypePool())) 683*1db9f3b2SDimitry Andric return std::move(Err); 684*1db9f3b2SDimitry Andric } 685*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::TypeNamesAssigned); 686*1db9f3b2SDimitry Andric break; 687*1db9f3b2SDimitry Andric 688*1db9f3b2SDimitry Andric case CompileUnit::Stage::TypeNamesAssigned: 689*1db9f3b2SDimitry Andric // Clone input compile unit. 690*1db9f3b2SDimitry Andric if (CU.isClangModule() || 691*1db9f3b2SDimitry Andric GlobalData.getOptions().UpdateIndexTablesOnly || 692*1db9f3b2SDimitry Andric CU.getContaingFile().Addresses->hasValidRelocs()) { 693*1db9f3b2SDimitry Andric if (Error Err = CU.cloneAndEmit(TargetTriple, ArtificialTypeUnit)) 694*1db9f3b2SDimitry Andric return std::move(Err); 695*1db9f3b2SDimitry Andric } 696*1db9f3b2SDimitry Andric 697*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Cloned); 698*1db9f3b2SDimitry Andric break; 699*1db9f3b2SDimitry Andric 700*1db9f3b2SDimitry Andric case CompileUnit::Stage::Cloned: 701*1db9f3b2SDimitry Andric // Update DIEs referencies. 702*1db9f3b2SDimitry Andric CU.updateDieRefPatchesWithClonedOffsets(); 703*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::PatchesUpdated); 704*1db9f3b2SDimitry Andric break; 705*1db9f3b2SDimitry Andric 706*1db9f3b2SDimitry Andric case CompileUnit::Stage::PatchesUpdated: 707*1db9f3b2SDimitry Andric // Cleanup resources. 708*1db9f3b2SDimitry Andric CU.cleanupDataAfterClonning(); 709*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Cleaned); 710*1db9f3b2SDimitry Andric break; 711*1db9f3b2SDimitry Andric 712*1db9f3b2SDimitry Andric case CompileUnit::Stage::Cleaned: 713*1db9f3b2SDimitry Andric assert(false); 714*1db9f3b2SDimitry Andric break; 715*1db9f3b2SDimitry Andric 716*1db9f3b2SDimitry Andric case CompileUnit::Stage::Skipped: 717*1db9f3b2SDimitry Andric // Nothing to do. 718*1db9f3b2SDimitry Andric break; 719*1db9f3b2SDimitry Andric } 720*1db9f3b2SDimitry Andric 721*1db9f3b2SDimitry Andric return true; 722*1db9f3b2SDimitry Andric })) { 723*1db9f3b2SDimitry Andric CU.error(std::move(Err)); 724*1db9f3b2SDimitry Andric CU.cleanupDataAfterClonning(); 725*1db9f3b2SDimitry Andric CU.setStage(CompileUnit::Stage::Skipped); 726*1db9f3b2SDimitry Andric } 727*1db9f3b2SDimitry Andric } 728*1db9f3b2SDimitry Andric 729*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::emitInvariantSections() { 730*1db9f3b2SDimitry Andric if (GlobalData.getOptions().NoOutput) 731*1db9f3b2SDimitry Andric return Error::success(); 732*1db9f3b2SDimitry Andric 733*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS 734*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data; 735*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS 736*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data; 737*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS 738*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data; 739*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS 740*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data; 741*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS 742*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection(); 743*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS 744*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data; 745*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS 746*1db9f3b2SDimitry Andric << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data; 747*1db9f3b2SDimitry Andric 748*1db9f3b2SDimitry Andric return Error::success(); 749*1db9f3b2SDimitry Andric } 750*1db9f3b2SDimitry Andric 751*1db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() { 752*1db9f3b2SDimitry Andric if (GlobalData.getOptions().NoOutput) 753*1db9f3b2SDimitry Andric return Error::success(); 754*1db9f3b2SDimitry Andric 755*1db9f3b2SDimitry Andric if (InputDWARFFile.Dwarf.get() == nullptr) 756*1db9f3b2SDimitry Andric return Error::success(); 757*1db9f3b2SDimitry Andric 758*1db9f3b2SDimitry Andric const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj(); 759*1db9f3b2SDimitry Andric 760*1db9f3b2SDimitry Andric StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data; 761*1db9f3b2SDimitry Andric if (OrigFrameData.empty()) 762*1db9f3b2SDimitry Andric return Error::success(); 763*1db9f3b2SDimitry Andric 764*1db9f3b2SDimitry Andric RangesTy AllUnitsRanges; 765*1db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) { 766*1db9f3b2SDimitry Andric for (auto CurRange : Unit->getFunctionRanges()) 767*1db9f3b2SDimitry Andric AllUnitsRanges.insert(CurRange.Range, CurRange.Value); 768*1db9f3b2SDimitry Andric } 769*1db9f3b2SDimitry Andric 770*1db9f3b2SDimitry Andric unsigned SrcAddrSize = InputDWARFObj.getAddressSize(); 771*1db9f3b2SDimitry Andric 772*1db9f3b2SDimitry Andric SectionDescriptor &OutSection = 773*1db9f3b2SDimitry Andric getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame); 774*1db9f3b2SDimitry Andric 775*1db9f3b2SDimitry Andric DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0); 776*1db9f3b2SDimitry Andric uint64_t InputOffset = 0; 777*1db9f3b2SDimitry Andric 778*1db9f3b2SDimitry Andric // Store the data of the CIEs defined in this object, keyed by their 779*1db9f3b2SDimitry Andric // offsets. 780*1db9f3b2SDimitry Andric DenseMap<uint64_t, StringRef> LocalCIES; 781*1db9f3b2SDimitry Andric 782*1db9f3b2SDimitry Andric /// The CIEs that have been emitted in the output section. The actual CIE 783*1db9f3b2SDimitry Andric /// data serves a the key to this StringMap. 784*1db9f3b2SDimitry Andric StringMap<uint32_t> EmittedCIEs; 785*1db9f3b2SDimitry Andric 786*1db9f3b2SDimitry Andric while (Data.isValidOffset(InputOffset)) { 787*1db9f3b2SDimitry Andric uint64_t EntryOffset = InputOffset; 788*1db9f3b2SDimitry Andric uint32_t InitialLength = Data.getU32(&InputOffset); 789*1db9f3b2SDimitry Andric if (InitialLength == 0xFFFFFFFF) 790*1db9f3b2SDimitry Andric return createFileError(InputDWARFObj.getFileName(), 791*1db9f3b2SDimitry Andric createStringError(std::errc::invalid_argument, 792*1db9f3b2SDimitry Andric "Dwarf64 bits no supported")); 793*1db9f3b2SDimitry Andric 794*1db9f3b2SDimitry Andric uint32_t CIEId = Data.getU32(&InputOffset); 795*1db9f3b2SDimitry Andric if (CIEId == 0xFFFFFFFF) { 796*1db9f3b2SDimitry Andric // This is a CIE, store it. 797*1db9f3b2SDimitry Andric StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4); 798*1db9f3b2SDimitry Andric LocalCIES[EntryOffset] = CIEData; 799*1db9f3b2SDimitry Andric // The -4 is to account for the CIEId we just read. 800*1db9f3b2SDimitry Andric InputOffset += InitialLength - 4; 801*1db9f3b2SDimitry Andric continue; 802*1db9f3b2SDimitry Andric } 803*1db9f3b2SDimitry Andric 804*1db9f3b2SDimitry Andric uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize); 805*1db9f3b2SDimitry Andric 806*1db9f3b2SDimitry Andric // Some compilers seem to emit frame info that doesn't start at 807*1db9f3b2SDimitry Andric // the function entry point, thus we can't just lookup the address 808*1db9f3b2SDimitry Andric // in the debug map. Use the AddressInfo's range map to see if the FDE 809*1db9f3b2SDimitry Andric // describes something that we can relocate. 810*1db9f3b2SDimitry Andric std::optional<AddressRangeValuePair> Range = 811*1db9f3b2SDimitry Andric AllUnitsRanges.getRangeThatContains(Loc); 812*1db9f3b2SDimitry Andric if (!Range) { 813*1db9f3b2SDimitry Andric // The +4 is to account for the size of the InitialLength field itself. 814*1db9f3b2SDimitry Andric InputOffset = EntryOffset + InitialLength + 4; 815*1db9f3b2SDimitry Andric continue; 816*1db9f3b2SDimitry Andric } 817*1db9f3b2SDimitry Andric 818*1db9f3b2SDimitry Andric // This is an FDE, and we have a mapping. 819*1db9f3b2SDimitry Andric // Have we already emitted a corresponding CIE? 820*1db9f3b2SDimitry Andric StringRef CIEData = LocalCIES[CIEId]; 821*1db9f3b2SDimitry Andric if (CIEData.empty()) 822*1db9f3b2SDimitry Andric return createFileError( 823*1db9f3b2SDimitry Andric InputDWARFObj.getFileName(), 824*1db9f3b2SDimitry Andric createStringError(std::errc::invalid_argument, 825*1db9f3b2SDimitry Andric "Inconsistent debug_frame content. Dropping.")); 826*1db9f3b2SDimitry Andric 827*1db9f3b2SDimitry Andric uint64_t OffsetToCIERecord = OutSection.OS.tell(); 828*1db9f3b2SDimitry Andric 829*1db9f3b2SDimitry Andric // Look if we already emitted a CIE that corresponds to the 830*1db9f3b2SDimitry Andric // referenced one (the CIE data is the key of that lookup). 831*1db9f3b2SDimitry Andric auto IteratorInserted = 832*1db9f3b2SDimitry Andric EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord)); 833*1db9f3b2SDimitry Andric OffsetToCIERecord = IteratorInserted.first->getValue(); 834*1db9f3b2SDimitry Andric 835*1db9f3b2SDimitry Andric // Emit CIE for this ID if it is not emitted yet. 836*1db9f3b2SDimitry Andric if (IteratorInserted.second) 837*1db9f3b2SDimitry Andric OutSection.OS << CIEData; 838*1db9f3b2SDimitry Andric 839*1db9f3b2SDimitry Andric // Remember offset to the FDE record, so that we might update 840*1db9f3b2SDimitry Andric // field referencing CIE record(containing OffsetToCIERecord), 841*1db9f3b2SDimitry Andric // when final offsets are known. OffsetToCIERecord(which is written later) 842*1db9f3b2SDimitry Andric // is local to the current .debug_frame section, it should be updated 843*1db9f3b2SDimitry Andric // with final offset of the .debug_frame section. 844*1db9f3b2SDimitry Andric OutSection.notePatch( 845*1db9f3b2SDimitry Andric DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true}); 846*1db9f3b2SDimitry Andric 847*1db9f3b2SDimitry Andric // Emit the FDE with updated address and CIE pointer. 848*1db9f3b2SDimitry Andric // (4 + AddrSize) is the size of the CIEId + initial_location 849*1db9f3b2SDimitry Andric // fields that will get reconstructed by emitFDE(). 850*1db9f3b2SDimitry Andric unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize); 851*1db9f3b2SDimitry Andric emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value, 852*1db9f3b2SDimitry Andric OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection); 853*1db9f3b2SDimitry Andric InputOffset += FDERemainingBytes; 854*1db9f3b2SDimitry Andric } 855*1db9f3b2SDimitry Andric 856*1db9f3b2SDimitry Andric return Error::success(); 857*1db9f3b2SDimitry Andric } 858*1db9f3b2SDimitry Andric 859*1db9f3b2SDimitry Andric /// Emit a FDE into the debug_frame section. \p FDEBytes 860*1db9f3b2SDimitry Andric /// contains the FDE data without the length, CIE offset and address 861*1db9f3b2SDimitry Andric /// which will be replaced with the parameter values. 862*1db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset, 863*1db9f3b2SDimitry Andric uint32_t AddrSize, uint64_t Address, 864*1db9f3b2SDimitry Andric StringRef FDEBytes, 865*1db9f3b2SDimitry Andric SectionDescriptor &Section) { 866*1db9f3b2SDimitry Andric Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4); 867*1db9f3b2SDimitry Andric Section.emitIntVal(CIEOffset, 4); 868*1db9f3b2SDimitry Andric Section.emitIntVal(Address, AddrSize); 869*1db9f3b2SDimitry Andric Section.OS.write(FDEBytes.data(), FDEBytes.size()); 870*1db9f3b2SDimitry Andric } 871*1db9f3b2SDimitry Andric 872*1db9f3b2SDimitry Andric void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() { 873*1db9f3b2SDimitry Andric if (GlobalData.getOptions().NoOutput) 874*1db9f3b2SDimitry Andric return; 875*1db9f3b2SDimitry Andric 876*1db9f3b2SDimitry Andric // Go through all object files, all compile units and assign 877*1db9f3b2SDimitry Andric // offsets to them. 878*1db9f3b2SDimitry Andric assignOffsets(); 879*1db9f3b2SDimitry Andric 880*1db9f3b2SDimitry Andric // Patch size/offsets fields according to the assigned CU offsets. 881*1db9f3b2SDimitry Andric patchOffsetsAndSizes(); 882*1db9f3b2SDimitry Andric 883*1db9f3b2SDimitry Andric // Emit common sections and write debug tables from all object files/compile 884*1db9f3b2SDimitry Andric // units into the resulting file. 885*1db9f3b2SDimitry Andric emitCommonSectionsAndWriteCompileUnitsToTheOutput(); 886*1db9f3b2SDimitry Andric 887*1db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) 888*1db9f3b2SDimitry Andric ArtificialTypeUnit.reset(); 889*1db9f3b2SDimitry Andric 890*1db9f3b2SDimitry Andric // Write common debug sections into the resulting file. 891*1db9f3b2SDimitry Andric writeCommonSectionsToTheOutput(); 892*1db9f3b2SDimitry Andric 893*1db9f3b2SDimitry Andric // Cleanup data. 894*1db9f3b2SDimitry Andric cleanupDataAfterDWARFOutputIsWritten(); 895*1db9f3b2SDimitry Andric 896*1db9f3b2SDimitry Andric if (GlobalData.getOptions().Statistics) 897*1db9f3b2SDimitry Andric printStatistic(); 898*1db9f3b2SDimitry Andric } 899*1db9f3b2SDimitry Andric 900*1db9f3b2SDimitry Andric void DWARFLinkerImpl::printStatistic() { 901*1db9f3b2SDimitry Andric 902*1db9f3b2SDimitry Andric // For each object file map how many bytes were emitted. 903*1db9f3b2SDimitry Andric StringMap<DebugInfoSize> SizeByObject; 904*1db9f3b2SDimitry Andric 905*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) { 906*1db9f3b2SDimitry Andric uint64_t AllDebugInfoSectionsSize = 0; 907*1db9f3b2SDimitry Andric 908*1db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 909*1db9f3b2SDimitry Andric if (std::optional<SectionDescriptor *> DebugInfo = 910*1db9f3b2SDimitry Andric CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) 911*1db9f3b2SDimitry Andric AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size(); 912*1db9f3b2SDimitry Andric 913*1db9f3b2SDimitry Andric SizeByObject[Context->InputDWARFFile.FileName].Input = 914*1db9f3b2SDimitry Andric Context->OriginalDebugInfoSize; 915*1db9f3b2SDimitry Andric SizeByObject[Context->InputDWARFFile.FileName].Output = 916*1db9f3b2SDimitry Andric AllDebugInfoSectionsSize; 917*1db9f3b2SDimitry Andric } 918*1db9f3b2SDimitry Andric 919*1db9f3b2SDimitry Andric // Create a vector sorted in descending order by output size. 920*1db9f3b2SDimitry Andric std::vector<std::pair<StringRef, DebugInfoSize>> Sorted; 921*1db9f3b2SDimitry Andric for (auto &E : SizeByObject) 922*1db9f3b2SDimitry Andric Sorted.emplace_back(E.first(), E.second); 923*1db9f3b2SDimitry Andric llvm::sort(Sorted, [](auto &LHS, auto &RHS) { 924*1db9f3b2SDimitry Andric return LHS.second.Output > RHS.second.Output; 925*1db9f3b2SDimitry Andric }); 926*1db9f3b2SDimitry Andric 927*1db9f3b2SDimitry Andric auto ComputePercentange = [](int64_t Input, int64_t Output) -> float { 928*1db9f3b2SDimitry Andric const float Difference = Output - Input; 929*1db9f3b2SDimitry Andric const float Sum = Input + Output; 930*1db9f3b2SDimitry Andric if (Sum == 0) 931*1db9f3b2SDimitry Andric return 0; 932*1db9f3b2SDimitry Andric return (Difference / (Sum / 2)); 933*1db9f3b2SDimitry Andric }; 934*1db9f3b2SDimitry Andric 935*1db9f3b2SDimitry Andric int64_t InputTotal = 0; 936*1db9f3b2SDimitry Andric int64_t OutputTotal = 0; 937*1db9f3b2SDimitry Andric const char *FormatStr = "{0,-45} {1,10}b {2,10}b {3,8:P}\n"; 938*1db9f3b2SDimitry Andric 939*1db9f3b2SDimitry Andric // Print header. 940*1db9f3b2SDimitry Andric outs() << ".debug_info section size (in bytes)\n"; 941*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 942*1db9f3b2SDimitry Andric "---------------\n"; 943*1db9f3b2SDimitry Andric outs() << "Filename Object " 944*1db9f3b2SDimitry Andric " dSYM Change\n"; 945*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 946*1db9f3b2SDimitry Andric "---------------\n"; 947*1db9f3b2SDimitry Andric 948*1db9f3b2SDimitry Andric // Print body. 949*1db9f3b2SDimitry Andric for (auto &E : Sorted) { 950*1db9f3b2SDimitry Andric InputTotal += E.second.Input; 951*1db9f3b2SDimitry Andric OutputTotal += E.second.Output; 952*1db9f3b2SDimitry Andric llvm::outs() << formatv( 953*1db9f3b2SDimitry Andric FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input, 954*1db9f3b2SDimitry Andric E.second.Output, ComputePercentange(E.second.Input, E.second.Output)); 955*1db9f3b2SDimitry Andric } 956*1db9f3b2SDimitry Andric // Print total and footer. 957*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 958*1db9f3b2SDimitry Andric "---------------\n"; 959*1db9f3b2SDimitry Andric llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal, 960*1db9f3b2SDimitry Andric ComputePercentange(InputTotal, OutputTotal)); 961*1db9f3b2SDimitry Andric outs() << "----------------------------------------------------------------" 962*1db9f3b2SDimitry Andric "---------------\n\n"; 963*1db9f3b2SDimitry Andric } 964*1db9f3b2SDimitry Andric 965*1db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsets() { 966*1db9f3b2SDimitry Andric llvm::parallel::TaskGroup TGroup; 967*1db9f3b2SDimitry Andric TGroup.spawn([&]() { assignOffsetsToStrings(); }); 968*1db9f3b2SDimitry Andric TGroup.spawn([&]() { assignOffsetsToSections(); }); 969*1db9f3b2SDimitry Andric } 970*1db9f3b2SDimitry Andric 971*1db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsetsToStrings() { 972*1db9f3b2SDimitry Andric size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry. 973*1db9f3b2SDimitry Andric uint64_t CurDebugStrOffset = 974*1db9f3b2SDimitry Andric 1; // start from 1 to take into account zero entry. 975*1db9f3b2SDimitry Andric size_t CurDebugLineStrIndex = 0; 976*1db9f3b2SDimitry Andric uint64_t CurDebugLineStrOffset = 0; 977*1db9f3b2SDimitry Andric 978*1db9f3b2SDimitry Andric // Enumerates all strings, add them into the DwarfStringPoolEntry map, 979*1db9f3b2SDimitry Andric // assign offset and index to the string if it is not indexed yet. 980*1db9f3b2SDimitry Andric forEachOutputString([&](StringDestinationKind Kind, 981*1db9f3b2SDimitry Andric const StringEntry *String) { 982*1db9f3b2SDimitry Andric switch (Kind) { 983*1db9f3b2SDimitry Andric case StringDestinationKind::DebugStr: { 984*1db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String); 985*1db9f3b2SDimitry Andric assert(Entry != nullptr); 986*1db9f3b2SDimitry Andric 987*1db9f3b2SDimitry Andric if (!Entry->isIndexed()) { 988*1db9f3b2SDimitry Andric Entry->Offset = CurDebugStrOffset; 989*1db9f3b2SDimitry Andric CurDebugStrOffset += Entry->String.size() + 1; 990*1db9f3b2SDimitry Andric Entry->Index = CurDebugStrIndex++; 991*1db9f3b2SDimitry Andric } 992*1db9f3b2SDimitry Andric } break; 993*1db9f3b2SDimitry Andric case StringDestinationKind::DebugLineStr: { 994*1db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *Entry = 995*1db9f3b2SDimitry Andric DebugLineStrStrings.add(String); 996*1db9f3b2SDimitry Andric assert(Entry != nullptr); 997*1db9f3b2SDimitry Andric 998*1db9f3b2SDimitry Andric if (!Entry->isIndexed()) { 999*1db9f3b2SDimitry Andric Entry->Offset = CurDebugLineStrOffset; 1000*1db9f3b2SDimitry Andric CurDebugLineStrOffset += Entry->String.size() + 1; 1001*1db9f3b2SDimitry Andric Entry->Index = CurDebugLineStrIndex++; 1002*1db9f3b2SDimitry Andric } 1003*1db9f3b2SDimitry Andric } break; 1004*1db9f3b2SDimitry Andric } 1005*1db9f3b2SDimitry Andric }); 1006*1db9f3b2SDimitry Andric } 1007*1db9f3b2SDimitry Andric 1008*1db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsetsToSections() { 1009*1db9f3b2SDimitry Andric std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0}; 1010*1db9f3b2SDimitry Andric 1011*1db9f3b2SDimitry Andric forEachObjectSectionsSet([&](OutputSections &UnitSections) { 1012*1db9f3b2SDimitry Andric UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator); 1013*1db9f3b2SDimitry Andric }); 1014*1db9f3b2SDimitry Andric } 1015*1db9f3b2SDimitry Andric 1016*1db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachOutputString( 1017*1db9f3b2SDimitry Andric function_ref<void(StringDestinationKind Kind, const StringEntry *String)> 1018*1db9f3b2SDimitry Andric StringHandler) { 1019*1db9f3b2SDimitry Andric // To save space we do not create any separate string table. 1020*1db9f3b2SDimitry Andric // We use already allocated string patches and accelerator entries: 1021*1db9f3b2SDimitry Andric // enumerate them in natural order and assign offsets. 1022*1db9f3b2SDimitry Andric // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str 1023*1db9f3b2SDimitry Andric // sections in the same order as they were assigned offsets. 1024*1db9f3b2SDimitry Andric forEachCompileUnit([&](CompileUnit *CU) { 1025*1db9f3b2SDimitry Andric CU->forEach([&](SectionDescriptor &OutSection) { 1026*1db9f3b2SDimitry Andric OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) { 1027*1db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 1028*1db9f3b2SDimitry Andric }); 1029*1db9f3b2SDimitry Andric 1030*1db9f3b2SDimitry Andric OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) { 1031*1db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugLineStr, Patch.String); 1032*1db9f3b2SDimitry Andric }); 1033*1db9f3b2SDimitry Andric }); 1034*1db9f3b2SDimitry Andric 1035*1db9f3b2SDimitry Andric CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) { 1036*1db9f3b2SDimitry Andric StringHandler(DebugStr, Info.String); 1037*1db9f3b2SDimitry Andric }); 1038*1db9f3b2SDimitry Andric }); 1039*1db9f3b2SDimitry Andric 1040*1db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) { 1041*1db9f3b2SDimitry Andric ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) { 1042*1db9f3b2SDimitry Andric OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) { 1043*1db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 1044*1db9f3b2SDimitry Andric }); 1045*1db9f3b2SDimitry Andric 1046*1db9f3b2SDimitry Andric OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) { 1047*1db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugLineStr, Patch.String); 1048*1db9f3b2SDimitry Andric }); 1049*1db9f3b2SDimitry Andric 1050*1db9f3b2SDimitry Andric OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) { 1051*1db9f3b2SDimitry Andric if (Patch.Die == nullptr) 1052*1db9f3b2SDimitry Andric return; 1053*1db9f3b2SDimitry Andric 1054*1db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 1055*1db9f3b2SDimitry Andric }); 1056*1db9f3b2SDimitry Andric 1057*1db9f3b2SDimitry Andric OutSection.ListDebugTypeLineStrPatch.forEach( 1058*1db9f3b2SDimitry Andric [&](DebugTypeLineStrPatch &Patch) { 1059*1db9f3b2SDimitry Andric if (Patch.Die == nullptr) 1060*1db9f3b2SDimitry Andric return; 1061*1db9f3b2SDimitry Andric 1062*1db9f3b2SDimitry Andric StringHandler(StringDestinationKind::DebugStr, Patch.String); 1063*1db9f3b2SDimitry Andric }); 1064*1db9f3b2SDimitry Andric }); 1065*1db9f3b2SDimitry Andric } 1066*1db9f3b2SDimitry Andric } 1067*1db9f3b2SDimitry Andric 1068*1db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachObjectSectionsSet( 1069*1db9f3b2SDimitry Andric function_ref<void(OutputSections &)> SectionsSetHandler) { 1070*1db9f3b2SDimitry Andric // Handle artificial type unit first. 1071*1db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) 1072*1db9f3b2SDimitry Andric SectionsSetHandler(*ArtificialTypeUnit); 1073*1db9f3b2SDimitry Andric 1074*1db9f3b2SDimitry Andric // Then all modules(before regular compilation units). 1075*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1076*1db9f3b2SDimitry Andric for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 1077*1db9f3b2SDimitry Andric if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 1078*1db9f3b2SDimitry Andric SectionsSetHandler(*ModuleUnit.Unit); 1079*1db9f3b2SDimitry Andric 1080*1db9f3b2SDimitry Andric // Finally all compilation units. 1081*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) { 1082*1db9f3b2SDimitry Andric // Handle object file common sections. 1083*1db9f3b2SDimitry Andric SectionsSetHandler(*Context); 1084*1db9f3b2SDimitry Andric 1085*1db9f3b2SDimitry Andric // Handle compilation units. 1086*1db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 1087*1db9f3b2SDimitry Andric if (CU->getStage() != CompileUnit::Stage::Skipped) 1088*1db9f3b2SDimitry Andric SectionsSetHandler(*CU); 1089*1db9f3b2SDimitry Andric } 1090*1db9f3b2SDimitry Andric } 1091*1db9f3b2SDimitry Andric 1092*1db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachCompileAndTypeUnit( 1093*1db9f3b2SDimitry Andric function_ref<void(DwarfUnit *CU)> UnitHandler) { 1094*1db9f3b2SDimitry Andric if (ArtificialTypeUnit.get() != nullptr) 1095*1db9f3b2SDimitry Andric UnitHandler(ArtificialTypeUnit.get()); 1096*1db9f3b2SDimitry Andric 1097*1db9f3b2SDimitry Andric // Enumerate module units. 1098*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1099*1db9f3b2SDimitry Andric for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 1100*1db9f3b2SDimitry Andric if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 1101*1db9f3b2SDimitry Andric UnitHandler(ModuleUnit.Unit.get()); 1102*1db9f3b2SDimitry Andric 1103*1db9f3b2SDimitry Andric // Enumerate compile units. 1104*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1105*1db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 1106*1db9f3b2SDimitry Andric if (CU->getStage() != CompileUnit::Stage::Skipped) 1107*1db9f3b2SDimitry Andric UnitHandler(CU.get()); 1108*1db9f3b2SDimitry Andric } 1109*1db9f3b2SDimitry Andric 1110*1db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachCompileUnit( 1111*1db9f3b2SDimitry Andric function_ref<void(CompileUnit *CU)> UnitHandler) { 1112*1db9f3b2SDimitry Andric // Enumerate module units. 1113*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1114*1db9f3b2SDimitry Andric for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits) 1115*1db9f3b2SDimitry Andric if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped) 1116*1db9f3b2SDimitry Andric UnitHandler(ModuleUnit.Unit.get()); 1117*1db9f3b2SDimitry Andric 1118*1db9f3b2SDimitry Andric // Enumerate compile units. 1119*1db9f3b2SDimitry Andric for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) 1120*1db9f3b2SDimitry Andric for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits) 1121*1db9f3b2SDimitry Andric if (CU->getStage() != CompileUnit::Stage::Skipped) 1122*1db9f3b2SDimitry Andric UnitHandler(CU.get()); 1123*1db9f3b2SDimitry Andric } 1124*1db9f3b2SDimitry Andric 1125*1db9f3b2SDimitry Andric void DWARFLinkerImpl::patchOffsetsAndSizes() { 1126*1db9f3b2SDimitry Andric forEachObjectSectionsSet([&](OutputSections &SectionsSet) { 1127*1db9f3b2SDimitry Andric SectionsSet.forEach([&](SectionDescriptor &OutSection) { 1128*1db9f3b2SDimitry Andric SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings, 1129*1db9f3b2SDimitry Andric ArtificialTypeUnit.get()); 1130*1db9f3b2SDimitry Andric }); 1131*1db9f3b2SDimitry Andric }); 1132*1db9f3b2SDimitry Andric } 1133*1db9f3b2SDimitry Andric 1134*1db9f3b2SDimitry Andric void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() { 1135*1db9f3b2SDimitry Andric llvm::parallel::TaskGroup TG; 1136*1db9f3b2SDimitry Andric 1137*1db9f3b2SDimitry Andric // Create section descriptors ahead if they are not exist at the moment. 1138*1db9f3b2SDimitry Andric // SectionDescriptors container is not thread safe. Thus we should be sure 1139*1db9f3b2SDimitry Andric // that descriptors would not be created in following parallel tasks. 1140*1db9f3b2SDimitry Andric 1141*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr); 1142*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr); 1143*1db9f3b2SDimitry Andric 1144*1db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 1145*1db9f3b2SDimitry Andric AccelTableKind::Apple)) { 1146*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames); 1147*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor( 1148*1db9f3b2SDimitry Andric DebugSectionKind::AppleNamespaces); 1149*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC); 1150*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes); 1151*1db9f3b2SDimitry Andric } 1152*1db9f3b2SDimitry Andric 1153*1db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 1154*1db9f3b2SDimitry Andric AccelTableKind::DebugNames)) 1155*1db9f3b2SDimitry Andric CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames); 1156*1db9f3b2SDimitry Andric 1157*1db9f3b2SDimitry Andric const Triple &TargetTriple = TheDwarfEmitter->getTargetTriple(); 1158*1db9f3b2SDimitry Andric 1159*1db9f3b2SDimitry Andric // Emit .debug_str and .debug_line_str sections. 1160*1db9f3b2SDimitry Andric TG.spawn([&]() { emitStringSections(); }); 1161*1db9f3b2SDimitry Andric 1162*1db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 1163*1db9f3b2SDimitry Andric AccelTableKind::Apple)) { 1164*1db9f3b2SDimitry Andric // Emit apple accelerator sections. 1165*1db9f3b2SDimitry Andric TG.spawn([&]() { emitAppleAcceleratorSections(TargetTriple); }); 1166*1db9f3b2SDimitry Andric } 1167*1db9f3b2SDimitry Andric 1168*1db9f3b2SDimitry Andric if (llvm::is_contained(GlobalData.Options.AccelTables, 1169*1db9f3b2SDimitry Andric AccelTableKind::DebugNames)) { 1170*1db9f3b2SDimitry Andric // Emit .debug_names section. 1171*1db9f3b2SDimitry Andric TG.spawn([&]() { emitDWARFv5DebugNamesSection(TargetTriple); }); 1172*1db9f3b2SDimitry Andric } 1173*1db9f3b2SDimitry Andric 1174*1db9f3b2SDimitry Andric // Write compile units to the output file. 1175*1db9f3b2SDimitry Andric TG.spawn([&]() { writeCompileUnitsToTheOutput(); }); 1176*1db9f3b2SDimitry Andric } 1177*1db9f3b2SDimitry Andric 1178*1db9f3b2SDimitry Andric void DWARFLinkerImpl::emitStringSections() { 1179*1db9f3b2SDimitry Andric uint64_t DebugStrNextOffset = 0; 1180*1db9f3b2SDimitry Andric uint64_t DebugLineStrNextOffset = 0; 1181*1db9f3b2SDimitry Andric 1182*1db9f3b2SDimitry Andric // Emit zero length string. Accelerator tables does not work correctly 1183*1db9f3b2SDimitry Andric // if the first string is not zero length string. 1184*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr) 1185*1db9f3b2SDimitry Andric .emitInplaceString(""); 1186*1db9f3b2SDimitry Andric DebugStrNextOffset++; 1187*1db9f3b2SDimitry Andric 1188*1db9f3b2SDimitry Andric forEachOutputString( 1189*1db9f3b2SDimitry Andric [&](StringDestinationKind Kind, const StringEntry *String) { 1190*1db9f3b2SDimitry Andric switch (Kind) { 1191*1db9f3b2SDimitry Andric case StringDestinationKind::DebugStr: { 1192*1db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *StringToEmit = 1193*1db9f3b2SDimitry Andric DebugStrStrings.getExistingEntry(String); 1194*1db9f3b2SDimitry Andric assert(StringToEmit->isIndexed()); 1195*1db9f3b2SDimitry Andric 1196*1db9f3b2SDimitry Andric // Strings may be repeated. Use accumulated DebugStrNextOffset 1197*1db9f3b2SDimitry Andric // to understand whether corresponding string is already emitted. 1198*1db9f3b2SDimitry Andric // Skip string if its offset less than accumulated offset. 1199*1db9f3b2SDimitry Andric if (StringToEmit->Offset >= DebugStrNextOffset) { 1200*1db9f3b2SDimitry Andric DebugStrNextOffset = 1201*1db9f3b2SDimitry Andric StringToEmit->Offset + StringToEmit->String.size() + 1; 1202*1db9f3b2SDimitry Andric // Emit the string itself. 1203*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr) 1204*1db9f3b2SDimitry Andric .emitInplaceString(StringToEmit->String); 1205*1db9f3b2SDimitry Andric } 1206*1db9f3b2SDimitry Andric } break; 1207*1db9f3b2SDimitry Andric case StringDestinationKind::DebugLineStr: { 1208*1db9f3b2SDimitry Andric DwarfStringPoolEntryWithExtString *StringToEmit = 1209*1db9f3b2SDimitry Andric DebugLineStrStrings.getExistingEntry(String); 1210*1db9f3b2SDimitry Andric assert(StringToEmit->isIndexed()); 1211*1db9f3b2SDimitry Andric 1212*1db9f3b2SDimitry Andric // Strings may be repeated. Use accumulated DebugLineStrStrings 1213*1db9f3b2SDimitry Andric // to understand whether corresponding string is already emitted. 1214*1db9f3b2SDimitry Andric // Skip string if its offset less than accumulated offset. 1215*1db9f3b2SDimitry Andric if (StringToEmit->Offset >= DebugLineStrNextOffset) { 1216*1db9f3b2SDimitry Andric DebugLineStrNextOffset = 1217*1db9f3b2SDimitry Andric StringToEmit->Offset + StringToEmit->String.size() + 1; 1218*1db9f3b2SDimitry Andric // Emit the string itself. 1219*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr) 1220*1db9f3b2SDimitry Andric .emitInplaceString(StringToEmit->String); 1221*1db9f3b2SDimitry Andric } 1222*1db9f3b2SDimitry Andric } break; 1223*1db9f3b2SDimitry Andric } 1224*1db9f3b2SDimitry Andric }); 1225*1db9f3b2SDimitry Andric } 1226*1db9f3b2SDimitry Andric 1227*1db9f3b2SDimitry Andric void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) { 1228*1db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces; 1229*1db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> AppleNames; 1230*1db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> AppleObjC; 1231*1db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticTypeData> AppleTypes; 1232*1db9f3b2SDimitry Andric 1233*1db9f3b2SDimitry Andric forEachCompileAndTypeUnit([&](DwarfUnit *CU) { 1234*1db9f3b2SDimitry Andric CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 1235*1db9f3b2SDimitry Andric uint64_t OutOffset = Info.OutOffset; 1236*1db9f3b2SDimitry Andric switch (Info.Type) { 1237*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::None: { 1238*1db9f3b2SDimitry Andric llvm_unreachable("Unknown accelerator record"); 1239*1db9f3b2SDimitry Andric } break; 1240*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::Namespace: { 1241*1db9f3b2SDimitry Andric AppleNamespaces.addName( 1242*1db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 1243*1db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1244*1db9f3b2SDimitry Andric OutOffset); 1245*1db9f3b2SDimitry Andric } break; 1246*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::Name: { 1247*1db9f3b2SDimitry Andric AppleNames.addName( 1248*1db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 1249*1db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1250*1db9f3b2SDimitry Andric OutOffset); 1251*1db9f3b2SDimitry Andric } break; 1252*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::ObjC: { 1253*1db9f3b2SDimitry Andric AppleObjC.addName( 1254*1db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 1255*1db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1256*1db9f3b2SDimitry Andric OutOffset); 1257*1db9f3b2SDimitry Andric } break; 1258*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::Type: { 1259*1db9f3b2SDimitry Andric AppleTypes.addName( 1260*1db9f3b2SDimitry Andric *DebugStrStrings.getExistingEntry(Info.String), 1261*1db9f3b2SDimitry Andric CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset + 1262*1db9f3b2SDimitry Andric OutOffset, 1263*1db9f3b2SDimitry Andric Info.Tag, 1264*1db9f3b2SDimitry Andric Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation 1265*1db9f3b2SDimitry Andric : 0, 1266*1db9f3b2SDimitry Andric Info.QualifiedNameHash); 1267*1db9f3b2SDimitry Andric } break; 1268*1db9f3b2SDimitry Andric } 1269*1db9f3b2SDimitry Andric }); 1270*1db9f3b2SDimitry Andric }); 1271*1db9f3b2SDimitry Andric 1272*1db9f3b2SDimitry Andric { 1273*1db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 1274*1db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 1275*1db9f3b2SDimitry Andric // to the raw_svector_ostream. 1276*1db9f3b2SDimitry Andric SectionDescriptor &OutSection = 1277*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces); 1278*1db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1279*1db9f3b2SDimitry Andric OutSection.OS); 1280*1db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1281*1db9f3b2SDimitry Andric consumeError(std::move(Err)); 1282*1db9f3b2SDimitry Andric return; 1283*1db9f3b2SDimitry Andric } 1284*1db9f3b2SDimitry Andric 1285*1db9f3b2SDimitry Andric // Emit table. 1286*1db9f3b2SDimitry Andric Emitter.emitAppleNamespaces(AppleNamespaces); 1287*1db9f3b2SDimitry Andric Emitter.finish(); 1288*1db9f3b2SDimitry Andric 1289*1db9f3b2SDimitry Andric // Set start offset and size for output section. 1290*1db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 1291*1db9f3b2SDimitry Andric } 1292*1db9f3b2SDimitry Andric 1293*1db9f3b2SDimitry Andric { 1294*1db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 1295*1db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 1296*1db9f3b2SDimitry Andric // to the raw_svector_ostream. 1297*1db9f3b2SDimitry Andric SectionDescriptor &OutSection = 1298*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames); 1299*1db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1300*1db9f3b2SDimitry Andric OutSection.OS); 1301*1db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1302*1db9f3b2SDimitry Andric consumeError(std::move(Err)); 1303*1db9f3b2SDimitry Andric return; 1304*1db9f3b2SDimitry Andric } 1305*1db9f3b2SDimitry Andric 1306*1db9f3b2SDimitry Andric // Emit table. 1307*1db9f3b2SDimitry Andric Emitter.emitAppleNames(AppleNames); 1308*1db9f3b2SDimitry Andric Emitter.finish(); 1309*1db9f3b2SDimitry Andric 1310*1db9f3b2SDimitry Andric // Set start offset ans size for output section. 1311*1db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 1312*1db9f3b2SDimitry Andric } 1313*1db9f3b2SDimitry Andric 1314*1db9f3b2SDimitry Andric { 1315*1db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 1316*1db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 1317*1db9f3b2SDimitry Andric // to the raw_svector_ostream. 1318*1db9f3b2SDimitry Andric SectionDescriptor &OutSection = 1319*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC); 1320*1db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1321*1db9f3b2SDimitry Andric OutSection.OS); 1322*1db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1323*1db9f3b2SDimitry Andric consumeError(std::move(Err)); 1324*1db9f3b2SDimitry Andric return; 1325*1db9f3b2SDimitry Andric } 1326*1db9f3b2SDimitry Andric 1327*1db9f3b2SDimitry Andric // Emit table. 1328*1db9f3b2SDimitry Andric Emitter.emitAppleObjc(AppleObjC); 1329*1db9f3b2SDimitry Andric Emitter.finish(); 1330*1db9f3b2SDimitry Andric 1331*1db9f3b2SDimitry Andric // Set start offset ans size for output section. 1332*1db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 1333*1db9f3b2SDimitry Andric } 1334*1db9f3b2SDimitry Andric 1335*1db9f3b2SDimitry Andric { 1336*1db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 1337*1db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 1338*1db9f3b2SDimitry Andric // to the raw_svector_ostream. 1339*1db9f3b2SDimitry Andric SectionDescriptor &OutSection = 1340*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes); 1341*1db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1342*1db9f3b2SDimitry Andric OutSection.OS); 1343*1db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1344*1db9f3b2SDimitry Andric consumeError(std::move(Err)); 1345*1db9f3b2SDimitry Andric return; 1346*1db9f3b2SDimitry Andric } 1347*1db9f3b2SDimitry Andric 1348*1db9f3b2SDimitry Andric // Emit table. 1349*1db9f3b2SDimitry Andric Emitter.emitAppleTypes(AppleTypes); 1350*1db9f3b2SDimitry Andric Emitter.finish(); 1351*1db9f3b2SDimitry Andric 1352*1db9f3b2SDimitry Andric // Set start offset ans size for output section. 1353*1db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 1354*1db9f3b2SDimitry Andric } 1355*1db9f3b2SDimitry Andric } 1356*1db9f3b2SDimitry Andric 1357*1db9f3b2SDimitry Andric void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) { 1358*1db9f3b2SDimitry Andric std::unique_ptr<DWARF5AccelTable> DebugNames; 1359*1db9f3b2SDimitry Andric 1360*1db9f3b2SDimitry Andric DebugNamesUnitsOffsets CompUnits; 1361*1db9f3b2SDimitry Andric CompUnitIDToIdx CUidToIdx; 1362*1db9f3b2SDimitry Andric 1363*1db9f3b2SDimitry Andric unsigned Id = 0; 1364*1db9f3b2SDimitry Andric 1365*1db9f3b2SDimitry Andric forEachCompileAndTypeUnit([&](DwarfUnit *CU) { 1366*1db9f3b2SDimitry Andric bool HasRecords = false; 1367*1db9f3b2SDimitry Andric CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) { 1368*1db9f3b2SDimitry Andric if (DebugNames.get() == nullptr) 1369*1db9f3b2SDimitry Andric DebugNames = std::make_unique<DWARF5AccelTable>(); 1370*1db9f3b2SDimitry Andric 1371*1db9f3b2SDimitry Andric HasRecords = true; 1372*1db9f3b2SDimitry Andric switch (Info.Type) { 1373*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::Name: 1374*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::Namespace: 1375*1db9f3b2SDimitry Andric case DwarfUnit::AccelType::Type: { 1376*1db9f3b2SDimitry Andric DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String), 1377*1db9f3b2SDimitry Andric Info.OutOffset, Info.Tag, CU->getUniqueID()); 1378*1db9f3b2SDimitry Andric } break; 1379*1db9f3b2SDimitry Andric 1380*1db9f3b2SDimitry Andric default: 1381*1db9f3b2SDimitry Andric break; // Nothing to do. 1382*1db9f3b2SDimitry Andric }; 1383*1db9f3b2SDimitry Andric }); 1384*1db9f3b2SDimitry Andric 1385*1db9f3b2SDimitry Andric if (HasRecords) { 1386*1db9f3b2SDimitry Andric CompUnits.push_back( 1387*1db9f3b2SDimitry Andric CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo) 1388*1db9f3b2SDimitry Andric .StartOffset); 1389*1db9f3b2SDimitry Andric CUidToIdx[CU->getUniqueID()] = Id++; 1390*1db9f3b2SDimitry Andric } 1391*1db9f3b2SDimitry Andric }); 1392*1db9f3b2SDimitry Andric 1393*1db9f3b2SDimitry Andric if (DebugNames.get() != nullptr) { 1394*1db9f3b2SDimitry Andric // FIXME: we use AsmPrinter to emit accelerator sections. 1395*1db9f3b2SDimitry Andric // It might be beneficial to directly emit accelerator data 1396*1db9f3b2SDimitry Andric // to the raw_svector_ostream. 1397*1db9f3b2SDimitry Andric SectionDescriptor &OutSection = 1398*1db9f3b2SDimitry Andric CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames); 1399*1db9f3b2SDimitry Andric DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, 1400*1db9f3b2SDimitry Andric OutSection.OS); 1401*1db9f3b2SDimitry Andric if (Error Err = Emitter.init(TargetTriple, "__DWARF")) { 1402*1db9f3b2SDimitry Andric consumeError(std::move(Err)); 1403*1db9f3b2SDimitry Andric return; 1404*1db9f3b2SDimitry Andric } 1405*1db9f3b2SDimitry Andric 1406*1db9f3b2SDimitry Andric // Emit table. 1407*1db9f3b2SDimitry Andric Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx); 1408*1db9f3b2SDimitry Andric Emitter.finish(); 1409*1db9f3b2SDimitry Andric 1410*1db9f3b2SDimitry Andric // Set start offset ans size for output section. 1411*1db9f3b2SDimitry Andric OutSection.setSizesForSectionCreatedByAsmPrinter(); 1412*1db9f3b2SDimitry Andric } 1413*1db9f3b2SDimitry Andric } 1414*1db9f3b2SDimitry Andric 1415*1db9f3b2SDimitry Andric void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() { 1416*1db9f3b2SDimitry Andric GlobalData.getStringPool().clear(); 1417*1db9f3b2SDimitry Andric DebugStrStrings.clear(); 1418*1db9f3b2SDimitry Andric DebugLineStrStrings.clear(); 1419*1db9f3b2SDimitry Andric } 1420*1db9f3b2SDimitry Andric 1421*1db9f3b2SDimitry Andric void DWARFLinkerImpl::writeCompileUnitsToTheOutput() { 1422*1db9f3b2SDimitry Andric bool HasAbbreviations = false; 1423*1db9f3b2SDimitry Andric 1424*1db9f3b2SDimitry Andric // Enumerate all sections and store them into the final emitter. 1425*1db9f3b2SDimitry Andric forEachObjectSectionsSet([&](OutputSections &Sections) { 1426*1db9f3b2SDimitry Andric Sections.forEach([&](SectionDescriptor &OutSection) { 1427*1db9f3b2SDimitry Andric if (!HasAbbreviations && !OutSection.getContents().empty() && 1428*1db9f3b2SDimitry Andric OutSection.getKind() == DebugSectionKind::DebugAbbrev) 1429*1db9f3b2SDimitry Andric HasAbbreviations = true; 1430*1db9f3b2SDimitry Andric 1431*1db9f3b2SDimitry Andric // Emit section content. 1432*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents(OutSection.getContents(), 1433*1db9f3b2SDimitry Andric OutSection.getName()); 1434*1db9f3b2SDimitry Andric OutSection.clearSectionContent(); 1435*1db9f3b2SDimitry Andric }); 1436*1db9f3b2SDimitry Andric }); 1437*1db9f3b2SDimitry Andric 1438*1db9f3b2SDimitry Andric if (!HasAbbreviations) { 1439*1db9f3b2SDimitry Andric const SmallVector<std::unique_ptr<DIEAbbrev>> Abbreviations; 1440*1db9f3b2SDimitry Andric TheDwarfEmitter->emitAbbrevs(Abbreviations, 3); 1441*1db9f3b2SDimitry Andric } 1442*1db9f3b2SDimitry Andric } 1443*1db9f3b2SDimitry Andric 1444*1db9f3b2SDimitry Andric void DWARFLinkerImpl::writeCommonSectionsToTheOutput() { 1445*1db9f3b2SDimitry Andric CommonSections.forEach([&](SectionDescriptor &OutSection) { 1446*1db9f3b2SDimitry Andric // Emit section content. 1447*1db9f3b2SDimitry Andric TheDwarfEmitter->emitSectionContents(OutSection.getContents(), 1448*1db9f3b2SDimitry Andric OutSection.getName()); 1449*1db9f3b2SDimitry Andric OutSection.clearSectionContent(); 1450*1db9f3b2SDimitry Andric }); 1451*1db9f3b2SDimitry Andric } 1452