1fcaf7f86SDimitry Andric //=== DebugInfoLinker.cpp -------------------------------------------------===// 2fcaf7f86SDimitry Andric // 3fcaf7f86SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fcaf7f86SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fcaf7f86SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fcaf7f86SDimitry Andric // 7fcaf7f86SDimitry Andric //===----------------------------------------------------------------------===// 8fcaf7f86SDimitry Andric 9fcaf7f86SDimitry Andric #include "DebugInfoLinker.h" 10fcaf7f86SDimitry Andric #include "Error.h" 11972a253aSDimitry Andric #include "llvm/ADT/StringSwitch.h" 12fcaf7f86SDimitry Andric #include "llvm/DWARFLinker/DWARFLinker.h" 13fcaf7f86SDimitry Andric #include "llvm/DWARFLinker/DWARFStreamer.h" 14*06c3fb27SDimitry Andric #include "llvm/DWARFLinkerParallel/DWARFLinker.h" 15fcaf7f86SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 16fcaf7f86SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 17fcaf7f86SDimitry Andric #include "llvm/Object/ObjectFile.h" 18bdd1243dSDimitry Andric #include "llvm/Support/Endian.h" 19fcaf7f86SDimitry Andric #include <memory> 20fcaf7f86SDimitry Andric #include <vector> 21fcaf7f86SDimitry Andric 22fcaf7f86SDimitry Andric namespace llvm { 23fcaf7f86SDimitry Andric namespace dwarfutil { 24fcaf7f86SDimitry Andric 25fcaf7f86SDimitry Andric // ObjFileAddressMap allows to check whether specified DIE referencing 26fcaf7f86SDimitry Andric // dead addresses. It uses tombstone values to determine dead addresses. 27fcaf7f86SDimitry Andric // The concrete values of tombstone constants were discussed in 28fcaf7f86SDimitry Andric // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825. 29fcaf7f86SDimitry Andric // So we use following values as indicators of dead addresses: 30fcaf7f86SDimitry Andric // 31fcaf7f86SDimitry Andric // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less)) 32fcaf7f86SDimitry Andric // or ([LowPC, HighPC] is not inside address ranges of .text sections). 33fcaf7f86SDimitry Andric // 34fcaf7f86SDimitry Andric // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less)) 35fcaf7f86SDimitry Andric // That value is assumed to be compatible with 36fcaf7f86SDimitry Andric // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1 37fcaf7f86SDimitry Andric // 38fcaf7f86SDimitry Andric // exec: [LowPC, HighPC] is not inside address ranges of .text sections 39fcaf7f86SDimitry Andric // 40fcaf7f86SDimitry Andric // universal: maxpc and bfd 41*06c3fb27SDimitry Andric template <typename AddressMapBase> 42*06c3fb27SDimitry Andric class ObjFileAddressMap : public AddressMapBase { 43fcaf7f86SDimitry Andric public: 44fcaf7f86SDimitry Andric ObjFileAddressMap(DWARFContext &Context, const Options &Options, 45fcaf7f86SDimitry Andric object::ObjectFile &ObjFile) 46*06c3fb27SDimitry Andric : Opts(Options) { 47fcaf7f86SDimitry Andric // Remember addresses of existing text sections. 48fcaf7f86SDimitry Andric for (const object::SectionRef &Sect : ObjFile.sections()) { 49fcaf7f86SDimitry Andric if (!Sect.isText()) 50fcaf7f86SDimitry Andric continue; 51fcaf7f86SDimitry Andric const uint64_t Size = Sect.getSize(); 52fcaf7f86SDimitry Andric if (Size == 0) 53fcaf7f86SDimitry Andric continue; 54fcaf7f86SDimitry Andric const uint64_t StartAddr = Sect.getAddress(); 55fcaf7f86SDimitry Andric TextAddressRanges.insert({StartAddr, StartAddr + Size}); 56fcaf7f86SDimitry Andric } 57fcaf7f86SDimitry Andric 58fcaf7f86SDimitry Andric // Check CU address ranges for tombstone value. 59fcaf7f86SDimitry Andric for (std::unique_ptr<DWARFUnit> &CU : Context.compile_units()) { 60fcaf7f86SDimitry Andric Expected<llvm::DWARFAddressRangesVector> ARanges = 61fcaf7f86SDimitry Andric CU->getUnitDIE().getAddressRanges(); 62*06c3fb27SDimitry Andric if (!ARanges) { 63*06c3fb27SDimitry Andric llvm::consumeError(ARanges.takeError()); 64*06c3fb27SDimitry Andric continue; 65*06c3fb27SDimitry Andric } 66*06c3fb27SDimitry Andric 67fcaf7f86SDimitry Andric for (auto &Range : *ARanges) { 68fcaf7f86SDimitry Andric if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(), 69*06c3fb27SDimitry Andric Options.Tombstone, CU->getAddressByteSize())) { 70*06c3fb27SDimitry Andric HasValidAddressRanges = true; 71*06c3fb27SDimitry Andric break; 72fcaf7f86SDimitry Andric } 73fcaf7f86SDimitry Andric } 74*06c3fb27SDimitry Andric 75*06c3fb27SDimitry Andric if (HasValidAddressRanges) 76*06c3fb27SDimitry Andric break; 77fcaf7f86SDimitry Andric } 78fcaf7f86SDimitry Andric } 79fcaf7f86SDimitry Andric 80fcaf7f86SDimitry Andric // should be renamed into has valid address ranges 81*06c3fb27SDimitry Andric bool hasValidRelocs() override { return HasValidAddressRanges; } 82fcaf7f86SDimitry Andric 83*06c3fb27SDimitry Andric std::optional<int64_t> 84*06c3fb27SDimitry Andric getSubprogramRelocAdjustment(const DWARFDie &DIE) override { 85fcaf7f86SDimitry Andric assert((DIE.getTag() == dwarf::DW_TAG_subprogram || 86fcaf7f86SDimitry Andric DIE.getTag() == dwarf::DW_TAG_label) && 87fcaf7f86SDimitry Andric "Wrong type of input die"); 88fcaf7f86SDimitry Andric 89bdd1243dSDimitry Andric if (std::optional<uint64_t> LowPC = 90fcaf7f86SDimitry Andric dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) { 91fcaf7f86SDimitry Andric if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(), 92fcaf7f86SDimitry Andric Opts.Tombstone, 93*06c3fb27SDimitry Andric DIE.getDwarfUnit()->getAddressByteSize())) 94*06c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 95*06c3fb27SDimitry Andric return 0; 96fcaf7f86SDimitry Andric } 97fcaf7f86SDimitry Andric 98*06c3fb27SDimitry Andric return std::nullopt; 99fcaf7f86SDimitry Andric } 100fcaf7f86SDimitry Andric 101*06c3fb27SDimitry Andric std::optional<int64_t> getExprOpAddressRelocAdjustment( 102*06c3fb27SDimitry Andric DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset, 103*06c3fb27SDimitry Andric uint64_t EndOffset) override { 104*06c3fb27SDimitry Andric switch (Op.getCode()) { 105*06c3fb27SDimitry Andric default: { 106*06c3fb27SDimitry Andric assert(false && "Specified operation does not have address operand"); 107*06c3fb27SDimitry Andric } break; 108*06c3fb27SDimitry Andric case dwarf::DW_OP_const4u: 109*06c3fb27SDimitry Andric case dwarf::DW_OP_const8u: 110*06c3fb27SDimitry Andric case dwarf::DW_OP_const4s: 111*06c3fb27SDimitry Andric case dwarf::DW_OP_const8s: 112*06c3fb27SDimitry Andric case dwarf::DW_OP_addr: { 113*06c3fb27SDimitry Andric if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone, 114*06c3fb27SDimitry Andric U.getAddressByteSize())) 115*06c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 116*06c3fb27SDimitry Andric return 0; 117*06c3fb27SDimitry Andric } break; 118*06c3fb27SDimitry Andric case dwarf::DW_OP_constx: 119*06c3fb27SDimitry Andric case dwarf::DW_OP_addrx: { 120*06c3fb27SDimitry Andric if (std::optional<object::SectionedAddress> Address = 121*06c3fb27SDimitry Andric U.getAddrOffsetSectionItem(Op.getRawOperand(0))) { 122*06c3fb27SDimitry Andric if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone, 123*06c3fb27SDimitry Andric U.getAddressByteSize())) 124*06c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 125*06c3fb27SDimitry Andric return 0; 126fcaf7f86SDimitry Andric } 127*06c3fb27SDimitry Andric } break; 128fcaf7f86SDimitry Andric } 129fcaf7f86SDimitry Andric 130*06c3fb27SDimitry Andric return std::nullopt; 131fcaf7f86SDimitry Andric } 132fcaf7f86SDimitry Andric 133fcaf7f86SDimitry Andric bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override { 134fcaf7f86SDimitry Andric // no need to apply relocations to the linked binary. 135fcaf7f86SDimitry Andric return false; 136fcaf7f86SDimitry Andric } 137fcaf7f86SDimitry Andric 138*06c3fb27SDimitry Andric void clear() override {} 139fcaf7f86SDimitry Andric 140fcaf7f86SDimitry Andric protected: 141fcaf7f86SDimitry Andric // returns true if specified address range is inside address ranges 142fcaf7f86SDimitry Andric // of executable sections. 143fcaf7f86SDimitry Andric bool isInsideExecutableSectionsAddressRange(uint64_t LowPC, 144bdd1243dSDimitry Andric std::optional<uint64_t> HighPC) { 145bdd1243dSDimitry Andric std::optional<AddressRange> Range = 146fcaf7f86SDimitry Andric TextAddressRanges.getRangeThatContains(LowPC); 147fcaf7f86SDimitry Andric 148fcaf7f86SDimitry Andric if (HighPC) 149fcaf7f86SDimitry Andric return Range.has_value() && Range->end() >= *HighPC; 150fcaf7f86SDimitry Andric 151fcaf7f86SDimitry Andric return Range.has_value(); 152fcaf7f86SDimitry Andric } 153fcaf7f86SDimitry Andric 154bdd1243dSDimitry Andric uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 155fcaf7f86SDimitry Andric uint16_t Version) { 156fcaf7f86SDimitry Andric if (LowPC == 0) 157fcaf7f86SDimitry Andric return true; 158fcaf7f86SDimitry Andric 159fcaf7f86SDimitry Andric if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1)) 160fcaf7f86SDimitry Andric return true; 161fcaf7f86SDimitry Andric 162fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 163fcaf7f86SDimitry Andric } 164fcaf7f86SDimitry Andric 165bdd1243dSDimitry Andric uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, 166bdd1243dSDimitry Andric std::optional<uint64_t> HighPC, 167fcaf7f86SDimitry Andric uint16_t Version, uint8_t AddressByteSize) { 168fcaf7f86SDimitry Andric if (Version <= 4 && HighPC) { 169fcaf7f86SDimitry Andric if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1)) 170fcaf7f86SDimitry Andric return true; 171fcaf7f86SDimitry Andric } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize)) 172fcaf7f86SDimitry Andric return true; 173fcaf7f86SDimitry Andric 174fcaf7f86SDimitry Andric if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC)) 175fcaf7f86SDimitry Andric warning("Address referencing invalid text section is not marked with " 176fcaf7f86SDimitry Andric "tombstone value"); 177fcaf7f86SDimitry Andric 178fcaf7f86SDimitry Andric return false; 179fcaf7f86SDimitry Andric } 180fcaf7f86SDimitry Andric 181bdd1243dSDimitry Andric bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 182fcaf7f86SDimitry Andric uint16_t Version, TombstoneKind Tombstone, 183fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 184fcaf7f86SDimitry Andric switch (Tombstone) { 185fcaf7f86SDimitry Andric case TombstoneKind::BFD: 186fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version); 187fcaf7f86SDimitry Andric case TombstoneKind::MaxPC: 188fcaf7f86SDimitry Andric return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 189fcaf7f86SDimitry Andric case TombstoneKind::Universal: 190fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version) || 191fcaf7f86SDimitry Andric isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 192fcaf7f86SDimitry Andric case TombstoneKind::Exec: 193fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 194fcaf7f86SDimitry Andric } 195fcaf7f86SDimitry Andric 196fcaf7f86SDimitry Andric llvm_unreachable("Unknown tombstone value"); 197fcaf7f86SDimitry Andric } 198fcaf7f86SDimitry Andric 199fcaf7f86SDimitry Andric bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone, 200fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 201bdd1243dSDimitry Andric return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone, 202bdd1243dSDimitry Andric AddressByteSize); 203fcaf7f86SDimitry Andric } 204fcaf7f86SDimitry Andric 205fcaf7f86SDimitry Andric private: 206fcaf7f86SDimitry Andric AddressRanges TextAddressRanges; 207fcaf7f86SDimitry Andric const Options &Opts; 208*06c3fb27SDimitry Andric bool HasValidAddressRanges = false; 209fcaf7f86SDimitry Andric }; 210fcaf7f86SDimitry Andric 211972a253aSDimitry Andric static bool knownByDWARFUtil(StringRef SecName) { 212972a253aSDimitry Andric return llvm::StringSwitch<bool>(SecName) 213972a253aSDimitry Andric .Case(".debug_info", true) 214972a253aSDimitry Andric .Case(".debug_types", true) 215972a253aSDimitry Andric .Case(".debug_abbrev", true) 216972a253aSDimitry Andric .Case(".debug_loc", true) 217972a253aSDimitry Andric .Case(".debug_loclists", true) 218972a253aSDimitry Andric .Case(".debug_frame", true) 219972a253aSDimitry Andric .Case(".debug_aranges", true) 220972a253aSDimitry Andric .Case(".debug_ranges", true) 221972a253aSDimitry Andric .Case(".debug_rnglists", true) 222972a253aSDimitry Andric .Case(".debug_line", true) 223972a253aSDimitry Andric .Case(".debug_line_str", true) 224972a253aSDimitry Andric .Case(".debug_addr", true) 225972a253aSDimitry Andric .Case(".debug_macro", true) 226972a253aSDimitry Andric .Case(".debug_macinfo", true) 227972a253aSDimitry Andric .Case(".debug_str", true) 228972a253aSDimitry Andric .Case(".debug_str_offsets", true) 229bdd1243dSDimitry Andric .Case(".debug_pubnames", true) 230bdd1243dSDimitry Andric .Case(".debug_pubtypes", true) 231bdd1243dSDimitry Andric .Case(".debug_names", true) 232972a253aSDimitry Andric .Default(false); 233972a253aSDimitry Andric } 234972a253aSDimitry Andric 235*06c3fb27SDimitry Andric template <typename AccelTableKind> 236*06c3fb27SDimitry Andric static std::optional<AccelTableKind> 237bdd1243dSDimitry Andric getAcceleratorTableKind(StringRef SecName) { 238*06c3fb27SDimitry Andric return llvm::StringSwitch<std::optional<AccelTableKind>>(SecName) 239*06c3fb27SDimitry Andric .Case(".debug_pubnames", AccelTableKind::Pub) 240*06c3fb27SDimitry Andric .Case(".debug_pubtypes", AccelTableKind::Pub) 241*06c3fb27SDimitry Andric .Case(".debug_names", AccelTableKind::DebugNames) 242bdd1243dSDimitry Andric .Default(std::nullopt); 243bdd1243dSDimitry Andric } 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric static std::string getMessageForReplacedAcceleratorTables( 246bdd1243dSDimitry Andric SmallVector<StringRef> &AccelTableNamesToReplace, 247bdd1243dSDimitry Andric DwarfUtilAccelKind TargetTable) { 248bdd1243dSDimitry Andric std::string Message; 249bdd1243dSDimitry Andric 250bdd1243dSDimitry Andric Message += "'"; 251bdd1243dSDimitry Andric for (StringRef Name : AccelTableNamesToReplace) { 252bdd1243dSDimitry Andric if (Message.size() > 1) 253bdd1243dSDimitry Andric Message += ", "; 254bdd1243dSDimitry Andric Message += Name; 255bdd1243dSDimitry Andric } 256bdd1243dSDimitry Andric 257bdd1243dSDimitry Andric Message += "' will be replaced with requested "; 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric switch (TargetTable) { 260bdd1243dSDimitry Andric case DwarfUtilAccelKind::DWARF: 261bdd1243dSDimitry Andric Message += ".debug_names table"; 262bdd1243dSDimitry Andric break; 263bdd1243dSDimitry Andric 264bdd1243dSDimitry Andric default: 265bdd1243dSDimitry Andric assert(false); 266bdd1243dSDimitry Andric } 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric return Message; 269bdd1243dSDimitry Andric } 270bdd1243dSDimitry Andric 271bdd1243dSDimitry Andric static std::string getMessageForDeletedAcceleratorTables( 272bdd1243dSDimitry Andric SmallVector<StringRef> &AccelTableNamesToReplace) { 273bdd1243dSDimitry Andric std::string Message; 274bdd1243dSDimitry Andric 275bdd1243dSDimitry Andric Message += "'"; 276bdd1243dSDimitry Andric for (StringRef Name : AccelTableNamesToReplace) { 277bdd1243dSDimitry Andric if (Message.size() > 1) 278bdd1243dSDimitry Andric Message += ", "; 279bdd1243dSDimitry Andric Message += Name; 280bdd1243dSDimitry Andric } 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric Message += "' will be deleted as no accelerator tables are requested"; 283bdd1243dSDimitry Andric 284bdd1243dSDimitry Andric return Message; 285bdd1243dSDimitry Andric } 286bdd1243dSDimitry Andric 287*06c3fb27SDimitry Andric template <typename Linker, typename OutDwarfFile, typename AddressMapBase> 288*06c3fb27SDimitry Andric Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, 289fcaf7f86SDimitry Andric raw_pwrite_stream &OutStream) { 290fcaf7f86SDimitry Andric auto ReportWarn = [&](const Twine &Message, StringRef Context, 291fcaf7f86SDimitry Andric const DWARFDie *Die) { 292fcaf7f86SDimitry Andric warning(Message, Context); 293fcaf7f86SDimitry Andric 294fcaf7f86SDimitry Andric if (!Options.Verbose || !Die) 295fcaf7f86SDimitry Andric return; 296fcaf7f86SDimitry Andric 297fcaf7f86SDimitry Andric DIDumpOptions DumpOpts; 298fcaf7f86SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 299fcaf7f86SDimitry Andric DumpOpts.Verbose = Options.Verbose; 300fcaf7f86SDimitry Andric 301fcaf7f86SDimitry Andric WithColor::note() << " in DIE:\n"; 302fcaf7f86SDimitry Andric Die->dump(errs(), /*Indent=*/6, DumpOpts); 303fcaf7f86SDimitry Andric }; 304fcaf7f86SDimitry Andric auto ReportErr = [&](const Twine &Message, StringRef Context, 305fcaf7f86SDimitry Andric const DWARFDie *) { 306fcaf7f86SDimitry Andric WithColor::error(errs(), Context) << Message << '\n'; 307fcaf7f86SDimitry Andric }; 308fcaf7f86SDimitry Andric 309fcaf7f86SDimitry Andric // Create DWARF linker. 310*06c3fb27SDimitry Andric std::unique_ptr<Linker> DebugInfoLinker = 311*06c3fb27SDimitry Andric Linker::createLinker(ReportErr, ReportWarn); 312fcaf7f86SDimitry Andric 313*06c3fb27SDimitry Andric Triple TargetTriple = File.makeTriple(); 314*06c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->createEmitter( 315*06c3fb27SDimitry Andric TargetTriple, Linker::OutputFileType::Object, OutStream)) 316*06c3fb27SDimitry Andric return Err; 317fcaf7f86SDimitry Andric 318*06c3fb27SDimitry Andric DebugInfoLinker->setEstimatedObjfilesAmount(1); 319*06c3fb27SDimitry Andric DebugInfoLinker->setNumThreads(Options.NumThreads); 320*06c3fb27SDimitry Andric DebugInfoLinker->setNoODR(!Options.DoODRDeduplication); 321*06c3fb27SDimitry Andric DebugInfoLinker->setVerbosity(Options.Verbose); 322*06c3fb27SDimitry Andric DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection); 323*06c3fb27SDimitry Andric 324*06c3fb27SDimitry Andric std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking(1); 325fcaf7f86SDimitry Andric std::vector<std::string> EmptyWarnings; 326fcaf7f86SDimitry Andric 327fcaf7f86SDimitry Andric // Add object files to the DWARFLinker. 328*06c3fb27SDimitry Andric std::unique_ptr<DWARFContext> Context = DWARFContext::create(File); 329*06c3fb27SDimitry Andric std::unique_ptr<ObjFileAddressMap<AddressMapBase>> AddressesMap( 330*06c3fb27SDimitry Andric std::make_unique<ObjFileAddressMap<AddressMapBase>>(*Context, Options, 331*06c3fb27SDimitry Andric File)); 332fcaf7f86SDimitry Andric 333*06c3fb27SDimitry Andric ObjectsForLinking[0] = 334*06c3fb27SDimitry Andric std::make_unique<OutDwarfFile>(File.getFileName(), std::move(Context), 335*06c3fb27SDimitry Andric std::move(AddressesMap), EmptyWarnings); 336fcaf7f86SDimitry Andric 337bdd1243dSDimitry Andric uint16_t MaxDWARFVersion = 0; 338bdd1243dSDimitry Andric std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded = 339bdd1243dSDimitry Andric [&MaxDWARFVersion](const DWARFUnit &Unit) { 340bdd1243dSDimitry Andric MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); 341bdd1243dSDimitry Andric }; 342bdd1243dSDimitry Andric 343fcaf7f86SDimitry Andric for (size_t I = 0; I < ObjectsForLinking.size(); I++) 344*06c3fb27SDimitry Andric DebugInfoLinker->addObjectFile(*ObjectsForLinking[I], nullptr, 345bdd1243dSDimitry Andric OnCUDieLoaded); 346bdd1243dSDimitry Andric 347bdd1243dSDimitry Andric // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. 348bdd1243dSDimitry Andric if (MaxDWARFVersion == 0) 349bdd1243dSDimitry Andric MaxDWARFVersion = 3; 350bdd1243dSDimitry Andric 351*06c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->setTargetDWARFVersion(MaxDWARFVersion)) 352bdd1243dSDimitry Andric return Err; 353bdd1243dSDimitry Andric 354*06c3fb27SDimitry Andric SmallVector<typename Linker::AccelTableKind> AccelTables; 355bdd1243dSDimitry Andric 356bdd1243dSDimitry Andric switch (Options.AccelTableKind) { 357bdd1243dSDimitry Andric case DwarfUtilAccelKind::None: 358bdd1243dSDimitry Andric // Nothing to do. 359bdd1243dSDimitry Andric break; 360bdd1243dSDimitry Andric case DwarfUtilAccelKind::DWARF: 361bdd1243dSDimitry Andric // use .debug_names for all DWARF versions. 362*06c3fb27SDimitry Andric AccelTables.push_back(Linker::AccelTableKind::DebugNames); 363bdd1243dSDimitry Andric break; 364bdd1243dSDimitry Andric } 365bdd1243dSDimitry Andric 366bdd1243dSDimitry Andric // Add accelerator tables to DWARFLinker. 367*06c3fb27SDimitry Andric for (typename Linker::AccelTableKind Table : AccelTables) 368*06c3fb27SDimitry Andric DebugInfoLinker->addAccelTableKind(Table); 369bdd1243dSDimitry Andric 370*06c3fb27SDimitry Andric for (std::unique_ptr<OutDwarfFile> &CurFile : ObjectsForLinking) { 371bdd1243dSDimitry Andric SmallVector<StringRef> AccelTableNamesToReplace; 372bdd1243dSDimitry Andric SmallVector<StringRef> AccelTableNamesToDelete; 373bdd1243dSDimitry Andric 374bdd1243dSDimitry Andric // Unknown debug sections or non-requested accelerator sections would be 375bdd1243dSDimitry Andric // removed. Display warning for such sections. 376*06c3fb27SDimitry Andric for (SectionName Sec : CurFile->Dwarf->getDWARFObj().getSectionNames()) { 377bdd1243dSDimitry Andric if (isDebugSection(Sec.Name)) { 378*06c3fb27SDimitry Andric std::optional<typename Linker::AccelTableKind> SrcAccelTableKind = 379*06c3fb27SDimitry Andric getAcceleratorTableKind<typename Linker::AccelTableKind>(Sec.Name); 380bdd1243dSDimitry Andric 381bdd1243dSDimitry Andric if (SrcAccelTableKind) { 382bdd1243dSDimitry Andric assert(knownByDWARFUtil(Sec.Name)); 383bdd1243dSDimitry Andric 384bdd1243dSDimitry Andric if (Options.AccelTableKind == DwarfUtilAccelKind::None) 385bdd1243dSDimitry Andric AccelTableNamesToDelete.push_back(Sec.Name); 386*06c3fb27SDimitry Andric else if (!llvm::is_contained(AccelTables, *SrcAccelTableKind)) 387bdd1243dSDimitry Andric AccelTableNamesToReplace.push_back(Sec.Name); 388bdd1243dSDimitry Andric } else if (!knownByDWARFUtil(Sec.Name)) { 389bdd1243dSDimitry Andric assert(!SrcAccelTableKind); 390bdd1243dSDimitry Andric warning( 391*06c3fb27SDimitry Andric formatv( 392*06c3fb27SDimitry Andric "'{0}' is not currently supported: section will be skipped", 393bdd1243dSDimitry Andric Sec.Name), 394bdd1243dSDimitry Andric Options.InputFileName); 395bdd1243dSDimitry Andric } 396bdd1243dSDimitry Andric } 397bdd1243dSDimitry Andric } 398bdd1243dSDimitry Andric 399bdd1243dSDimitry Andric // Display message for the replaced accelerator tables. 400bdd1243dSDimitry Andric if (!AccelTableNamesToReplace.empty()) 401bdd1243dSDimitry Andric warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace, 402bdd1243dSDimitry Andric Options.AccelTableKind), 403bdd1243dSDimitry Andric Options.InputFileName); 404bdd1243dSDimitry Andric 405bdd1243dSDimitry Andric // Display message for the removed accelerator tables. 406bdd1243dSDimitry Andric if (!AccelTableNamesToDelete.empty()) 407bdd1243dSDimitry Andric warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete), 408bdd1243dSDimitry Andric Options.InputFileName); 409*06c3fb27SDimitry Andric } 410fcaf7f86SDimitry Andric 411fcaf7f86SDimitry Andric // Link debug info. 412*06c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->link()) 413972a253aSDimitry Andric return Err; 414972a253aSDimitry Andric 415*06c3fb27SDimitry Andric DebugInfoLinker->getEmitter()->finish(); 416972a253aSDimitry Andric return Error::success(); 417fcaf7f86SDimitry Andric } 418fcaf7f86SDimitry Andric 419*06c3fb27SDimitry Andric Error linkDebugInfo(object::ObjectFile &File, const Options &Options, 420*06c3fb27SDimitry Andric raw_pwrite_stream &OutStream) { 421*06c3fb27SDimitry Andric if (Options.UseLLVMDWARFLinker) 422*06c3fb27SDimitry Andric return linkDebugInfoImpl<dwarflinker_parallel::DWARFLinker, 423*06c3fb27SDimitry Andric dwarflinker_parallel::DWARFFile, 424*06c3fb27SDimitry Andric dwarflinker_parallel::AddressesMap>(File, Options, 425*06c3fb27SDimitry Andric OutStream); 426*06c3fb27SDimitry Andric else 427*06c3fb27SDimitry Andric return linkDebugInfoImpl<DWARFLinker, DWARFFile, AddressesMap>( 428*06c3fb27SDimitry Andric File, Options, OutStream); 429*06c3fb27SDimitry Andric } 430*06c3fb27SDimitry Andric 431fcaf7f86SDimitry Andric } // end of namespace dwarfutil 432fcaf7f86SDimitry Andric } // end of namespace llvm 433