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/Classic/DWARFLinker.h" 13 #include "llvm/DWARFLinker/Classic/DWARFStreamer.h" 14 #include "llvm/DWARFLinker/Parallel/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 using namespace dwarf_linker; 23 24 namespace dwarfutil { 25 26 // ObjFileAddressMap allows to check whether specified DIE referencing 27 // dead addresses. It uses tombstone values to determine dead addresses. 28 // The concrete values of tombstone constants were discussed in 29 // https://reviews.llvm.org/D81784 and https://reviews.llvm.org/D84825. 30 // So we use following values as indicators of dead addresses: 31 // 32 // bfd: (LowPC == 0) or (LowPC == 1 and HighPC == 1 and DWARF v4 (or less)) 33 // or ([LowPC, HighPC] is not inside address ranges of .text sections). 34 // 35 // maxpc: (LowPC == -1) or (LowPC == -2 and DWARF v4 (or less)) 36 // That value is assumed to be compatible with 37 // http://www.dwarfstd.org/ShowIssue.php?issue=200609.1 38 // 39 // exec: [LowPC, HighPC] is not inside address ranges of .text sections 40 // 41 // universal: maxpc and bfd 42 class ObjFileAddressMap : public AddressesMap { 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 llvm::consumeError(ARanges.takeError()); 64 continue; 65 } 66 67 for (auto &Range : *ARanges) { 68 if (!isDeadAddressRange(Range.LowPC, Range.HighPC, CU->getVersion(), 69 Options.Tombstone, CU->getAddressByteSize())) { 70 HasValidAddressRanges = true; 71 break; 72 } 73 } 74 75 if (HasValidAddressRanges) 76 break; 77 } 78 } 79 80 // should be renamed into has valid address ranges 81 bool hasValidRelocs() override { return HasValidAddressRanges; } 82 83 std::optional<int64_t> 84 getSubprogramRelocAdjustment(const DWARFDie &DIE) override { 85 assert((DIE.getTag() == dwarf::DW_TAG_subprogram || 86 DIE.getTag() == dwarf::DW_TAG_label) && 87 "Wrong type of input die"); 88 89 if (std::optional<uint64_t> LowPC = 90 dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) { 91 if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(), 92 Opts.Tombstone, 93 DIE.getDwarfUnit()->getAddressByteSize())) 94 // Relocation value for the linked binary is 0. 95 return 0; 96 } 97 98 return std::nullopt; 99 } 100 101 std::optional<int64_t> 102 getExprOpAddressRelocAdjustment(DWARFUnit &U, 103 const DWARFExpression::Operation &Op, 104 uint64_t, uint64_t) override { 105 switch (Op.getCode()) { 106 default: { 107 assert(false && "Specified operation does not have address operand"); 108 } break; 109 case dwarf::DW_OP_const2u: 110 case dwarf::DW_OP_const4u: 111 case dwarf::DW_OP_const8u: 112 case dwarf::DW_OP_const2s: 113 case dwarf::DW_OP_const4s: 114 case dwarf::DW_OP_const8s: 115 case dwarf::DW_OP_addr: { 116 if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone, 117 U.getAddressByteSize())) 118 // Relocation value for the linked binary is 0. 119 return 0; 120 } break; 121 case dwarf::DW_OP_constx: 122 case dwarf::DW_OP_addrx: { 123 if (std::optional<object::SectionedAddress> Address = 124 U.getAddrOffsetSectionItem(Op.getRawOperand(0))) { 125 if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone, 126 U.getAddressByteSize())) 127 // Relocation value for the linked binary is 0. 128 return 0; 129 } 130 } break; 131 } 132 133 return std::nullopt; 134 } 135 136 std::optional<StringRef> getLibraryInstallName() override { 137 return std::nullopt; 138 } 139 140 bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override { 141 // no need to apply relocations to the linked binary. 142 return false; 143 } 144 145 bool needToSaveValidRelocs() override { return false; } 146 147 void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t, 148 uint64_t) override {} 149 150 void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset, 151 uint64_t OutputUnitOffset) override {} 152 153 void clear() override {} 154 155 protected: 156 // returns true if specified address range is inside address ranges 157 // of executable sections. 158 bool isInsideExecutableSectionsAddressRange(uint64_t LowPC, 159 std::optional<uint64_t> HighPC) { 160 std::optional<AddressRange> Range = 161 TextAddressRanges.getRangeThatContains(LowPC); 162 163 if (HighPC) 164 return Range.has_value() && Range->end() >= *HighPC; 165 166 return Range.has_value(); 167 } 168 169 uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 170 uint16_t Version) { 171 if (LowPC == 0) 172 return true; 173 174 if ((Version <= 4) && HighPC && (LowPC == 1 && *HighPC == 1)) 175 return true; 176 177 return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 178 } 179 180 uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, 181 std::optional<uint64_t> HighPC, 182 uint16_t Version, uint8_t AddressByteSize) { 183 if (Version <= 4 && HighPC) { 184 if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1)) 185 return true; 186 } else if (LowPC == dwarf::computeTombstoneAddress(AddressByteSize)) 187 return true; 188 189 if (!isInsideExecutableSectionsAddressRange(LowPC, HighPC)) 190 warning("Address referencing invalid text section is not marked with " 191 "tombstone value"); 192 193 return false; 194 } 195 196 bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC, 197 uint16_t Version, TombstoneKind Tombstone, 198 uint8_t AddressByteSize) { 199 switch (Tombstone) { 200 case TombstoneKind::BFD: 201 return isBFDDeadAddressRange(LowPC, HighPC, Version); 202 case TombstoneKind::MaxPC: 203 return isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 204 case TombstoneKind::Universal: 205 return isBFDDeadAddressRange(LowPC, HighPC, Version) || 206 isMAXPCDeadAddressRange(LowPC, HighPC, Version, AddressByteSize); 207 case TombstoneKind::Exec: 208 return !isInsideExecutableSectionsAddressRange(LowPC, HighPC); 209 } 210 211 llvm_unreachable("Unknown tombstone value"); 212 } 213 214 bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone, 215 uint8_t AddressByteSize) { 216 return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone, 217 AddressByteSize); 218 } 219 220 private: 221 AddressRanges TextAddressRanges; 222 const Options &Opts; 223 bool HasValidAddressRanges = false; 224 }; 225 226 static bool knownByDWARFUtil(StringRef SecName) { 227 return llvm::StringSwitch<bool>(SecName) 228 .Case(".debug_info", true) 229 .Case(".debug_types", true) 230 .Case(".debug_abbrev", true) 231 .Case(".debug_loc", true) 232 .Case(".debug_loclists", true) 233 .Case(".debug_frame", true) 234 .Case(".debug_aranges", true) 235 .Case(".debug_ranges", true) 236 .Case(".debug_rnglists", true) 237 .Case(".debug_line", true) 238 .Case(".debug_line_str", true) 239 .Case(".debug_addr", true) 240 .Case(".debug_macro", true) 241 .Case(".debug_macinfo", true) 242 .Case(".debug_str", true) 243 .Case(".debug_str_offsets", true) 244 .Case(".debug_pubnames", true) 245 .Case(".debug_pubtypes", true) 246 .Case(".debug_names", true) 247 .Default(false); 248 } 249 250 template <typename AccelTableKind> 251 static std::optional<AccelTableKind> 252 getAcceleratorTableKind(StringRef SecName) { 253 return llvm::StringSwitch<std::optional<AccelTableKind>>(SecName) 254 .Case(".debug_pubnames", AccelTableKind::Pub) 255 .Case(".debug_pubtypes", AccelTableKind::Pub) 256 .Case(".debug_names", AccelTableKind::DebugNames) 257 .Default(std::nullopt); 258 } 259 260 static std::string getMessageForReplacedAcceleratorTables( 261 SmallVector<StringRef> &AccelTableNamesToReplace, 262 DwarfUtilAccelKind TargetTable) { 263 std::string Message; 264 265 Message += "'"; 266 for (StringRef Name : AccelTableNamesToReplace) { 267 if (Message.size() > 1) 268 Message += ", "; 269 Message += Name; 270 } 271 272 Message += "' will be replaced with requested "; 273 274 switch (TargetTable) { 275 case DwarfUtilAccelKind::DWARF: 276 Message += ".debug_names table"; 277 break; 278 279 default: 280 assert(false); 281 } 282 283 return Message; 284 } 285 286 static std::string getMessageForDeletedAcceleratorTables( 287 SmallVector<StringRef> &AccelTableNamesToReplace) { 288 std::string Message; 289 290 Message += "'"; 291 for (StringRef Name : AccelTableNamesToReplace) { 292 if (Message.size() > 1) 293 Message += ", "; 294 Message += Name; 295 } 296 297 Message += "' will be deleted as no accelerator tables are requested"; 298 299 return Message; 300 } 301 302 template <typename Linker> 303 Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options, 304 raw_pwrite_stream &OutStream) { 305 std::mutex ErrorHandlerMutex; 306 307 auto ReportWarn = [&](const Twine &Message, StringRef Context, 308 const DWARFDie *Die) { 309 // FIXME: implement warning logging which does not block other threads. 310 if (!ErrorHandlerMutex.try_lock()) 311 return; 312 313 warning(Message, Context); 314 if (Options.Verbose && Die) { 315 DIDumpOptions DumpOpts; 316 DumpOpts.ChildRecurseDepth = 0; 317 DumpOpts.Verbose = Options.Verbose; 318 319 WithColor::note() << " in DIE:\n"; 320 Die->dump(errs(), /*Indent=*/6, DumpOpts); 321 } 322 ErrorHandlerMutex.unlock(); 323 }; 324 auto ReportErr = [&](const Twine &Message, StringRef Context, 325 const DWARFDie *) { 326 // FIXME: implement error logging which does not block other threads. 327 if (!ErrorHandlerMutex.try_lock()) 328 return; 329 330 WithColor::error(errs(), Context) << Message << '\n'; 331 ErrorHandlerMutex.unlock(); 332 }; 333 334 // Create DWARF linker. 335 std::unique_ptr<Linker> DebugInfoLinker = 336 Linker::createLinker(ReportErr, ReportWarn); 337 338 Triple TargetTriple = File.makeTriple(); 339 if (Error Err = DebugInfoLinker->createEmitter( 340 TargetTriple, Linker::OutputFileType::Object, OutStream)) 341 return Err; 342 343 DebugInfoLinker->setEstimatedObjfilesAmount(1); 344 DebugInfoLinker->setNumThreads(Options.NumThreads); 345 DebugInfoLinker->setNoODR(!Options.DoODRDeduplication); 346 DebugInfoLinker->setVerbosity(Options.Verbose); 347 DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection); 348 349 std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1); 350 351 // Add object files to the DWARFLinker. 352 std::unique_ptr<DWARFContext> Context = DWARFContext::create( 353 File, DWARFContext::ProcessDebugRelocations::Process, nullptr, "", 354 [&](Error Err) { 355 handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) { 356 ReportErr(Info.message(), "", nullptr); 357 }); 358 }, 359 [&](Error Warning) { 360 handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) { 361 ReportWarn(Info.message(), "", nullptr); 362 }); 363 }); 364 std::unique_ptr<ObjFileAddressMap> AddressesMap( 365 std::make_unique<ObjFileAddressMap>(*Context, Options, File)); 366 367 ObjectsForLinking[0] = std::make_unique<DWARFFile>( 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<DWARFFile> &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<parallel::DWARFLinker>(File, Options, OutStream); 456 else 457 return linkDebugInfoImpl<classic::DWARFLinker>(File, Options, OutStream); 458 } 459 460 } // end of namespace dwarfutil 461 } // end of namespace llvm 462