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