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 "llvm/Support/Endian.h" 18 #include <memory> 19 #include <vector> 20 21 namespace llvm { 22 namespace dwarfutil { 23 24 // ObjFileAddressMap allows to check whether specified DIE referencing 25 // dead addresses. It uses tombstone values to determine dead addresses. 26 // The concrete values of tombstone constants were discussed in 27 // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825. 28 // So we use following values as indicators of dead addresses: 29 // 30 // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less)) 31 // or ([LowPC, HighPC] is not inside address ranges of .text sections). 32 // 33 // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less)) 34 // That value is assumed to be compatible with 35 // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1 36 // 37 // exec: [LowPC, HighPC] is not inside address ranges of .text sections 38 // 39 // universal: maxpc and bfd 40 class ObjFileAddressMap : public AddressesMap { 41 public: 42 ObjFileAddressMap(DWARFContext &Context, const Options &Options, 43 object::ObjectFile &ObjFile) 44 : Opts(Options), Context(Context) { 45 // Remember addresses of existing text sections. 46 for (const object::SectionRef &Sect : ObjFile.sections()) { 47 if (!Sect.isText()) 48 continue; 49 const uint64_t Size = Sect.getSize(); 50 if (Size == 0) 51 continue; 52 const uint64_t StartAddr = Sect.getAddress(); 53 TextAddressRanges.insert({StartAddr, StartAddr + Size}); 54 } 55 56 // Check CU address ranges for tombstone value. 57 for (std::unique_ptr<DWARFUnit> &CU : Context.compile_units()) { 58 Expected<llvm::DWARFAddressRangesVector> ARanges = 59 CU->getUnitDIE().getAddressRanges(); 60 if (ARanges) { 61 for (auto &Range : *ARanges) { 62 if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(), 63 Options.Tombstone, CU->getAddressByteSize())) 64 DWARFAddressRanges.insert({Range.LowPC, Range.HighPC}, 0); 65 } 66 } 67 } 68 } 69 70 // should be renamed into has valid address ranges 71 bool hasValidRelocs() override { return !DWARFAddressRanges.empty(); } 72 73 bool isLiveSubprogram(const DWARFDie &DIE, 74 CompileUnit::DIEInfo &Info) override { 75 assert((DIE.getTag() == dwarf::DW_TAG_subprogram || 76 DIE.getTag() == dwarf::DW_TAG_label) && 77 "Wrong type of input die"); 78 79 if (std::optional<uint64_t> LowPC = 80 dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) { 81 if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(), 82 Opts.Tombstone, 83 DIE.getDwarfUnit()->getAddressByteSize())) { 84 Info.AddrAdjust = 0; 85 Info.InDebugMap = true; 86 return true; 87 } 88 } 89 90 return false; 91 } 92 93 bool isLiveVariable(const DWARFDie &DIE, 94 CompileUnit::DIEInfo &Info) override { 95 assert((DIE.getTag() == dwarf::DW_TAG_variable || 96 DIE.getTag() == dwarf::DW_TAG_constant) && 97 "Wrong type of input die"); 98 99 if (Expected<DWARFLocationExpressionsVector> Loc = 100 DIE.getLocations(dwarf::DW_AT_location)) { 101 DWARFUnit *U = DIE.getDwarfUnit(); 102 for (const auto &Entry : *Loc) { 103 DataExtractor Data(toStringRef(Entry.Expr), 104 U->getContext().isLittleEndian(), 0); 105 DWARFExpression Expression(Data, U->getAddressByteSize(), 106 U->getFormParams().Format); 107 bool HasLiveAddresses = 108 any_of(Expression, [&](const DWARFExpression::Operation &Op) { 109 // TODO: add handling of dwarf::DW_OP_addrx 110 return !Op.isError() && 111 (Op.getCode() == dwarf::DW_OP_addr && 112 !isDeadAddress(Op.getRawOperand(0), U->getVersion(), 113 Opts.Tombstone, 114 DIE.getDwarfUnit()->getAddressByteSize())); 115 }); 116 117 if (HasLiveAddresses) { 118 Info.AddrAdjust = 0; 119 Info.InDebugMap = true; 120 return true; 121 } 122 } 123 } else { 124 // FIXME: missing DW_AT_location is OK here, but other errors should be 125 // reported to the user. 126 consumeError(Loc.takeError()); 127 } 128 129 return false; 130 } 131 132 bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override { 133 // no need to apply relocations to the linked binary. 134 return false; 135 } 136 137 RangesTy &getValidAddressRanges() override { return DWARFAddressRanges; }; 138 139 void clear() override { DWARFAddressRanges.clear(); } 140 141 llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset, 142 uint64_t EndOffset) override { 143 // No relocations in linked binary. Return just address value. 144 145 const char *AddrPtr = 146 Context.getDWARFObj().getAddrSection().Data.data() + StartOffset; 147 support::endianness Endianess = 148 Context.getDWARFObj().isLittleEndian() ? support::little : support::big; 149 150 assert(EndOffset > StartOffset); 151 switch (EndOffset - StartOffset) { 152 case 1: 153 return *AddrPtr; 154 case 2: 155 return support::endian::read16(AddrPtr, Endianess); 156 case 4: 157 return support::endian::read32(AddrPtr, Endianess); 158 case 8: 159 return support::endian::read64(AddrPtr, Endianess); 160 } 161 162 llvm_unreachable("relocateIndexedAddr unhandled case!"); 163 } 164 165 protected: 166 // returns true if specified address range is inside address ranges 167 // of executable sections. 168 bool isInsideExecutableSectionsAddressRange(uint64_t LowPC, 169 std::optional<uint64_t> HighPC) { 170 std::optional<AddressRange> Range = 171 TextAddressRanges.getRangeThatContains(LowPC); 172 173 if (HighPC) 174 return Range.has_value() && Range->end() >= *HighPC; 175 176 return Range.has_value(); 177 } 178 179 uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 180 uint16_t Version) { 181 if (LowPC == 0) 182 return true; 183 184 if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1)) 185 return true; 186 187 return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 188 } 189 190 uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, 191 std::optional<uint64_t> HighPC, 192 uint16_t Version, uint8_t AddressByteSize) { 193 if (Version <= 4 && HighPC) { 194 if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1)) 195 return true; 196 } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize)) 197 return true; 198 199 if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC)) 200 warning("Address referencing invalid text section is not marked with " 201 "tombstone value"); 202 203 return false; 204 } 205 206 bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 207 uint16_t Version, TombstoneKind Tombstone, 208 uint8_t AddressByteSize) { 209 switch (Tombstone) { 210 case TombstoneKind::BFD: 211 return isBFDDeadAddressRange(LowPC, HighPC, Version); 212 case TombstoneKind::MaxPC: 213 return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 214 case TombstoneKind::Universal: 215 return isBFDDeadAddressRange(LowPC, HighPC, Version) || 216 isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 217 case TombstoneKind::Exec: 218 return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 219 } 220 221 llvm_unreachable("Unknown tombstone value"); 222 } 223 224 bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone, 225 uint8_t AddressByteSize) { 226 return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone, 227 AddressByteSize); 228 } 229 230 private: 231 RangesTy DWARFAddressRanges; 232 AddressRanges TextAddressRanges; 233 const Options &Opts; 234 DWARFContext &Context; 235 }; 236 237 static bool knownByDWARFUtil(StringRef SecName) { 238 return llvm::StringSwitch<bool>(SecName) 239 .Case(".debug_info", true) 240 .Case(".debug_types", true) 241 .Case(".debug_abbrev", true) 242 .Case(".debug_loc", true) 243 .Case(".debug_loclists", true) 244 .Case(".debug_frame", true) 245 .Case(".debug_aranges", true) 246 .Case(".debug_ranges", true) 247 .Case(".debug_rnglists", true) 248 .Case(".debug_line", true) 249 .Case(".debug_line_str", true) 250 .Case(".debug_addr", true) 251 .Case(".debug_macro", true) 252 .Case(".debug_macinfo", true) 253 .Case(".debug_str", true) 254 .Case(".debug_str_offsets", true) 255 .Case(".debug_pubnames", true) 256 .Case(".debug_pubtypes", true) 257 .Case(".debug_names", true) 258 .Default(false); 259 } 260 261 static std::optional<DwarfLinkerAccelTableKind> 262 getAcceleratorTableKind(StringRef SecName) { 263 return llvm::StringSwitch<std::optional<DwarfLinkerAccelTableKind>>(SecName) 264 .Case(".debug_pubnames", DwarfLinkerAccelTableKind::Pub) 265 .Case(".debug_pubtypes", DwarfLinkerAccelTableKind::Pub) 266 .Case(".debug_names", DwarfLinkerAccelTableKind::DebugNames) 267 .Default(std::nullopt); 268 } 269 270 static std::string getMessageForReplacedAcceleratorTables( 271 SmallVector<StringRef> &AccelTableNamesToReplace, 272 DwarfUtilAccelKind TargetTable) { 273 std::string Message; 274 275 Message += "'"; 276 for (StringRef Name : AccelTableNamesToReplace) { 277 if (Message.size() > 1) 278 Message += ", "; 279 Message += Name; 280 } 281 282 Message += "' will be replaced with requested "; 283 284 switch (TargetTable) { 285 case DwarfUtilAccelKind::DWARF: 286 Message += ".debug_names table"; 287 break; 288 289 default: 290 assert(false); 291 } 292 293 return Message; 294 } 295 296 static std::string getMessageForDeletedAcceleratorTables( 297 SmallVector<StringRef> &AccelTableNamesToReplace) { 298 std::string Message; 299 300 Message += "'"; 301 for (StringRef Name : AccelTableNamesToReplace) { 302 if (Message.size() > 1) 303 Message += ", "; 304 Message += Name; 305 } 306 307 Message += "' will be deleted as no accelerator tables are requested"; 308 309 return Message; 310 } 311 312 Error linkDebugInfo(object::ObjectFile &File, const Options &Options, 313 raw_pwrite_stream &OutStream) { 314 315 auto ReportWarn = [&](const Twine &Message, StringRef Context, 316 const DWARFDie *Die) { 317 warning(Message, Context); 318 319 if (!Options.Verbose || !Die) 320 return; 321 322 DIDumpOptions DumpOpts; 323 DumpOpts.ChildRecurseDepth = 0; 324 DumpOpts.Verbose = Options.Verbose; 325 326 WithColor::note() << " in DIE:\n"; 327 Die->dump(errs(), /*Indent=*/6, DumpOpts); 328 }; 329 auto ReportErr = [&](const Twine &Message, StringRef Context, 330 const DWARFDie *) { 331 WithColor::error(errs(), Context) << Message << '\n'; 332 }; 333 334 // Create output streamer. 335 DwarfStreamer OutStreamer(OutputFileType::Object, OutStream, nullptr, 336 ReportWarn, ReportWarn); 337 Triple TargetTriple = File.makeTriple(); 338 if (!OutStreamer.init(TargetTriple, formatv("cannot create a stream for {0}", 339 TargetTriple.getTriple()) 340 .str())) 341 return createStringError(std::errc::invalid_argument, ""); 342 343 std::unique_ptr<DWARFContext> Context = DWARFContext::create(File); 344 345 // Create DWARF linker. 346 DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD); 347 348 DebugInfoLinker.setEstimatedObjfilesAmount(1); 349 DebugInfoLinker.setErrorHandler(ReportErr); 350 DebugInfoLinker.setWarningHandler(ReportWarn); 351 DebugInfoLinker.setNumThreads(Options.NumThreads); 352 DebugInfoLinker.setNoODR(!Options.DoODRDeduplication); 353 DebugInfoLinker.setVerbosity(Options.Verbose); 354 DebugInfoLinker.setUpdate(!Options.DoGarbageCollection); 355 356 std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1); 357 std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1); 358 std::vector<std::string> EmptyWarnings; 359 360 // Add object files to the DWARFLinker. 361 AddresssMapForLinking[0] = 362 std::make_unique<ObjFileAddressMap>(*Context, Options, File); 363 364 ObjectsForLinking[0] = std::make_unique<DWARFFile>( 365 File.getFileName(), &*Context, AddresssMapForLinking[0].get(), 366 EmptyWarnings); 367 368 uint16_t MaxDWARFVersion = 0; 369 std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded = 370 [&MaxDWARFVersion](const DWARFUnit &Unit) { 371 MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); 372 }; 373 374 for (size_t I = 0; I < ObjectsForLinking.size(); I++) 375 DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr, 376 OnCUDieLoaded); 377 378 // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. 379 if (MaxDWARFVersion == 0) 380 MaxDWARFVersion = 3; 381 382 if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion)) 383 return Err; 384 385 SmallVector<DwarfLinkerAccelTableKind> AccelTables; 386 387 switch (Options.AccelTableKind) { 388 case DwarfUtilAccelKind::None: 389 // Nothing to do. 390 break; 391 case DwarfUtilAccelKind::DWARF: 392 // use .debug_names for all DWARF versions. 393 AccelTables.push_back(DwarfLinkerAccelTableKind::DebugNames); 394 break; 395 } 396 397 // Add accelerator tables to DWARFLinker. 398 for (DwarfLinkerAccelTableKind Table : AccelTables) 399 DebugInfoLinker.addAccelTableKind(Table); 400 401 SmallVector<StringRef> AccelTableNamesToReplace; 402 SmallVector<StringRef> AccelTableNamesToDelete; 403 404 // Unknown debug sections or non-requested accelerator sections would be 405 // removed. Display warning for such sections. 406 for (SectionName Sec : Context->getDWARFObj().getSectionNames()) { 407 if (isDebugSection(Sec.Name)) { 408 std::optional<DwarfLinkerAccelTableKind> SrcAccelTableKind = 409 getAcceleratorTableKind(Sec.Name); 410 411 if (SrcAccelTableKind) { 412 assert(knownByDWARFUtil(Sec.Name)); 413 414 if (Options.AccelTableKind == DwarfUtilAccelKind::None) 415 AccelTableNamesToDelete.push_back(Sec.Name); 416 else if (std::find(AccelTables.begin(), AccelTables.end(), 417 *SrcAccelTableKind) == AccelTables.end()) 418 AccelTableNamesToReplace.push_back(Sec.Name); 419 } else if (!knownByDWARFUtil(Sec.Name)) { 420 assert(!SrcAccelTableKind); 421 warning( 422 formatv("'{0}' is not currently supported: section will be skipped", 423 Sec.Name), 424 Options.InputFileName); 425 } 426 } 427 } 428 429 // Display message for the replaced accelerator tables. 430 if (!AccelTableNamesToReplace.empty()) 431 warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace, 432 Options.AccelTableKind), 433 Options.InputFileName); 434 435 // Display message for the removed accelerator tables. 436 if (!AccelTableNamesToDelete.empty()) 437 warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete), 438 Options.InputFileName); 439 440 // Link debug info. 441 if (Error Err = DebugInfoLinker.link()) 442 return Err; 443 444 OutStreamer.finish(); 445 return Error::success(); 446 } 447 448 } // end of namespace dwarfutil 449 } // end of namespace llvm 450