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