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" 121db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinker.h" 131db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFStreamer.h" 141db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Parallel/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" 18fcaf7f86SDimitry Andric #include <memory> 19fcaf7f86SDimitry Andric #include <vector> 20fcaf7f86SDimitry Andric 21fcaf7f86SDimitry Andric namespace llvm { 221db9f3b2SDimitry Andric using namespace dwarf_linker; 231db9f3b2SDimitry Andric 24fcaf7f86SDimitry Andric namespace dwarfutil { 25fcaf7f86SDimitry Andric 26fcaf7f86SDimitry Andric // ObjFileAddressMap allows to check whether specified DIE referencing 27fcaf7f86SDimitry Andric // dead addresses. It uses tombstone values to determine dead addresses. 28fcaf7f86SDimitry Andric // The concrete values of tombstone constants were discussed in 29fcaf7f86SDimitry Andric // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825. 30fcaf7f86SDimitry Andric // So we use following values as indicators of dead addresses: 31fcaf7f86SDimitry Andric // 32fcaf7f86SDimitry Andric // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less)) 33fcaf7f86SDimitry Andric // or ([LowPC, HighPC] is not inside address ranges of .text sections). 34fcaf7f86SDimitry Andric // 35fcaf7f86SDimitry Andric // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less)) 36fcaf7f86SDimitry Andric // That value is assumed to be compatible with 37fcaf7f86SDimitry Andric // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1 38fcaf7f86SDimitry Andric // 39fcaf7f86SDimitry Andric // exec: [LowPC, HighPC] is not inside address ranges of .text sections 40fcaf7f86SDimitry Andric // 41fcaf7f86SDimitry Andric // universal: maxpc and bfd 421db9f3b2SDimitry Andric class ObjFileAddressMap : public AddressesMap { 43fcaf7f86SDimitry Andric public: 44fcaf7f86SDimitry Andric ObjFileAddressMap(DWARFContext &Context, const Options &Options, 45fcaf7f86SDimitry Andric object::ObjectFile &ObjFile) 4606c3fb27SDimitry 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(); 6206c3fb27SDimitry Andric if (!ARanges) { 6306c3fb27SDimitry Andric llvm::consumeError(ARanges.takeError()); 6406c3fb27SDimitry Andric continue; 6506c3fb27SDimitry Andric } 6606c3fb27SDimitry Andric 67fcaf7f86SDimitry Andric for (auto &Range : *ARanges) { 68fcaf7f86SDimitry Andric if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(), 6906c3fb27SDimitry Andric Options.Tombstone, CU->getAddressByteSize())) { 7006c3fb27SDimitry Andric HasValidAddressRanges = true; 7106c3fb27SDimitry Andric break; 72fcaf7f86SDimitry Andric } 73fcaf7f86SDimitry Andric } 7406c3fb27SDimitry Andric 7506c3fb27SDimitry Andric if (HasValidAddressRanges) 7606c3fb27SDimitry Andric break; 77fcaf7f86SDimitry Andric } 78fcaf7f86SDimitry Andric } 79fcaf7f86SDimitry Andric 80fcaf7f86SDimitry Andric // should be renamed into has valid address ranges 8106c3fb27SDimitry Andric bool hasValidRelocs() override { return HasValidAddressRanges; } 82fcaf7f86SDimitry Andric 837a6dacacSDimitry Andric std::optional<int64_t> getSubprogramRelocAdjustment(const DWARFDie &DIE, 847a6dacacSDimitry Andric bool Verbose) 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, 9306c3fb27SDimitry Andric DIE.getDwarfUnit()->getAddressByteSize())) 9406c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 9506c3fb27SDimitry Andric return 0; 96fcaf7f86SDimitry Andric } 97fcaf7f86SDimitry Andric 9806c3fb27SDimitry Andric return std::nullopt; 99fcaf7f86SDimitry Andric } 100fcaf7f86SDimitry Andric 1015f757f3fSDimitry Andric std::optional<int64_t> 1025f757f3fSDimitry Andric getExprOpAddressRelocAdjustment(DWARFUnit &U, 1035f757f3fSDimitry Andric const DWARFExpression::Operation &Op, 1047a6dacacSDimitry Andric uint64_t, uint64_t, bool Verbose) override { 10506c3fb27SDimitry Andric switch (Op.getCode()) { 10606c3fb27SDimitry Andric default: { 10706c3fb27SDimitry Andric assert(false && "Specified operation does not have address operand"); 10806c3fb27SDimitry Andric } break; 1095f757f3fSDimitry Andric case dwarf::DW_OP_const2u: 11006c3fb27SDimitry Andric case dwarf::DW_OP_const4u: 11106c3fb27SDimitry Andric case dwarf::DW_OP_const8u: 1125f757f3fSDimitry Andric case dwarf::DW_OP_const2s: 11306c3fb27SDimitry Andric case dwarf::DW_OP_const4s: 11406c3fb27SDimitry Andric case dwarf::DW_OP_const8s: 11506c3fb27SDimitry Andric case dwarf::DW_OP_addr: { 11606c3fb27SDimitry Andric if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone, 11706c3fb27SDimitry Andric U.getAddressByteSize())) 11806c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 11906c3fb27SDimitry Andric return 0; 12006c3fb27SDimitry Andric } break; 12106c3fb27SDimitry Andric case dwarf::DW_OP_constx: 12206c3fb27SDimitry Andric case dwarf::DW_OP_addrx: { 12306c3fb27SDimitry Andric if (std::optional<object::SectionedAddress> Address = 12406c3fb27SDimitry Andric U.getAddrOffsetSectionItem(Op.getRawOperand(0))) { 12506c3fb27SDimitry Andric if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone, 12606c3fb27SDimitry Andric U.getAddressByteSize())) 12706c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 12806c3fb27SDimitry Andric return 0; 129fcaf7f86SDimitry Andric } 13006c3fb27SDimitry Andric } break; 131fcaf7f86SDimitry Andric } 132fcaf7f86SDimitry Andric 13306c3fb27SDimitry Andric return std::nullopt; 134fcaf7f86SDimitry Andric } 135fcaf7f86SDimitry Andric 1365f757f3fSDimitry Andric std::optional<StringRef> getLibraryInstallName() override { 1375f757f3fSDimitry Andric return std::nullopt; 1385f757f3fSDimitry Andric } 1395f757f3fSDimitry Andric 140fcaf7f86SDimitry Andric bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override { 141fcaf7f86SDimitry Andric // no need to apply relocations to the linked binary. 142fcaf7f86SDimitry Andric return false; 143fcaf7f86SDimitry Andric } 144fcaf7f86SDimitry Andric 1455f757f3fSDimitry Andric bool needToSaveValidRelocs() override { return false; } 1465f757f3fSDimitry Andric 1475f757f3fSDimitry Andric void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t, 1485f757f3fSDimitry Andric uint64_t) override {} 1495f757f3fSDimitry Andric 1505f757f3fSDimitry Andric void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset, 1515f757f3fSDimitry Andric uint64_t OutputUnitOffset) override {} 1525f757f3fSDimitry Andric 15306c3fb27SDimitry Andric void clear() override {} 154fcaf7f86SDimitry Andric 155fcaf7f86SDimitry Andric protected: 156fcaf7f86SDimitry Andric // returns true if specified address range is inside address ranges 157fcaf7f86SDimitry Andric // of executable sections. 158fcaf7f86SDimitry Andric bool isInsideExecutableSectionsAddressRange(uint64_t LowPC, 159bdd1243dSDimitry Andric std::optional<uint64_t> HighPC) { 160bdd1243dSDimitry Andric std::optional<AddressRange> Range = 161fcaf7f86SDimitry Andric TextAddressRanges.getRangeThatContains(LowPC); 162fcaf7f86SDimitry Andric 163fcaf7f86SDimitry Andric if (HighPC) 164fcaf7f86SDimitry Andric return Range.has_value() && Range->end() >= *HighPC; 165fcaf7f86SDimitry Andric 166fcaf7f86SDimitry Andric return Range.has_value(); 167fcaf7f86SDimitry Andric } 168fcaf7f86SDimitry Andric 169bdd1243dSDimitry Andric uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 170fcaf7f86SDimitry Andric uint16_t Version) { 171fcaf7f86SDimitry Andric if (LowPC == 0) 172fcaf7f86SDimitry Andric return true; 173fcaf7f86SDimitry Andric 174fcaf7f86SDimitry Andric if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1)) 175fcaf7f86SDimitry Andric return true; 176fcaf7f86SDimitry Andric 177fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 178fcaf7f86SDimitry Andric } 179fcaf7f86SDimitry Andric 180bdd1243dSDimitry Andric uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, 181bdd1243dSDimitry Andric std::optional<uint64_t> HighPC, 182fcaf7f86SDimitry Andric uint16_t Version, uint8_t AddressByteSize) { 183fcaf7f86SDimitry Andric if (Version <= 4 && HighPC) { 184fcaf7f86SDimitry Andric if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1)) 185fcaf7f86SDimitry Andric return true; 186fcaf7f86SDimitry Andric } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize)) 187fcaf7f86SDimitry Andric return true; 188fcaf7f86SDimitry Andric 189fcaf7f86SDimitry Andric if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC)) 190fcaf7f86SDimitry Andric warning("Address referencing invalid text section is not marked with " 191fcaf7f86SDimitry Andric "tombstone value"); 192fcaf7f86SDimitry Andric 193fcaf7f86SDimitry Andric return false; 194fcaf7f86SDimitry Andric } 195fcaf7f86SDimitry Andric 196bdd1243dSDimitry Andric bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 197fcaf7f86SDimitry Andric uint16_t Version, TombstoneKind Tombstone, 198fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 199fcaf7f86SDimitry Andric switch (Tombstone) { 200fcaf7f86SDimitry Andric case TombstoneKind::BFD: 201fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version); 202fcaf7f86SDimitry Andric case TombstoneKind::MaxPC: 203fcaf7f86SDimitry Andric return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 204fcaf7f86SDimitry Andric case TombstoneKind::Universal: 205fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version) || 206fcaf7f86SDimitry Andric isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 207fcaf7f86SDimitry Andric case TombstoneKind::Exec: 208fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 209fcaf7f86SDimitry Andric } 210fcaf7f86SDimitry Andric 211fcaf7f86SDimitry Andric llvm_unreachable("Unknown tombstone value"); 212fcaf7f86SDimitry Andric } 213fcaf7f86SDimitry Andric 214fcaf7f86SDimitry Andric bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone, 215fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 216bdd1243dSDimitry Andric return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone, 217bdd1243dSDimitry Andric AddressByteSize); 218fcaf7f86SDimitry Andric } 219fcaf7f86SDimitry Andric 220fcaf7f86SDimitry Andric private: 221fcaf7f86SDimitry Andric AddressRanges TextAddressRanges; 222fcaf7f86SDimitry Andric const Options &Opts; 22306c3fb27SDimitry Andric bool HasValidAddressRanges = false; 224fcaf7f86SDimitry Andric }; 225fcaf7f86SDimitry Andric 226972a253aSDimitry Andric static bool knownByDWARFUtil(StringRef SecName) { 227972a253aSDimitry Andric return llvm::StringSwitch<bool>(SecName) 228972a253aSDimitry Andric .Case(".debug_info", true) 229972a253aSDimitry Andric .Case(".debug_types", true) 230972a253aSDimitry Andric .Case(".debug_abbrev", true) 231972a253aSDimitry Andric .Case(".debug_loc", true) 232972a253aSDimitry Andric .Case(".debug_loclists", true) 233972a253aSDimitry Andric .Case(".debug_frame", true) 234972a253aSDimitry Andric .Case(".debug_aranges", true) 235972a253aSDimitry Andric .Case(".debug_ranges", true) 236972a253aSDimitry Andric .Case(".debug_rnglists", true) 237972a253aSDimitry Andric .Case(".debug_line", true) 238972a253aSDimitry Andric .Case(".debug_line_str", true) 239972a253aSDimitry Andric .Case(".debug_addr", true) 240972a253aSDimitry Andric .Case(".debug_macro", true) 241972a253aSDimitry Andric .Case(".debug_macinfo", true) 242972a253aSDimitry Andric .Case(".debug_str", true) 243972a253aSDimitry Andric .Case(".debug_str_offsets", true) 244bdd1243dSDimitry Andric .Case(".debug_pubnames", true) 245bdd1243dSDimitry Andric .Case(".debug_pubtypes", true) 246bdd1243dSDimitry Andric .Case(".debug_names", true) 247972a253aSDimitry Andric .Default(false); 248972a253aSDimitry Andric } 249972a253aSDimitry Andric 25006c3fb27SDimitry Andric template <typename AccelTableKind> 25106c3fb27SDimitry Andric static std::optional<AccelTableKind> 252bdd1243dSDimitry Andric getAcceleratorTableKind(StringRef SecName) { 25306c3fb27SDimitry Andric return llvm::StringSwitch<std::optional<AccelTableKind>>(SecName) 25406c3fb27SDimitry Andric .Case(".debug_pubnames", AccelTableKind::Pub) 25506c3fb27SDimitry Andric .Case(".debug_pubtypes", AccelTableKind::Pub) 25606c3fb27SDimitry Andric .Case(".debug_names", AccelTableKind::DebugNames) 257bdd1243dSDimitry Andric .Default(std::nullopt); 258bdd1243dSDimitry Andric } 259bdd1243dSDimitry Andric 260bdd1243dSDimitry Andric static std::string getMessageForReplacedAcceleratorTables( 261bdd1243dSDimitry Andric SmallVector<StringRef> &AccelTableNamesToReplace, 262bdd1243dSDimitry Andric DwarfUtilAccelKind TargetTable) { 263bdd1243dSDimitry Andric std::string Message; 264bdd1243dSDimitry Andric 265bdd1243dSDimitry Andric Message += "'"; 266bdd1243dSDimitry Andric for (StringRef Name : AccelTableNamesToReplace) { 267bdd1243dSDimitry Andric if (Message.size() > 1) 268bdd1243dSDimitry Andric Message += ", "; 269bdd1243dSDimitry Andric Message += Name; 270bdd1243dSDimitry Andric } 271bdd1243dSDimitry Andric 272bdd1243dSDimitry Andric Message += "' will be replaced with requested "; 273bdd1243dSDimitry Andric 274bdd1243dSDimitry Andric switch (TargetTable) { 275bdd1243dSDimitry Andric case DwarfUtilAccelKind::DWARF: 276bdd1243dSDimitry Andric Message += ".debug_names table"; 277bdd1243dSDimitry Andric break; 278bdd1243dSDimitry Andric 279bdd1243dSDimitry Andric default: 280bdd1243dSDimitry Andric assert(false); 281bdd1243dSDimitry Andric } 282bdd1243dSDimitry Andric 283bdd1243dSDimitry Andric return Message; 284bdd1243dSDimitry Andric } 285bdd1243dSDimitry Andric 286bdd1243dSDimitry Andric static std::string getMessageForDeletedAcceleratorTables( 287bdd1243dSDimitry Andric SmallVector<StringRef> &AccelTableNamesToReplace) { 288bdd1243dSDimitry Andric std::string Message; 289bdd1243dSDimitry Andric 290bdd1243dSDimitry Andric Message += "'"; 291bdd1243dSDimitry Andric for (StringRef Name : AccelTableNamesToReplace) { 292bdd1243dSDimitry Andric if (Message.size() > 1) 293bdd1243dSDimitry Andric Message += ", "; 294bdd1243dSDimitry Andric Message += Name; 295bdd1243dSDimitry Andric } 296bdd1243dSDimitry Andric 297bdd1243dSDimitry Andric Message += "' will be deleted as no accelerator tables are requested"; 298bdd1243dSDimitry Andric 299bdd1243dSDimitry Andric return Message; 300bdd1243dSDimitry Andric } 301bdd1243dSDimitry Andric 3021db9f3b2SDimitry Andric template <typename Linker> 30306c3fb27SDimitry Andric Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, 304fcaf7f86SDimitry Andric raw_pwrite_stream &OutStream) { 3055f757f3fSDimitry Andric std::mutex ErrorHandlerMutex; 3065f757f3fSDimitry Andric 307fcaf7f86SDimitry Andric auto ReportWarn = [&](const Twine &Message, StringRef Context, 308fcaf7f86SDimitry Andric const DWARFDie *Die) { 3095f757f3fSDimitry Andric // FIXME: implement warning logging which does not block other threads. 3105f757f3fSDimitry Andric if (!ErrorHandlerMutex.try_lock()) 311fcaf7f86SDimitry Andric return; 312fcaf7f86SDimitry Andric 3135f757f3fSDimitry Andric warning(Message, Context); 3145f757f3fSDimitry Andric if (Options.Verbose && Die) { 315fcaf7f86SDimitry Andric DIDumpOptions DumpOpts; 316fcaf7f86SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 317fcaf7f86SDimitry Andric DumpOpts.Verbose = Options.Verbose; 318fcaf7f86SDimitry Andric 319fcaf7f86SDimitry Andric WithColor::note() << " in DIE:\n"; 320fcaf7f86SDimitry Andric Die->dump(errs(), /*Indent=*/6, DumpOpts); 3215f757f3fSDimitry Andric } 3225f757f3fSDimitry Andric ErrorHandlerMutex.unlock(); 323fcaf7f86SDimitry Andric }; 324fcaf7f86SDimitry Andric auto ReportErr = [&](const Twine &Message, StringRef Context, 325fcaf7f86SDimitry Andric const DWARFDie *) { 3265f757f3fSDimitry Andric // FIXME: implement error logging which does not block other threads. 3275f757f3fSDimitry Andric if (!ErrorHandlerMutex.try_lock()) 3285f757f3fSDimitry Andric return; 3295f757f3fSDimitry Andric 330fcaf7f86SDimitry Andric WithColor::error(errs(), Context) << Message << '\n'; 3315f757f3fSDimitry Andric ErrorHandlerMutex.unlock(); 332fcaf7f86SDimitry Andric }; 333fcaf7f86SDimitry Andric 334fcaf7f86SDimitry Andric // Create DWARF linker. 33506c3fb27SDimitry Andric std::unique_ptr<Linker> DebugInfoLinker = 33606c3fb27SDimitry Andric Linker::createLinker(ReportErr, ReportWarn); 337fcaf7f86SDimitry Andric 33806c3fb27SDimitry Andric Triple TargetTriple = File.makeTriple(); 3397a6dacacSDimitry Andric std::unique_ptr<classic::DwarfStreamer> Streamer; 3407a6dacacSDimitry Andric if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr = 341*0fca6ea1SDimitry Andric classic::DwarfStreamer::createStreamer(TargetTriple, 342*0fca6ea1SDimitry Andric Linker::OutputFileType::Object, 343*0fca6ea1SDimitry Andric OutStream, ReportWarn)) 3447a6dacacSDimitry Andric Streamer = std::move(*StreamerOrErr); 3457a6dacacSDimitry Andric else 3467a6dacacSDimitry Andric return StreamerOrErr.takeError(); 3477a6dacacSDimitry Andric 3487a6dacacSDimitry Andric if constexpr (std::is_same<Linker, 3497a6dacacSDimitry Andric dwarf_linker::parallel::DWARFLinker>::value) { 3507a6dacacSDimitry Andric DebugInfoLinker->setOutputDWARFHandler( 3517a6dacacSDimitry Andric TargetTriple, 3527a6dacacSDimitry Andric [&](std::shared_ptr<dwarf_linker::parallel::SectionDescriptorBase> 3537a6dacacSDimitry Andric Section) { 3547a6dacacSDimitry Andric Streamer->emitSectionContents(Section->getContents(), 3557a6dacacSDimitry Andric Section->getKind()); 3567a6dacacSDimitry Andric }); 3577a6dacacSDimitry Andric } else 3587a6dacacSDimitry Andric DebugInfoLinker->setOutputDWARFEmitter(Streamer.get()); 359fcaf7f86SDimitry Andric 36006c3fb27SDimitry Andric DebugInfoLinker->setEstimatedObjfilesAmount(1); 36106c3fb27SDimitry Andric DebugInfoLinker->setNumThreads(Options.NumThreads); 36206c3fb27SDimitry Andric DebugInfoLinker->setNoODR(!Options.DoODRDeduplication); 36306c3fb27SDimitry Andric DebugInfoLinker->setVerbosity(Options.Verbose); 36406c3fb27SDimitry Andric DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection); 36506c3fb27SDimitry Andric 3661db9f3b2SDimitry Andric std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1); 367fcaf7f86SDimitry Andric 368fcaf7f86SDimitry Andric // Add object files to the DWARFLinker. 3695f757f3fSDimitry Andric std::unique_ptr<DWARFContext> Context = DWARFContext::create( 3705f757f3fSDimitry Andric File, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", 3715f757f3fSDimitry Andric [&](Error Err) { 3725f757f3fSDimitry Andric handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) { 3735f757f3fSDimitry Andric ReportErr(Info.message(), "", nullptr); 3745f757f3fSDimitry Andric }); 3755f757f3fSDimitry Andric }, 3765f757f3fSDimitry Andric [&](Error Warning) { 3775f757f3fSDimitry Andric handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) { 3785f757f3fSDimitry Andric ReportWarn(Info.message(), "", nullptr); 3795f757f3fSDimitry Andric }); 3805f757f3fSDimitry Andric }); 3811db9f3b2SDimitry Andric std::unique_ptr<ObjFileAddressMap> AddressesMap( 3821db9f3b2SDimitry Andric std::make_unique<ObjFileAddressMap>(*Context, Options, File)); 383fcaf7f86SDimitry Andric 3841db9f3b2SDimitry Andric ObjectsForLinking[0] = std::make_unique<DWARFFile>( 3855f757f3fSDimitry Andric File.getFileName(), std::move(Context), std::move(AddressesMap)); 386fcaf7f86SDimitry Andric 387bdd1243dSDimitry Andric uint16_t MaxDWARFVersion = 0; 388bdd1243dSDimitry Andric std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded = 389bdd1243dSDimitry Andric [&MaxDWARFVersion](const DWARFUnit &Unit) { 390bdd1243dSDimitry Andric MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); 391bdd1243dSDimitry Andric }; 392bdd1243dSDimitry Andric 393fcaf7f86SDimitry Andric for (size_t I = 0; I < ObjectsForLinking.size(); I++) 39406c3fb27SDimitry Andric DebugInfoLinker->addObjectFile(*ObjectsForLinking[I], nullptr, 395bdd1243dSDimitry Andric OnCUDieLoaded); 396bdd1243dSDimitry Andric 397bdd1243dSDimitry Andric // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. 398bdd1243dSDimitry Andric if (MaxDWARFVersion == 0) 399bdd1243dSDimitry Andric MaxDWARFVersion = 3; 400bdd1243dSDimitry Andric 40106c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->setTargetDWARFVersion(MaxDWARFVersion)) 402bdd1243dSDimitry Andric return Err; 403bdd1243dSDimitry Andric 40406c3fb27SDimitry Andric SmallVector<typename Linker::AccelTableKind> AccelTables; 405bdd1243dSDimitry Andric 406bdd1243dSDimitry Andric switch (Options.AccelTableKind) { 407bdd1243dSDimitry Andric case DwarfUtilAccelKind::None: 408bdd1243dSDimitry Andric // Nothing to do. 409bdd1243dSDimitry Andric break; 410bdd1243dSDimitry Andric case DwarfUtilAccelKind::DWARF: 411bdd1243dSDimitry Andric // use .debug_names for all DWARF versions. 41206c3fb27SDimitry Andric AccelTables.push_back(Linker::AccelTableKind::DebugNames); 413bdd1243dSDimitry Andric break; 414bdd1243dSDimitry Andric } 415bdd1243dSDimitry Andric 416bdd1243dSDimitry Andric // Add accelerator tables to DWARFLinker. 41706c3fb27SDimitry Andric for (typename Linker::AccelTableKind Table : AccelTables) 41806c3fb27SDimitry Andric DebugInfoLinker->addAccelTableKind(Table); 419bdd1243dSDimitry Andric 4201db9f3b2SDimitry Andric for (std::unique_ptr<DWARFFile> &CurFile : ObjectsForLinking) { 421bdd1243dSDimitry Andric SmallVector<StringRef> AccelTableNamesToReplace; 422bdd1243dSDimitry Andric SmallVector<StringRef> AccelTableNamesToDelete; 423bdd1243dSDimitry Andric 424bdd1243dSDimitry Andric // Unknown debug sections or non-requested accelerator sections would be 425bdd1243dSDimitry Andric // removed. Display warning for such sections. 42606c3fb27SDimitry Andric for (SectionName Sec : CurFile->Dwarf->getDWARFObj().getSectionNames()) { 427bdd1243dSDimitry Andric if (isDebugSection(Sec.Name)) { 42806c3fb27SDimitry Andric std::optional<typename Linker::AccelTableKind> SrcAccelTableKind = 42906c3fb27SDimitry Andric getAcceleratorTableKind<typename Linker::AccelTableKind>(Sec.Name); 430bdd1243dSDimitry Andric 431bdd1243dSDimitry Andric if (SrcAccelTableKind) { 432bdd1243dSDimitry Andric assert(knownByDWARFUtil(Sec.Name)); 433bdd1243dSDimitry Andric 434bdd1243dSDimitry Andric if (Options.AccelTableKind == DwarfUtilAccelKind::None) 435bdd1243dSDimitry Andric AccelTableNamesToDelete.push_back(Sec.Name); 43606c3fb27SDimitry Andric else if (!llvm::is_contained(AccelTables, *SrcAccelTableKind)) 437bdd1243dSDimitry Andric AccelTableNamesToReplace.push_back(Sec.Name); 438bdd1243dSDimitry Andric } else if (!knownByDWARFUtil(Sec.Name)) { 439bdd1243dSDimitry Andric assert(!SrcAccelTableKind); 440bdd1243dSDimitry Andric warning( 44106c3fb27SDimitry Andric formatv( 44206c3fb27SDimitry Andric "'{0}' is not currently supported: section will be skipped", 443bdd1243dSDimitry Andric Sec.Name), 444bdd1243dSDimitry Andric Options.InputFileName); 445bdd1243dSDimitry Andric } 446bdd1243dSDimitry Andric } 447bdd1243dSDimitry Andric } 448bdd1243dSDimitry Andric 449bdd1243dSDimitry Andric // Display message for the replaced accelerator tables. 450bdd1243dSDimitry Andric if (!AccelTableNamesToReplace.empty()) 451bdd1243dSDimitry Andric warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace, 452bdd1243dSDimitry Andric Options.AccelTableKind), 453bdd1243dSDimitry Andric Options.InputFileName); 454bdd1243dSDimitry Andric 455bdd1243dSDimitry Andric // Display message for the removed accelerator tables. 456bdd1243dSDimitry Andric if (!AccelTableNamesToDelete.empty()) 457bdd1243dSDimitry Andric warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete), 458bdd1243dSDimitry Andric Options.InputFileName); 45906c3fb27SDimitry Andric } 460fcaf7f86SDimitry Andric 461fcaf7f86SDimitry Andric // Link debug info. 46206c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->link()) 463972a253aSDimitry Andric return Err; 464972a253aSDimitry Andric 4657a6dacacSDimitry Andric Streamer->finish(); 466972a253aSDimitry Andric return Error::success(); 467fcaf7f86SDimitry Andric } 468fcaf7f86SDimitry Andric 46906c3fb27SDimitry Andric Error linkDebugInfo(object::ObjectFile &File, const Options &Options, 47006c3fb27SDimitry Andric raw_pwrite_stream &OutStream) { 4717a6dacacSDimitry Andric if (Options.UseDWARFLinkerParallel) 4721db9f3b2SDimitry Andric return linkDebugInfoImpl<parallel::DWARFLinker>(File, Options, OutStream); 47306c3fb27SDimitry Andric else 4741db9f3b2SDimitry Andric return linkDebugInfoImpl<classic::DWARFLinker>(File, Options, OutStream); 47506c3fb27SDimitry Andric } 47606c3fb27SDimitry Andric 477fcaf7f86SDimitry Andric } // end of namespace dwarfutil 478fcaf7f86SDimitry Andric } // end of namespace llvm 479