1*fcaf7f86SDimitry Andric //=== DebugInfoLinker.cpp -------------------------------------------------===// 2*fcaf7f86SDimitry Andric // 3*fcaf7f86SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*fcaf7f86SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*fcaf7f86SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*fcaf7f86SDimitry Andric // 7*fcaf7f86SDimitry Andric //===----------------------------------------------------------------------===// 8*fcaf7f86SDimitry Andric 9*fcaf7f86SDimitry Andric #include "DebugInfoLinker.h" 10*fcaf7f86SDimitry Andric #include "Error.h" 11*fcaf7f86SDimitry Andric #include "llvm/DWARFLinker/DWARFLinker.h" 12*fcaf7f86SDimitry Andric #include "llvm/DWARFLinker/DWARFStreamer.h" 13*fcaf7f86SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 14*fcaf7f86SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 15*fcaf7f86SDimitry Andric #include "llvm/Object/ObjectFile.h" 16*fcaf7f86SDimitry Andric #include <memory> 17*fcaf7f86SDimitry Andric #include <vector> 18*fcaf7f86SDimitry Andric 19*fcaf7f86SDimitry Andric namespace llvm { 20*fcaf7f86SDimitry Andric namespace dwarfutil { 21*fcaf7f86SDimitry Andric 22*fcaf7f86SDimitry Andric // ObjFileAddressMap allows to check whether specified DIE referencing 23*fcaf7f86SDimitry Andric // dead addresses. It uses tombstone values to determine dead addresses. 24*fcaf7f86SDimitry Andric // The concrete values of tombstone constants were discussed in 25*fcaf7f86SDimitry Andric // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825. 26*fcaf7f86SDimitry Andric // So we use following values as indicators of dead addresses: 27*fcaf7f86SDimitry Andric // 28*fcaf7f86SDimitry Andric // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less)) 29*fcaf7f86SDimitry Andric // or ([LowPC, HighPC] is not inside address ranges of .text sections). 30*fcaf7f86SDimitry Andric // 31*fcaf7f86SDimitry Andric // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less)) 32*fcaf7f86SDimitry Andric // That value is assumed to be compatible with 33*fcaf7f86SDimitry Andric // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1 34*fcaf7f86SDimitry Andric // 35*fcaf7f86SDimitry Andric // exec: [LowPC, HighPC] is not inside address ranges of .text sections 36*fcaf7f86SDimitry Andric // 37*fcaf7f86SDimitry Andric // universal: maxpc and bfd 38*fcaf7f86SDimitry Andric class ObjFileAddressMap : public AddressesMap { 39*fcaf7f86SDimitry Andric public: 40*fcaf7f86SDimitry Andric ObjFileAddressMap(DWARFContext &Context, const Options &Options, 41*fcaf7f86SDimitry Andric object::ObjectFile &ObjFile) 42*fcaf7f86SDimitry Andric : Opts(Options) { 43*fcaf7f86SDimitry Andric // Remember addresses of existing text sections. 44*fcaf7f86SDimitry Andric for (const object::SectionRef &Sect : ObjFile.sections()) { 45*fcaf7f86SDimitry Andric if (!Sect.isText()) 46*fcaf7f86SDimitry Andric continue; 47*fcaf7f86SDimitry Andric const uint64_t Size = Sect.getSize(); 48*fcaf7f86SDimitry Andric if (Size == 0) 49*fcaf7f86SDimitry Andric continue; 50*fcaf7f86SDimitry Andric const uint64_t StartAddr = Sect.getAddress(); 51*fcaf7f86SDimitry Andric TextAddressRanges.insert({StartAddr, StartAddr + Size}); 52*fcaf7f86SDimitry Andric } 53*fcaf7f86SDimitry Andric 54*fcaf7f86SDimitry Andric // Check CU address ranges for tombstone value. 55*fcaf7f86SDimitry Andric for (std::unique_ptr<DWARFUnit> &CU : Context.compile_units()) { 56*fcaf7f86SDimitry Andric Expected<llvm::DWARFAddressRangesVector> ARanges = 57*fcaf7f86SDimitry Andric CU->getUnitDIE().getAddressRanges(); 58*fcaf7f86SDimitry Andric if (ARanges) { 59*fcaf7f86SDimitry Andric for (auto &Range : *ARanges) { 60*fcaf7f86SDimitry Andric if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(), 61*fcaf7f86SDimitry Andric Options.Tombstone, CU->getAddressByteSize())) 62*fcaf7f86SDimitry Andric DWARFAddressRanges.insert({Range.LowPC, Range.HighPC}, 0); 63*fcaf7f86SDimitry Andric } 64*fcaf7f86SDimitry Andric } 65*fcaf7f86SDimitry Andric } 66*fcaf7f86SDimitry Andric } 67*fcaf7f86SDimitry Andric 68*fcaf7f86SDimitry Andric // should be renamed into has valid address ranges 69*fcaf7f86SDimitry Andric bool hasValidRelocs() override { return !DWARFAddressRanges.empty(); } 70*fcaf7f86SDimitry Andric 71*fcaf7f86SDimitry Andric bool isLiveSubprogram(const DWARFDie &DIE, 72*fcaf7f86SDimitry Andric CompileUnit::DIEInfo &Info) override { 73*fcaf7f86SDimitry Andric assert((DIE.getTag() == dwarf::DW_TAG_subprogram || 74*fcaf7f86SDimitry Andric DIE.getTag() == dwarf::DW_TAG_label) && 75*fcaf7f86SDimitry Andric "Wrong type of input die"); 76*fcaf7f86SDimitry Andric 77*fcaf7f86SDimitry Andric if (Optional<uint64_t> LowPC = 78*fcaf7f86SDimitry Andric dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) { 79*fcaf7f86SDimitry Andric if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(), 80*fcaf7f86SDimitry Andric Opts.Tombstone, 81*fcaf7f86SDimitry Andric DIE.getDwarfUnit()->getAddressByteSize())) { 82*fcaf7f86SDimitry Andric Info.AddrAdjust = 0; 83*fcaf7f86SDimitry Andric Info.InDebugMap = true; 84*fcaf7f86SDimitry Andric return true; 85*fcaf7f86SDimitry Andric } 86*fcaf7f86SDimitry Andric } 87*fcaf7f86SDimitry Andric 88*fcaf7f86SDimitry Andric return false; 89*fcaf7f86SDimitry Andric } 90*fcaf7f86SDimitry Andric 91*fcaf7f86SDimitry Andric bool isLiveVariable(const DWARFDie &DIE, 92*fcaf7f86SDimitry Andric CompileUnit::DIEInfo &Info) override { 93*fcaf7f86SDimitry Andric assert((DIE.getTag() == dwarf::DW_TAG_variable || 94*fcaf7f86SDimitry Andric DIE.getTag() == dwarf::DW_TAG_constant) && 95*fcaf7f86SDimitry Andric "Wrong type of input die"); 96*fcaf7f86SDimitry Andric 97*fcaf7f86SDimitry Andric if (Expected<DWARFLocationExpressionsVector> Loc = 98*fcaf7f86SDimitry Andric DIE.getLocations(dwarf::DW_AT_location)) { 99*fcaf7f86SDimitry Andric DWARFUnit *U = DIE.getDwarfUnit(); 100*fcaf7f86SDimitry Andric for (const auto &Entry : *Loc) { 101*fcaf7f86SDimitry Andric DataExtractor Data(toStringRef(Entry.Expr), 102*fcaf7f86SDimitry Andric U->getContext().isLittleEndian(), 0); 103*fcaf7f86SDimitry Andric DWARFExpression Expression(Data, U->getAddressByteSize(), 104*fcaf7f86SDimitry Andric U->getFormParams().Format); 105*fcaf7f86SDimitry Andric bool HasLiveAddresses = 106*fcaf7f86SDimitry Andric any_of(Expression, [&](const DWARFExpression::Operation &Op) { 107*fcaf7f86SDimitry Andric // TODO: add handling of dwarf::DW_OP_addrx 108*fcaf7f86SDimitry Andric return !Op.isError() && 109*fcaf7f86SDimitry Andric (Op.getCode() == dwarf::DW_OP_addr && 110*fcaf7f86SDimitry Andric !isDeadAddress(Op.getRawOperand(0), U->getVersion(), 111*fcaf7f86SDimitry Andric Opts.Tombstone, 112*fcaf7f86SDimitry Andric DIE.getDwarfUnit()->getAddressByteSize())); 113*fcaf7f86SDimitry Andric }); 114*fcaf7f86SDimitry Andric 115*fcaf7f86SDimitry Andric if (HasLiveAddresses) { 116*fcaf7f86SDimitry Andric Info.AddrAdjust = 0; 117*fcaf7f86SDimitry Andric Info.InDebugMap = true; 118*fcaf7f86SDimitry Andric return true; 119*fcaf7f86SDimitry Andric } 120*fcaf7f86SDimitry Andric } 121*fcaf7f86SDimitry Andric } else { 122*fcaf7f86SDimitry Andric // FIXME: missing DW_AT_location is OK here, but other errors should be 123*fcaf7f86SDimitry Andric // reported to the user. 124*fcaf7f86SDimitry Andric consumeError(Loc.takeError()); 125*fcaf7f86SDimitry Andric } 126*fcaf7f86SDimitry Andric 127*fcaf7f86SDimitry Andric return false; 128*fcaf7f86SDimitry Andric } 129*fcaf7f86SDimitry Andric 130*fcaf7f86SDimitry Andric bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override { 131*fcaf7f86SDimitry Andric // no need to apply relocations to the linked binary. 132*fcaf7f86SDimitry Andric return false; 133*fcaf7f86SDimitry Andric } 134*fcaf7f86SDimitry Andric 135*fcaf7f86SDimitry Andric RangesTy &getValidAddressRanges() override { return DWARFAddressRanges; }; 136*fcaf7f86SDimitry Andric 137*fcaf7f86SDimitry Andric void clear() override { DWARFAddressRanges.clear(); } 138*fcaf7f86SDimitry Andric 139*fcaf7f86SDimitry Andric llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t, uint64_t) override { 140*fcaf7f86SDimitry Andric // should not be called. 141*fcaf7f86SDimitry Andric return object::createError("no relocations in linked binary"); 142*fcaf7f86SDimitry Andric } 143*fcaf7f86SDimitry Andric 144*fcaf7f86SDimitry Andric protected: 145*fcaf7f86SDimitry Andric // returns true if specified address range is inside address ranges 146*fcaf7f86SDimitry Andric // of executable sections. 147*fcaf7f86SDimitry Andric bool isInsideExecutableSectionsAddressRange(uint64_t LowPC, 148*fcaf7f86SDimitry Andric Optional<uint64_t> HighPC) { 149*fcaf7f86SDimitry Andric Optional<AddressRange> Range = 150*fcaf7f86SDimitry Andric TextAddressRanges.getRangeThatContains(LowPC); 151*fcaf7f86SDimitry Andric 152*fcaf7f86SDimitry Andric if (HighPC) 153*fcaf7f86SDimitry Andric return Range.has_value() && Range->end() >= *HighPC; 154*fcaf7f86SDimitry Andric 155*fcaf7f86SDimitry Andric return Range.has_value(); 156*fcaf7f86SDimitry Andric } 157*fcaf7f86SDimitry Andric 158*fcaf7f86SDimitry Andric uint64_t isBFDDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC, 159*fcaf7f86SDimitry Andric uint16_t Version) { 160*fcaf7f86SDimitry Andric if (LowPC == 0) 161*fcaf7f86SDimitry Andric return true; 162*fcaf7f86SDimitry Andric 163*fcaf7f86SDimitry Andric if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1)) 164*fcaf7f86SDimitry Andric return true; 165*fcaf7f86SDimitry Andric 166*fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 167*fcaf7f86SDimitry Andric } 168*fcaf7f86SDimitry Andric 169*fcaf7f86SDimitry Andric uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC, 170*fcaf7f86SDimitry Andric uint16_t Version, uint8_t AddressByteSize) { 171*fcaf7f86SDimitry Andric if (Version <= 4 && HighPC) { 172*fcaf7f86SDimitry Andric if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1)) 173*fcaf7f86SDimitry Andric return true; 174*fcaf7f86SDimitry Andric } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize)) 175*fcaf7f86SDimitry Andric return true; 176*fcaf7f86SDimitry Andric 177*fcaf7f86SDimitry Andric if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC)) 178*fcaf7f86SDimitry Andric warning("Address referencing invalid text section is not marked with " 179*fcaf7f86SDimitry Andric "tombstone value"); 180*fcaf7f86SDimitry Andric 181*fcaf7f86SDimitry Andric return false; 182*fcaf7f86SDimitry Andric } 183*fcaf7f86SDimitry Andric 184*fcaf7f86SDimitry Andric bool isDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC, 185*fcaf7f86SDimitry Andric uint16_t Version, TombstoneKind Tombstone, 186*fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 187*fcaf7f86SDimitry Andric switch (Tombstone) { 188*fcaf7f86SDimitry Andric case TombstoneKind::BFD: 189*fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version); 190*fcaf7f86SDimitry Andric case TombstoneKind::MaxPC: 191*fcaf7f86SDimitry Andric return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 192*fcaf7f86SDimitry Andric case TombstoneKind::Universal: 193*fcaf7f86SDimitry Andric return isBFDDeadAddressRange(LowPC, HighPC, Version) || 194*fcaf7f86SDimitry Andric isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 195*fcaf7f86SDimitry Andric case TombstoneKind::Exec: 196*fcaf7f86SDimitry Andric return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 197*fcaf7f86SDimitry Andric } 198*fcaf7f86SDimitry Andric 199*fcaf7f86SDimitry Andric llvm_unreachable("Unknown tombstone value"); 200*fcaf7f86SDimitry Andric } 201*fcaf7f86SDimitry Andric 202*fcaf7f86SDimitry Andric bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone, 203*fcaf7f86SDimitry Andric uint8_t AddressByteSize) { 204*fcaf7f86SDimitry Andric return isDeadAddressRange(LowPC, None, Version, Tombstone, AddressByteSize); 205*fcaf7f86SDimitry Andric } 206*fcaf7f86SDimitry Andric 207*fcaf7f86SDimitry Andric private: 208*fcaf7f86SDimitry Andric RangesTy DWARFAddressRanges; 209*fcaf7f86SDimitry Andric AddressRanges TextAddressRanges; 210*fcaf7f86SDimitry Andric const Options &Opts; 211*fcaf7f86SDimitry Andric }; 212*fcaf7f86SDimitry Andric 213*fcaf7f86SDimitry Andric bool linkDebugInfo(object::ObjectFile &File, const Options &Options, 214*fcaf7f86SDimitry Andric raw_pwrite_stream &OutStream) { 215*fcaf7f86SDimitry Andric 216*fcaf7f86SDimitry Andric auto ReportWarn = [&](const Twine &Message, StringRef Context, 217*fcaf7f86SDimitry Andric const DWARFDie *Die) { 218*fcaf7f86SDimitry Andric warning(Message, Context); 219*fcaf7f86SDimitry Andric 220*fcaf7f86SDimitry Andric if (!Options.Verbose || !Die) 221*fcaf7f86SDimitry Andric return; 222*fcaf7f86SDimitry Andric 223*fcaf7f86SDimitry Andric DIDumpOptions DumpOpts; 224*fcaf7f86SDimitry Andric DumpOpts.ChildRecurseDepth = 0; 225*fcaf7f86SDimitry Andric DumpOpts.Verbose = Options.Verbose; 226*fcaf7f86SDimitry Andric 227*fcaf7f86SDimitry Andric WithColor::note() << " in DIE:\n"; 228*fcaf7f86SDimitry Andric Die->dump(errs(), /*Indent=*/6, DumpOpts); 229*fcaf7f86SDimitry Andric }; 230*fcaf7f86SDimitry Andric auto ReportErr = [&](const Twine &Message, StringRef Context, 231*fcaf7f86SDimitry Andric const DWARFDie *) { 232*fcaf7f86SDimitry Andric WithColor::error(errs(), Context) << Message << '\n'; 233*fcaf7f86SDimitry Andric }; 234*fcaf7f86SDimitry Andric 235*fcaf7f86SDimitry Andric // Create output streamer. 236*fcaf7f86SDimitry Andric DwarfStreamer OutStreamer(OutputFileType::Object, OutStream, nullptr, 237*fcaf7f86SDimitry Andric ReportWarn, ReportWarn); 238*fcaf7f86SDimitry Andric if (!OutStreamer.init(File.makeTriple(), "")) 239*fcaf7f86SDimitry Andric return false; 240*fcaf7f86SDimitry Andric 241*fcaf7f86SDimitry Andric // Create DWARF linker. 242*fcaf7f86SDimitry Andric DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD); 243*fcaf7f86SDimitry Andric 244*fcaf7f86SDimitry Andric DebugInfoLinker.setEstimatedObjfilesAmount(1); 245*fcaf7f86SDimitry Andric DebugInfoLinker.setAccelTableKind(DwarfLinkerAccelTableKind::None); 246*fcaf7f86SDimitry Andric DebugInfoLinker.setErrorHandler(ReportErr); 247*fcaf7f86SDimitry Andric DebugInfoLinker.setWarningHandler(ReportWarn); 248*fcaf7f86SDimitry Andric DebugInfoLinker.setNumThreads(Options.NumThreads); 249*fcaf7f86SDimitry Andric DebugInfoLinker.setNoODR(!Options.DoODRDeduplication); 250*fcaf7f86SDimitry Andric DebugInfoLinker.setVerbosity(Options.Verbose); 251*fcaf7f86SDimitry Andric DebugInfoLinker.setUpdate(!Options.DoGarbageCollection); 252*fcaf7f86SDimitry Andric 253*fcaf7f86SDimitry Andric std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1); 254*fcaf7f86SDimitry Andric std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1); 255*fcaf7f86SDimitry Andric std::vector<std::string> EmptyWarnings; 256*fcaf7f86SDimitry Andric 257*fcaf7f86SDimitry Andric std::unique_ptr<DWARFContext> Context = DWARFContext::create(File); 258*fcaf7f86SDimitry Andric 259*fcaf7f86SDimitry Andric // Add object files to the DWARFLinker. 260*fcaf7f86SDimitry Andric AddresssMapForLinking[0] = 261*fcaf7f86SDimitry Andric std::make_unique<ObjFileAddressMap>(*Context, Options, File); 262*fcaf7f86SDimitry Andric 263*fcaf7f86SDimitry Andric ObjectsForLinking[0] = std::make_unique<DWARFFile>( 264*fcaf7f86SDimitry Andric File.getFileName(), &*Context, AddresssMapForLinking[0].get(), 265*fcaf7f86SDimitry Andric EmptyWarnings); 266*fcaf7f86SDimitry Andric 267*fcaf7f86SDimitry Andric for (size_t I = 0; I < ObjectsForLinking.size(); I++) 268*fcaf7f86SDimitry Andric DebugInfoLinker.addObjectFile(*ObjectsForLinking[I]); 269*fcaf7f86SDimitry Andric 270*fcaf7f86SDimitry Andric // Link debug info. 271*fcaf7f86SDimitry Andric DebugInfoLinker.link(); 272*fcaf7f86SDimitry Andric OutStreamer.finish(); 273*fcaf7f86SDimitry Andric return true; 274*fcaf7f86SDimitry Andric } 275*fcaf7f86SDimitry Andric 276*fcaf7f86SDimitry Andric } // end of namespace dwarfutil 277*fcaf7f86SDimitry Andric } // end of namespace llvm 278