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" 1406c3fb27SDimitry 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" 18fcaf7f86SDimitry Andric #include <memory> 19fcaf7f86SDimitry Andric #include <vector> 20fcaf7f86SDimitry Andric 21fcaf7f86SDimitry Andric namespace llvm { 22fcaf7f86SDimitry Andric namespace dwarfutil { 23fcaf7f86SDimitry Andric 24fcaf7f86SDimitry Andric // ObjFileAddressMap allows to check whether specified DIE referencing 25fcaf7f86SDimitry Andric // dead addresses. It uses tombstone values to determine dead addresses. 26fcaf7f86SDimitry Andric // The concrete values of tombstone constants were discussed in 27fcaf7f86SDimitry Andric // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825. 28fcaf7f86SDimitry Andric // So we use following values as indicators of dead addresses: 29fcaf7f86SDimitry Andric // 30fcaf7f86SDimitry Andric // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less)) 31fcaf7f86SDimitry Andric // or ([LowPC, HighPC] is not inside address ranges of .text sections). 32fcaf7f86SDimitry Andric // 33fcaf7f86SDimitry Andric // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less)) 34fcaf7f86SDimitry Andric // That value is assumed to be compatible with 35fcaf7f86SDimitry Andric // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1 36fcaf7f86SDimitry Andric // 37fcaf7f86SDimitry Andric // exec: [LowPC, HighPC] is not inside address ranges of .text sections 38fcaf7f86SDimitry Andric // 39fcaf7f86SDimitry Andric // universal: maxpc and bfd 4006c3fb27SDimitry Andric template <typename AddressMapBase> 4106c3fb27SDimitry Andric class ObjFileAddressMap : public AddressMapBase { 42fcaf7f86SDimitry Andric public: 43fcaf7f86SDimitry Andric ObjFileAddressMap(DWARFContext &Context, const Options &Options, 44fcaf7f86SDimitry Andric object::ObjectFile &ObjFile) 4506c3fb27SDimitry Andric : Opts(Options) { 46fcaf7f86SDimitry Andric // Remember addresses of existing text sections. 47fcaf7f86SDimitry Andric for (const object::SectionRef &Sect : ObjFile.sections()) { 48fcaf7f86SDimitry Andric if (!Sect.isText()) 49fcaf7f86SDimitry Andric continue; 50fcaf7f86SDimitry Andric const uint64_t Size = Sect.getSize(); 51fcaf7f86SDimitry Andric if (Size == 0) 52fcaf7f86SDimitry Andric continue; 53fcaf7f86SDimitry Andric const uint64_t StartAddr = Sect.getAddress(); 54fcaf7f86SDimitry Andric TextAddressRanges.insert({StartAddr, StartAddr + Size}); 55fcaf7f86SDimitry Andric } 56fcaf7f86SDimitry Andric 57fcaf7f86SDimitry Andric // Check CU address ranges for tombstone value. 58fcaf7f86SDimitry Andric for (std::unique_ptr<DWARFUnit> &CU : Context.compile_units()) { 59fcaf7f86SDimitry Andric Expected<llvm::DWARFAddressRangesVector> ARanges = 60fcaf7f86SDimitry Andric CU->getUnitDIE().getAddressRanges(); 6106c3fb27SDimitry Andric if (!ARanges) { 6206c3fb27SDimitry Andric llvm::consumeError(ARanges.takeError()); 6306c3fb27SDimitry Andric continue; 6406c3fb27SDimitry Andric } 6506c3fb27SDimitry Andric 66fcaf7f86SDimitry Andric for (auto &Range : *ARanges) { 67fcaf7f86SDimitry Andric if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(), 6806c3fb27SDimitry Andric Options.Tombstone, CU->getAddressByteSize())) { 6906c3fb27SDimitry Andric HasValidAddressRanges = true; 7006c3fb27SDimitry Andric break; 71fcaf7f86SDimitry Andric } 72fcaf7f86SDimitry Andric } 7306c3fb27SDimitry Andric 7406c3fb27SDimitry Andric if (HasValidAddressRanges) 7506c3fb27SDimitry Andric break; 76fcaf7f86SDimitry Andric } 77fcaf7f86SDimitry Andric } 78fcaf7f86SDimitry Andric 79fcaf7f86SDimitry Andric // should be renamed into has valid address ranges 8006c3fb27SDimitry Andric bool hasValidRelocs() override { return HasValidAddressRanges; } 81fcaf7f86SDimitry Andric 8206c3fb27SDimitry Andric std::optional<int64_t> 8306c3fb27SDimitry Andric getSubprogramRelocAdjustment(const DWARFDie &DIE) override { 84fcaf7f86SDimitry Andric assert((DIE.getTag() == dwarf::DW_TAG_subprogram || 85fcaf7f86SDimitry Andric DIE.getTag() == dwarf::DW_TAG_label) && 86fcaf7f86SDimitry Andric "Wrong type of input die"); 87fcaf7f86SDimitry Andric 88bdd1243dSDimitry Andric if (std::optional<uint64_t> LowPC = 89fcaf7f86SDimitry Andric dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) { 90fcaf7f86SDimitry Andric if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(), 91fcaf7f86SDimitry Andric Opts.Tombstone, 9206c3fb27SDimitry Andric DIE.getDwarfUnit()->getAddressByteSize())) 9306c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 9406c3fb27SDimitry Andric return 0; 95fcaf7f86SDimitry Andric } 96fcaf7f86SDimitry Andric 9706c3fb27SDimitry Andric return std::nullopt; 98fcaf7f86SDimitry Andric } 99fcaf7f86SDimitry Andric 100*5f757f3fSDimitry Andric std::optional<int64_t> 101*5f757f3fSDimitry Andric getExprOpAddressRelocAdjustment(DWARFUnit &U, 102*5f757f3fSDimitry Andric const DWARFExpression::Operation &Op, 103*5f757f3fSDimitry Andric uint64_t, uint64_t) override { 10406c3fb27SDimitry Andric switch (Op.getCode()) { 10506c3fb27SDimitry Andric default: { 10606c3fb27SDimitry Andric assert(false && "Specified operation does not have address operand"); 10706c3fb27SDimitry Andric } break; 108*5f757f3fSDimitry Andric case dwarf::DW_OP_const2u: 10906c3fb27SDimitry Andric case dwarf::DW_OP_const4u: 11006c3fb27SDimitry Andric case dwarf::DW_OP_const8u: 111*5f757f3fSDimitry Andric case dwarf::DW_OP_const2s: 11206c3fb27SDimitry Andric case dwarf::DW_OP_const4s: 11306c3fb27SDimitry Andric case dwarf::DW_OP_const8s: 11406c3fb27SDimitry Andric case dwarf::DW_OP_addr: { 11506c3fb27SDimitry Andric if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone, 11606c3fb27SDimitry Andric U.getAddressByteSize())) 11706c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 11806c3fb27SDimitry Andric return 0; 11906c3fb27SDimitry Andric } break; 12006c3fb27SDimitry Andric case dwarf::DW_OP_constx: 12106c3fb27SDimitry Andric case dwarf::DW_OP_addrx: { 12206c3fb27SDimitry Andric if (std::optional<object::SectionedAddress> Address = 12306c3fb27SDimitry Andric U.getAddrOffsetSectionItem(Op.getRawOperand(0))) { 12406c3fb27SDimitry Andric if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone, 12506c3fb27SDimitry Andric U.getAddressByteSize())) 12606c3fb27SDimitry Andric // Relocation value for the linked binary is 0. 12706c3fb27SDimitry Andric return 0; 128fcaf7f86SDimitry Andric } 12906c3fb27SDimitry Andric } break; 130fcaf7f86SDimitry Andric } 131fcaf7f86SDimitry Andric 13206c3fb27SDimitry Andric return std::nullopt; 133fcaf7f86SDimitry Andric } 134fcaf7f86SDimitry Andric 135*5f757f3fSDimitry Andric std::optional<StringRef> getLibraryInstallName() override { 136*5f757f3fSDimitry Andric return std::nullopt; 137*5f757f3fSDimitry Andric } 138*5f757f3fSDimitry Andric 139fcaf7f86SDimitry Andric bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override { 140fcaf7f86SDimitry Andric // no need to apply relocations to the linked binary. 141fcaf7f86SDimitry Andric return false; 142fcaf7f86SDimitry Andric } 143fcaf7f86SDimitry Andric 144*5f757f3fSDimitry Andric bool needToSaveValidRelocs() override { return false; } 145*5f757f3fSDimitry Andric 146*5f757f3fSDimitry Andric void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t, 147*5f757f3fSDimitry Andric uint64_t) override {} 148*5f757f3fSDimitry Andric 149*5f757f3fSDimitry Andric void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset, 150*5f757f3fSDimitry Andric uint64_t OutputUnitOffset) override {} 151*5f757f3fSDimitry Andric 15206c3fb27SDimitry Andric void clear() override {} 153fcaf7f86SDimitry Andric 154fcaf7f86SDimitry Andric protected: 155fcaf7f86SDimitry Andric // returns true if specified address range is inside address ranges 156fcaf7f86SDimitry Andric // of executable sections. 157fcaf7f86SDimitry Andric bool isInsideExecutableSectionsAddressRange(uint64_t LowPC, 158bdd1243dSDimitry Andric std::optional<uint64_t> HighPC) { 159bdd1243dSDimitry Andric std::optional<AddressRange> Range = 160fcaf7f86SDimitry Andric TextAddressRanges.getRangeThatContains(LowPC); 161fcaf7f86SDimitry Andric 162fcaf7f86SDimitry Andric if (HighPC) 163fcaf7f86SDimitry Andric return Range.has_value() && Range->end() >= *HighPC; 164fcaf7f86SDimitry Andric 165fcaf7f86SDimitry Andric return Range.has_value(); 166fcaf7f86SDimitry Andric } 167fcaf7f86SDimitry Andric 168bdd1243dSDimitry Andric uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 169fcaf7f86SDimitry Andric uint16_t Version) { 170fcaf7f86SDimitry Andric if (LowPC == 0) 171fcaf7f86SDimitry Andric return true; 172fcaf7f86SDimitry Andric 173fcaf7f86SDimitry Andric if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1)) 174fcaf7f86SDimitry Andric return true; 175fcaf7f86SDimitry Andric 176fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 177fcaf7f86SDimitry Andric } 178fcaf7f86SDimitry Andric 179bdd1243dSDimitry Andric uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, 180bdd1243dSDimitry Andric std::optional<uint64_t> HighPC, 181fcaf7f86SDimitry Andric uint16_t Version, uint8_t AddressByteSize) { 182fcaf7f86SDimitry Andric if (Version <= 4 && HighPC) { 183fcaf7f86SDimitry Andric if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1)) 184fcaf7f86SDimitry Andric return true; 185fcaf7f86SDimitry Andric } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize)) 186fcaf7f86SDimitry Andric return true; 187fcaf7f86SDimitry Andric 188fcaf7f86SDimitry Andric if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC)) 189fcaf7f86SDimitry Andric warning("Address referencing invalid text section is not marked with " 190fcaf7f86SDimitry Andric "tombstone value"); 191fcaf7f86SDimitry Andric 192fcaf7f86SDimitry Andric return false; 193fcaf7f86SDimitry Andric } 194fcaf7f86SDimitry Andric 195bdd1243dSDimitry Andric bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 196fcaf7f86SDimitry Andric uint16_t Version, TombstoneKind Tombstone, 197fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 198fcaf7f86SDimitry Andric switch (Tombstone) { 199fcaf7f86SDimitry Andric case TombstoneKind::BFD: 200fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version); 201fcaf7f86SDimitry Andric case TombstoneKind::MaxPC: 202fcaf7f86SDimitry Andric return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 203fcaf7f86SDimitry Andric case TombstoneKind::Universal: 204fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version) || 205fcaf7f86SDimitry Andric isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 206fcaf7f86SDimitry Andric case TombstoneKind::Exec: 207fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 208fcaf7f86SDimitry Andric } 209fcaf7f86SDimitry Andric 210fcaf7f86SDimitry Andric llvm_unreachable("Unknown tombstone value"); 211fcaf7f86SDimitry Andric } 212fcaf7f86SDimitry Andric 213fcaf7f86SDimitry Andric bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone, 214fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 215bdd1243dSDimitry Andric return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone, 216bdd1243dSDimitry Andric AddressByteSize); 217fcaf7f86SDimitry Andric } 218fcaf7f86SDimitry Andric 219fcaf7f86SDimitry Andric private: 220fcaf7f86SDimitry Andric AddressRanges TextAddressRanges; 221fcaf7f86SDimitry Andric const Options &Opts; 22206c3fb27SDimitry Andric bool HasValidAddressRanges = false; 223fcaf7f86SDimitry Andric }; 224fcaf7f86SDimitry Andric 225972a253aSDimitry Andric static bool knownByDWARFUtil(StringRef SecName) { 226972a253aSDimitry Andric return llvm::StringSwitch<bool>(SecName) 227972a253aSDimitry Andric .Case(".debug_info", true) 228972a253aSDimitry Andric .Case(".debug_types", true) 229972a253aSDimitry Andric .Case(".debug_abbrev", true) 230972a253aSDimitry Andric .Case(".debug_loc", true) 231972a253aSDimitry Andric .Case(".debug_loclists", true) 232972a253aSDimitry Andric .Case(".debug_frame", true) 233972a253aSDimitry Andric .Case(".debug_aranges", true) 234972a253aSDimitry Andric .Case(".debug_ranges", true) 235972a253aSDimitry Andric .Case(".debug_rnglists", true) 236972a253aSDimitry Andric .Case(".debug_line", true) 237972a253aSDimitry Andric .Case(".debug_line_str", true) 238972a253aSDimitry Andric .Case(".debug_addr", true) 239972a253aSDimitry Andric .Case(".debug_macro", true) 240972a253aSDimitry Andric .Case(".debug_macinfo", true) 241972a253aSDimitry Andric .Case(".debug_str", true) 242972a253aSDimitry Andric .Case(".debug_str_offsets", true) 243bdd1243dSDimitry Andric .Case(".debug_pubnames", true) 244bdd1243dSDimitry Andric .Case(".debug_pubtypes", true) 245bdd1243dSDimitry Andric .Case(".debug_names", true) 246972a253aSDimitry Andric .Default(false); 247972a253aSDimitry Andric } 248972a253aSDimitry Andric 24906c3fb27SDimitry Andric template <typename AccelTableKind> 25006c3fb27SDimitry Andric static std::optional<AccelTableKind> 251bdd1243dSDimitry Andric getAcceleratorTableKind(StringRef SecName) { 25206c3fb27SDimitry Andric return llvm::StringSwitch<std::optional<AccelTableKind>>(SecName) 25306c3fb27SDimitry Andric .Case(".debug_pubnames", AccelTableKind::Pub) 25406c3fb27SDimitry Andric .Case(".debug_pubtypes", AccelTableKind::Pub) 25506c3fb27SDimitry Andric .Case(".debug_names", AccelTableKind::DebugNames) 256bdd1243dSDimitry Andric .Default(std::nullopt); 257bdd1243dSDimitry Andric } 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric static std::string getMessageForReplacedAcceleratorTables( 260bdd1243dSDimitry Andric SmallVector<StringRef> &AccelTableNamesToReplace, 261bdd1243dSDimitry Andric DwarfUtilAccelKind TargetTable) { 262bdd1243dSDimitry Andric std::string Message; 263bdd1243dSDimitry Andric 264bdd1243dSDimitry Andric Message += "'"; 265bdd1243dSDimitry Andric for (StringRef Name : AccelTableNamesToReplace) { 266bdd1243dSDimitry Andric if (Message.size() > 1) 267bdd1243dSDimitry Andric Message += ", "; 268bdd1243dSDimitry Andric Message += Name; 269bdd1243dSDimitry Andric } 270bdd1243dSDimitry Andric 271bdd1243dSDimitry Andric Message += "' will be replaced with requested "; 272bdd1243dSDimitry Andric 273bdd1243dSDimitry Andric switch (TargetTable) { 274bdd1243dSDimitry Andric case DwarfUtilAccelKind::DWARF: 275bdd1243dSDimitry Andric Message += ".debug_names table"; 276bdd1243dSDimitry Andric break; 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric default: 279bdd1243dSDimitry Andric assert(false); 280bdd1243dSDimitry Andric } 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric return Message; 283bdd1243dSDimitry Andric } 284bdd1243dSDimitry Andric 285bdd1243dSDimitry Andric static std::string getMessageForDeletedAcceleratorTables( 286bdd1243dSDimitry Andric SmallVector<StringRef> &AccelTableNamesToReplace) { 287bdd1243dSDimitry Andric std::string Message; 288bdd1243dSDimitry Andric 289bdd1243dSDimitry Andric Message += "'"; 290bdd1243dSDimitry Andric for (StringRef Name : AccelTableNamesToReplace) { 291bdd1243dSDimitry Andric if (Message.size() > 1) 292bdd1243dSDimitry Andric Message += ", "; 293bdd1243dSDimitry Andric Message += Name; 294bdd1243dSDimitry Andric } 295bdd1243dSDimitry Andric 296bdd1243dSDimitry Andric Message += "' will be deleted as no accelerator tables are requested"; 297bdd1243dSDimitry Andric 298bdd1243dSDimitry Andric return Message; 299bdd1243dSDimitry Andric } 300bdd1243dSDimitry Andric 30106c3fb27SDimitry Andric template <typename Linker, typename OutDwarfFile, typename AddressMapBase> 30206c3fb27SDimitry Andric Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, 303fcaf7f86SDimitry Andric raw_pwrite_stream &OutStream) { 304*5f757f3fSDimitry Andric std::mutex ErrorHandlerMutex; 305*5f757f3fSDimitry Andric 306fcaf7f86SDimitry Andric auto ReportWarn = [&](const Twine &Message, StringRef Context, 307fcaf7f86SDimitry Andric const DWARFDie *Die) { 308*5f757f3fSDimitry Andric // FIXME: implement warning logging which does not block other threads. 309*5f757f3fSDimitry Andric if (!ErrorHandlerMutex.try_lock()) 310fcaf7f86SDimitry Andric return; 311fcaf7f86SDimitry Andric 312*5f757f3fSDimitry Andric warning(Message, Context); 313*5f757f3fSDimitry Andric if (Options.Verbose && Die) { 314fcaf7f86SDimitry Andric DIDumpOptions DumpOpts; 315fcaf7f86SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 316fcaf7f86SDimitry Andric DumpOpts.Verbose = Options.Verbose; 317fcaf7f86SDimitry Andric 318fcaf7f86SDimitry Andric WithColor::note() << " in DIE:\n"; 319fcaf7f86SDimitry Andric Die->dump(errs(), /*Indent=*/6, DumpOpts); 320*5f757f3fSDimitry Andric } 321*5f757f3fSDimitry Andric ErrorHandlerMutex.unlock(); 322fcaf7f86SDimitry Andric }; 323fcaf7f86SDimitry Andric auto ReportErr = [&](const Twine &Message, StringRef Context, 324fcaf7f86SDimitry Andric const DWARFDie *) { 325*5f757f3fSDimitry Andric // FIXME: implement error logging which does not block other threads. 326*5f757f3fSDimitry Andric if (!ErrorHandlerMutex.try_lock()) 327*5f757f3fSDimitry Andric return; 328*5f757f3fSDimitry Andric 329fcaf7f86SDimitry Andric WithColor::error(errs(), Context) << Message << '\n'; 330*5f757f3fSDimitry Andric ErrorHandlerMutex.unlock(); 331fcaf7f86SDimitry Andric }; 332fcaf7f86SDimitry Andric 333fcaf7f86SDimitry Andric // Create DWARF linker. 33406c3fb27SDimitry Andric std::unique_ptr<Linker> DebugInfoLinker = 33506c3fb27SDimitry Andric Linker::createLinker(ReportErr, ReportWarn); 336fcaf7f86SDimitry Andric 33706c3fb27SDimitry Andric Triple TargetTriple = File.makeTriple(); 33806c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->createEmitter( 33906c3fb27SDimitry Andric TargetTriple, Linker::OutputFileType::Object, OutStream)) 34006c3fb27SDimitry Andric return Err; 341fcaf7f86SDimitry Andric 34206c3fb27SDimitry Andric DebugInfoLinker->setEstimatedObjfilesAmount(1); 34306c3fb27SDimitry Andric DebugInfoLinker->setNumThreads(Options.NumThreads); 34406c3fb27SDimitry Andric DebugInfoLinker->setNoODR(!Options.DoODRDeduplication); 34506c3fb27SDimitry Andric DebugInfoLinker->setVerbosity(Options.Verbose); 34606c3fb27SDimitry Andric DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection); 34706c3fb27SDimitry Andric 34806c3fb27SDimitry Andric std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking(1); 349fcaf7f86SDimitry Andric 350fcaf7f86SDimitry Andric // Add object files to the DWARFLinker. 351*5f757f3fSDimitry Andric std::unique_ptr<DWARFContext> Context = DWARFContext::create( 352*5f757f3fSDimitry Andric File, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", 353*5f757f3fSDimitry Andric [&](Error Err) { 354*5f757f3fSDimitry Andric handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) { 355*5f757f3fSDimitry Andric ReportErr(Info.message(), "", nullptr); 356*5f757f3fSDimitry Andric }); 357*5f757f3fSDimitry Andric }, 358*5f757f3fSDimitry Andric [&](Error Warning) { 359*5f757f3fSDimitry Andric handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) { 360*5f757f3fSDimitry Andric ReportWarn(Info.message(), "", nullptr); 361*5f757f3fSDimitry Andric }); 362*5f757f3fSDimitry Andric }); 36306c3fb27SDimitry Andric std::unique_ptr<ObjFileAddressMap<AddressMapBase>> AddressesMap( 36406c3fb27SDimitry Andric std::make_unique<ObjFileAddressMap<AddressMapBase>>(*Context, Options, 36506c3fb27SDimitry Andric File)); 366fcaf7f86SDimitry Andric 367*5f757f3fSDimitry Andric ObjectsForLinking[0] = std::make_unique<OutDwarfFile>( 368*5f757f3fSDimitry Andric File.getFileName(), std::move(Context), std::move(AddressesMap)); 369fcaf7f86SDimitry Andric 370bdd1243dSDimitry Andric uint16_t MaxDWARFVersion = 0; 371bdd1243dSDimitry Andric std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded = 372bdd1243dSDimitry Andric [&MaxDWARFVersion](const DWARFUnit &Unit) { 373bdd1243dSDimitry Andric MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); 374bdd1243dSDimitry Andric }; 375bdd1243dSDimitry Andric 376fcaf7f86SDimitry Andric for (size_t I = 0; I < ObjectsForLinking.size(); I++) 37706c3fb27SDimitry Andric DebugInfoLinker->addObjectFile(*ObjectsForLinking[I], nullptr, 378bdd1243dSDimitry Andric OnCUDieLoaded); 379bdd1243dSDimitry Andric 380bdd1243dSDimitry Andric // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. 381bdd1243dSDimitry Andric if (MaxDWARFVersion == 0) 382bdd1243dSDimitry Andric MaxDWARFVersion = 3; 383bdd1243dSDimitry Andric 38406c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->setTargetDWARFVersion(MaxDWARFVersion)) 385bdd1243dSDimitry Andric return Err; 386bdd1243dSDimitry Andric 38706c3fb27SDimitry Andric SmallVector<typename Linker::AccelTableKind> AccelTables; 388bdd1243dSDimitry Andric 389bdd1243dSDimitry Andric switch (Options.AccelTableKind) { 390bdd1243dSDimitry Andric case DwarfUtilAccelKind::None: 391bdd1243dSDimitry Andric // Nothing to do. 392bdd1243dSDimitry Andric break; 393bdd1243dSDimitry Andric case DwarfUtilAccelKind::DWARF: 394bdd1243dSDimitry Andric // use .debug_names for all DWARF versions. 39506c3fb27SDimitry Andric AccelTables.push_back(Linker::AccelTableKind::DebugNames); 396bdd1243dSDimitry Andric break; 397bdd1243dSDimitry Andric } 398bdd1243dSDimitry Andric 399bdd1243dSDimitry Andric // Add accelerator tables to DWARFLinker. 40006c3fb27SDimitry Andric for (typename Linker::AccelTableKind Table : AccelTables) 40106c3fb27SDimitry Andric DebugInfoLinker->addAccelTableKind(Table); 402bdd1243dSDimitry Andric 40306c3fb27SDimitry Andric for (std::unique_ptr<OutDwarfFile> &CurFile : ObjectsForLinking) { 404bdd1243dSDimitry Andric SmallVector<StringRef> AccelTableNamesToReplace; 405bdd1243dSDimitry Andric SmallVector<StringRef> AccelTableNamesToDelete; 406bdd1243dSDimitry Andric 407bdd1243dSDimitry Andric // Unknown debug sections or non-requested accelerator sections would be 408bdd1243dSDimitry Andric // removed. Display warning for such sections. 40906c3fb27SDimitry Andric for (SectionName Sec : CurFile->Dwarf->getDWARFObj().getSectionNames()) { 410bdd1243dSDimitry Andric if (isDebugSection(Sec.Name)) { 41106c3fb27SDimitry Andric std::optional<typename Linker::AccelTableKind> SrcAccelTableKind = 41206c3fb27SDimitry Andric getAcceleratorTableKind<typename Linker::AccelTableKind>(Sec.Name); 413bdd1243dSDimitry Andric 414bdd1243dSDimitry Andric if (SrcAccelTableKind) { 415bdd1243dSDimitry Andric assert(knownByDWARFUtil(Sec.Name)); 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric if (Options.AccelTableKind == DwarfUtilAccelKind::None) 418bdd1243dSDimitry Andric AccelTableNamesToDelete.push_back(Sec.Name); 41906c3fb27SDimitry Andric else if (!llvm::is_contained(AccelTables, *SrcAccelTableKind)) 420bdd1243dSDimitry Andric AccelTableNamesToReplace.push_back(Sec.Name); 421bdd1243dSDimitry Andric } else if (!knownByDWARFUtil(Sec.Name)) { 422bdd1243dSDimitry Andric assert(!SrcAccelTableKind); 423bdd1243dSDimitry Andric warning( 42406c3fb27SDimitry Andric formatv( 42506c3fb27SDimitry Andric "'{0}' is not currently supported: section will be skipped", 426bdd1243dSDimitry Andric Sec.Name), 427bdd1243dSDimitry Andric Options.InputFileName); 428bdd1243dSDimitry Andric } 429bdd1243dSDimitry Andric } 430bdd1243dSDimitry Andric } 431bdd1243dSDimitry Andric 432bdd1243dSDimitry Andric // Display message for the replaced accelerator tables. 433bdd1243dSDimitry Andric if (!AccelTableNamesToReplace.empty()) 434bdd1243dSDimitry Andric warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace, 435bdd1243dSDimitry Andric Options.AccelTableKind), 436bdd1243dSDimitry Andric Options.InputFileName); 437bdd1243dSDimitry Andric 438bdd1243dSDimitry Andric // Display message for the removed accelerator tables. 439bdd1243dSDimitry Andric if (!AccelTableNamesToDelete.empty()) 440bdd1243dSDimitry Andric warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete), 441bdd1243dSDimitry Andric Options.InputFileName); 44206c3fb27SDimitry Andric } 443fcaf7f86SDimitry Andric 444fcaf7f86SDimitry Andric // Link debug info. 44506c3fb27SDimitry Andric if (Error Err = DebugInfoLinker->link()) 446972a253aSDimitry Andric return Err; 447972a253aSDimitry Andric 44806c3fb27SDimitry Andric DebugInfoLinker->getEmitter()->finish(); 449972a253aSDimitry Andric return Error::success(); 450fcaf7f86SDimitry Andric } 451fcaf7f86SDimitry Andric 45206c3fb27SDimitry Andric Error linkDebugInfo(object::ObjectFile &File, const Options &Options, 45306c3fb27SDimitry Andric raw_pwrite_stream &OutStream) { 45406c3fb27SDimitry Andric if (Options.UseLLVMDWARFLinker) 45506c3fb27SDimitry Andric return linkDebugInfoImpl<dwarflinker_parallel::DWARFLinker, 45606c3fb27SDimitry Andric dwarflinker_parallel::DWARFFile, 45706c3fb27SDimitry Andric dwarflinker_parallel::AddressesMap>(File, Options, 45806c3fb27SDimitry Andric OutStream); 45906c3fb27SDimitry Andric else 46006c3fb27SDimitry Andric return linkDebugInfoImpl<DWARFLinker, DWARFFile, AddressesMap>( 46106c3fb27SDimitry Andric File, Options, OutStream); 46206c3fb27SDimitry Andric } 46306c3fb27SDimitry Andric 464fcaf7f86SDimitry Andric } // end of namespace dwarfutil 465fcaf7f86SDimitry Andric } // end of namespace llvm 466