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