1 //===- bolt/Rewrite/DWARFRewriter.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 "bolt/Rewrite/DWARFRewriter.h" 10 #include "bolt/Core/BinaryContext.h" 11 #include "bolt/Core/BinaryFunction.h" 12 #include "bolt/Core/DIEBuilder.h" 13 #include "bolt/Core/DebugData.h" 14 #include "bolt/Core/DynoStats.h" 15 #include "bolt/Core/ParallelUtilities.h" 16 #include "bolt/Rewrite/RewriteInstance.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/BinaryFormat/Dwarf.h" 21 #include "llvm/CodeGen/AsmPrinter.h" 22 #include "llvm/CodeGen/DIE.h" 23 #include "llvm/DWARFLinker/Classic/DWARFStreamer.h" 24 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 25 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 27 #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 28 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 29 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 30 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 31 #include "llvm/MC/MCAsmBackend.h" 32 #include "llvm/MC/MCAssembler.h" 33 #include "llvm/MC/MCObjectWriter.h" 34 #include "llvm/MC/MCStreamer.h" 35 #include "llvm/MC/MCTargetOptionsCommandFlags.h" 36 #include "llvm/Object/ObjectFile.h" 37 #include "llvm/Support/Casting.h" 38 #include "llvm/Support/CommandLine.h" 39 #include "llvm/Support/Debug.h" 40 #include "llvm/Support/Endian.h" 41 #include "llvm/Support/Error.h" 42 #include "llvm/Support/FileSystem.h" 43 #include "llvm/Support/LEB128.h" 44 #include "llvm/Support/ThreadPool.h" 45 #include "llvm/Support/raw_ostream.h" 46 #include <algorithm> 47 #include <cstdint> 48 #include <functional> 49 #include <iterator> 50 #include <memory> 51 #include <optional> 52 #include <string> 53 #include <unordered_map> 54 #include <utility> 55 #include <vector> 56 57 #undef DEBUG_TYPE 58 #define DEBUG_TYPE "bolt" 59 60 static mc::RegisterMCTargetOptionsFlags MOF; 61 62 static void printDie(const DWARFDie &DIE) { 63 DIDumpOptions DumpOpts; 64 DumpOpts.ShowForm = true; 65 DumpOpts.Verbose = true; 66 DumpOpts.ChildRecurseDepth = 0; 67 DumpOpts.ShowChildren = false; 68 DIE.dump(dbgs(), 0, DumpOpts); 69 } 70 71 /// Lazily parse DWARF DIE and print it out. 72 LLVM_ATTRIBUTE_UNUSED 73 static void printDie(DWARFUnit &DU, uint64_t DIEOffset) { 74 uint64_t OriginalOffsets = DIEOffset; 75 uint64_t NextCUOffset = DU.getNextUnitOffset(); 76 DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor(); 77 DWARFDebugInfoEntry DIEEntry; 78 if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) { 79 if (DIEEntry.getAbbreviationDeclarationPtr()) { 80 DWARFDie DDie(&DU, &DIEEntry); 81 printDie(DDie); 82 } else { 83 dbgs() << "Failed to extract abbreviation for" 84 << Twine::utohexstr(OriginalOffsets) << "\n"; 85 } 86 } else { 87 dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets) 88 << " \n"; 89 } 90 } 91 92 using namespace bolt; 93 94 /// Take a set of DWARF address ranges corresponding to the input binary and 95 /// translate them to a set of address ranges in the output binary. 96 static DebugAddressRangesVector 97 translateInputToOutputRanges(const BinaryFunction &BF, 98 const DWARFAddressRangesVector &InputRanges) { 99 DebugAddressRangesVector OutputRanges; 100 101 // If the function hasn't changed return the same ranges. 102 if (!BF.isEmitted()) { 103 OutputRanges.resize(InputRanges.size()); 104 llvm::transform(InputRanges, OutputRanges.begin(), 105 [](const DWARFAddressRange &Range) { 106 return DebugAddressRange(Range.LowPC, Range.HighPC); 107 }); 108 return OutputRanges; 109 } 110 111 for (const DWARFAddressRange &Range : InputRanges) 112 llvm::append_range(OutputRanges, BF.translateInputToOutputRange( 113 {Range.LowPC, Range.HighPC})); 114 115 // Post-processing pass to sort and merge ranges. 116 llvm::sort(OutputRanges); 117 DebugAddressRangesVector MergedRanges; 118 uint64_t PrevHighPC = 0; 119 for (const DebugAddressRange &Range : OutputRanges) { 120 if (Range.LowPC <= PrevHighPC) { 121 MergedRanges.back().HighPC = 122 std::max(MergedRanges.back().HighPC, Range.HighPC); 123 } else { 124 MergedRanges.emplace_back(Range.LowPC, Range.HighPC); 125 } 126 PrevHighPC = MergedRanges.back().HighPC; 127 } 128 129 return MergedRanges; 130 } 131 132 /// Similar to translateInputToOutputRanges() but operates on location lists. 133 static DebugLocationsVector 134 translateInputToOutputLocationList(const BinaryFunction &BF, 135 const DebugLocationsVector &InputLL) { 136 DebugLocationsVector OutputLL; 137 138 // If the function hasn't changed - there's nothing to update. 139 if (!BF.isEmitted()) 140 return InputLL; 141 142 for (const DebugLocationEntry &Entry : InputLL) { 143 DebugAddressRangesVector OutRanges = 144 BF.translateInputToOutputRange({Entry.LowPC, Entry.HighPC}); 145 if (!OutRanges.empty() && !OutputLL.empty()) { 146 if (OutRanges.front().LowPC == OutputLL.back().HighPC && 147 Entry.Expr == OutputLL.back().Expr) { 148 OutputLL.back().HighPC = 149 std::max(OutputLL.back().HighPC, OutRanges.front().HighPC); 150 OutRanges.erase(OutRanges.begin()); 151 } 152 } 153 llvm::transform(OutRanges, std::back_inserter(OutputLL), 154 [&Entry](const DebugAddressRange &R) { 155 return DebugLocationEntry{R.LowPC, R.HighPC, Entry.Expr}; 156 }); 157 } 158 159 // Sort and merge adjacent entries with identical locations. 160 llvm::stable_sort( 161 OutputLL, [](const DebugLocationEntry &A, const DebugLocationEntry &B) { 162 return A.LowPC < B.LowPC; 163 }); 164 DebugLocationsVector MergedLL; 165 uint64_t PrevHighPC = 0; 166 const SmallVectorImpl<uint8_t> *PrevExpr = nullptr; 167 for (const DebugLocationEntry &Entry : OutputLL) { 168 if (Entry.LowPC <= PrevHighPC && *PrevExpr == Entry.Expr) { 169 MergedLL.back().HighPC = std::max(Entry.HighPC, MergedLL.back().HighPC); 170 } else { 171 const uint64_t Begin = std::max(Entry.LowPC, PrevHighPC); 172 const uint64_t End = std::max(Begin, Entry.HighPC); 173 MergedLL.emplace_back(DebugLocationEntry{Begin, End, Entry.Expr}); 174 } 175 PrevHighPC = MergedLL.back().HighPC; 176 PrevExpr = &MergedLL.back().Expr; 177 } 178 179 return MergedLL; 180 } 181 182 using namespace dwarf_linker; 183 using namespace dwarf_linker::classic; 184 185 namespace llvm { 186 namespace bolt { 187 /// Emits debug information into .debug_info or .debug_types section. 188 class DIEStreamer : public DwarfStreamer { 189 DIEBuilder *DIEBldr; 190 GDBIndex &GDBIndexSection; 191 192 private: 193 /// Emit the compilation unit header for \p Unit in the debug_info 194 /// section. 195 /// 196 /// A Dwarf 4 section header is encoded as: 197 /// uint32_t Unit length (omitting this field) 198 /// uint16_t Version 199 /// uint32_t Abbreviation table offset 200 /// uint8_t Address size 201 /// Leading to a total of 11 bytes. 202 /// 203 /// A Dwarf 5 section header is encoded as: 204 /// uint32_t Unit length (omitting this field) 205 /// uint16_t Version 206 /// uint8_t Unit type 207 /// uint8_t Address size 208 /// uint32_t Abbreviation table offset 209 /// Leading to a total of 12 bytes. 210 void emitCompileUnitHeader(DWARFUnit &Unit, DIE &UnitDIE, 211 unsigned DwarfVersion) { 212 213 AsmPrinter &Asm = getAsmPrinter(); 214 switchToDebugInfoSection(DwarfVersion); 215 216 emitCommonHeader(Unit, UnitDIE, DwarfVersion); 217 218 if (DwarfVersion >= 5 && 219 Unit.getUnitType() != dwarf::UnitType::DW_UT_compile) { 220 std::optional<uint64_t> DWOId = Unit.getDWOId(); 221 assert(DWOId && 222 "DWOId does not exist and this is not a DW_UT_compile Unit"); 223 Asm.emitInt64(*DWOId); 224 } 225 } 226 227 void emitCommonHeader(DWARFUnit &Unit, DIE &UnitDIE, uint16_t Version) { 228 dwarf::UnitType UT = dwarf::UnitType(Unit.getUnitType()); 229 llvm::AsmPrinter &Asm = getAsmPrinter(); 230 231 // Emit size of content not including length itself 232 Asm.emitInt32(Unit.getHeaderSize() + UnitDIE.getSize() - 4); 233 Asm.emitInt16(Version); 234 235 // DWARF v5 reorders the address size and adds a unit type. 236 if (Version >= 5) { 237 Asm.emitInt8(UT); 238 Asm.emitInt8(Asm.MAI->getCodePointerSize()); 239 } 240 241 Asm.emitInt32(0); 242 if (Version <= 4) { 243 Asm.emitInt8(Asm.MAI->getCodePointerSize()); 244 } 245 } 246 247 void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE, 248 unsigned DwarfVersion) { 249 AsmPrinter &Asm = getAsmPrinter(); 250 const uint64_t TypeSignature = cast<DWARFTypeUnit>(Unit).getTypeHash(); 251 DIE *TypeDIE = DIEBldr->getTypeDIE(Unit); 252 const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit); 253 GDBIndexSection.addGDBTypeUnitEntry( 254 {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()}); 255 if (Unit.getVersion() < 5) { 256 // Switch the section to .debug_types section. 257 std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer; 258 llvm::MCContext &MC = Asm.OutContext; 259 const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo(); 260 261 MS->switchSection(MOFI->getDwarfTypesSection(0)); 262 MC.setDwarfVersion(DwarfVersion); 263 } else 264 switchToDebugInfoSection(DwarfVersion); 265 266 emitCommonHeader(Unit, UnitDIE, DwarfVersion); 267 Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature)); 268 Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0); 269 } 270 271 void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) { 272 if (Unit.isTypeUnit()) 273 emitTypeUnitHeader(Unit, UnitDIE, Unit.getVersion()); 274 else 275 emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion()); 276 } 277 278 void emitDIE(DIE &Die) override { 279 AsmPrinter &Asm = getAsmPrinter(); 280 Asm.emitDwarfDIE(Die); 281 } 282 283 public: 284 DIEStreamer(DIEBuilder *DIEBldr, GDBIndex &GDBIndexSection, 285 DWARFLinkerBase::OutputFileType OutFileType, 286 raw_pwrite_stream &OutFile, 287 DWARFLinkerBase::MessageHandlerTy Warning) 288 : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr), 289 GDBIndexSection(GDBIndexSection) {}; 290 291 using DwarfStreamer::emitCompileUnitHeader; 292 293 void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) { 294 emitUnitHeader(Unit, UnitDIE); 295 emitDIE(UnitDIE); 296 } 297 }; 298 299 /// Finds attributes FormValue and Offset. 300 /// 301 /// \param DIE die to look up in. 302 /// \param Attrs finds the first attribute that matches and extracts it. 303 /// \return an optional AttrInfo with DWARFFormValue and Offset. 304 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE, 305 std::vector<dwarf::Attribute> Attrs) { 306 for (dwarf::Attribute &Attr : Attrs) 307 if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr)) 308 return Info; 309 return std::nullopt; 310 } 311 312 } // namespace bolt 313 } // namespace llvm 314 315 using namespace llvm; 316 using namespace llvm::support::endian; 317 using namespace object; 318 using namespace bolt; 319 320 namespace opts { 321 322 extern cl::OptionCategory BoltCategory; 323 extern cl::opt<unsigned> Verbosity; 324 extern cl::opt<std::string> OutputFilename; 325 326 static cl::opt<bool> KeepARanges( 327 "keep-aranges", 328 cl::desc( 329 "keep or generate .debug_aranges section if .gdb_index is written"), 330 cl::Hidden, cl::cat(BoltCategory)); 331 332 static cl::opt<unsigned> 333 DebugThreadCount("debug-thread-count", 334 cl::desc("specifies thread count for the multithreading " 335 "for updating DWO debug info"), 336 cl::init(1), cl::cat(BoltCategory)); 337 338 static cl::opt<std::string> DwarfOutputPath( 339 "dwarf-output-path", 340 cl::desc("Path to where .dwo files will be written out to."), cl::init(""), 341 cl::cat(BoltCategory)); 342 343 static cl::opt<bool> CreateDebugNames( 344 "create-debug-names-section", 345 cl::desc("Creates .debug_names section, if the input binary doesn't have " 346 "it already, for DWARF5 CU/TUs."), 347 cl::init(false), cl::cat(BoltCategory)); 348 349 static cl::opt<bool> 350 DebugSkeletonCu("debug-skeleton-cu", 351 cl::desc("prints out offsets for abbrev and debug_info of " 352 "Skeleton CUs that get patched."), 353 cl::ZeroOrMore, cl::Hidden, cl::init(false), 354 cl::cat(BoltCategory)); 355 356 static cl::opt<unsigned> BatchSize( 357 "cu-processing-batch-size", 358 cl::desc( 359 "Specifies the size of batches for processing CUs. Higher number has " 360 "better performance, but more memory usage. Default value is 1."), 361 cl::Hidden, cl::init(1), cl::cat(BoltCategory)); 362 363 static cl::opt<bool> AlwaysConvertToRanges( 364 "always-convert-to-ranges", 365 cl::desc("This option is for testing purposes only. It forces BOLT to " 366 "convert low_pc/high_pc to ranges always."), 367 cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory)); 368 369 extern cl::opt<std::string> CompDirOverride; 370 } // namespace opts 371 372 /// If DW_AT_low_pc exists sets LowPC and returns true. 373 static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC, 374 uint64_t &SectionIndex) { 375 DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc); 376 if (!DvalLowPc) 377 return false; 378 379 dwarf::Form Form = DvalLowPc.getForm(); 380 bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset; 381 uint64_t LowPcValue = DvalLowPc.getDIEInteger().getValue(); 382 if (Form == dwarf::DW_FORM_GNU_addr_index || Form == dwarf::DW_FORM_addrx || 383 AddrOffset) { 384 385 uint32_t Index = AddrOffset ? (LowPcValue >> 32) : LowPcValue; 386 std::optional<object::SectionedAddress> SA = 387 DU.getAddrOffsetSectionItem(Index); 388 if (!SA) 389 return false; 390 if (AddrOffset) 391 SA->Address += (LowPcValue & 0xffffffff); 392 393 LowPC = SA->Address; 394 SectionIndex = SA->SectionIndex; 395 } else { 396 LowPC = LowPcValue; 397 SectionIndex = 0; 398 } 399 return true; 400 } 401 402 /// If DW_AT_high_pc exists sets HighPC and returns true. 403 static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) { 404 DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc); 405 if (!DvalHighPc) 406 return false; 407 if (DvalHighPc.getForm() == dwarf::DW_FORM_addr) 408 HighPC = DvalHighPc.getDIEInteger().getValue(); 409 else 410 HighPC = LowPC + DvalHighPc.getDIEInteger().getValue(); 411 return true; 412 } 413 414 /// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns 415 /// true. 416 static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU, 417 uint64_t &LowPC, uint64_t &HighPC, 418 uint64_t &SectionIndex) { 419 uint64_t TempLowPC = LowPC; 420 uint64_t TempHighPC = HighPC; 421 uint64_t TempSectionIndex = SectionIndex; 422 if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) && 423 getHighPC(Die, TempLowPC, TempHighPC)) { 424 LowPC = TempLowPC; 425 HighPC = TempHighPC; 426 SectionIndex = TempSectionIndex; 427 return true; 428 } 429 return false; 430 } 431 432 static Expected<llvm::DWARFAddressRangesVector> 433 getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) { 434 uint64_t LowPC, HighPC, Index; 435 if (getLowAndHighPC(Die, DU, LowPC, HighPC, Index)) 436 return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; 437 if (DIEValue Dval = Die.findAttribute(dwarf::DW_AT_ranges)) { 438 if (Dval.getForm() == dwarf::DW_FORM_rnglistx) 439 return DU.findRnglistFromIndex(Dval.getDIEInteger().getValue()); 440 441 return DU.findRnglistFromOffset(Dval.getDIEInteger().getValue()); 442 } 443 444 return DWARFAddressRangesVector(); 445 } 446 447 static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU, 448 const DIEValue &AttrVal) { 449 DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue()); 450 if (std::optional<object::SectionedAddress> SA = 451 DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU)) 452 return SA->Address; 453 return std::nullopt; 454 } 455 456 static std::unique_ptr<DIEStreamer> 457 createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile, 458 StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr, 459 GDBIndex &GDBIndexSection) { 460 461 std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>( 462 &DIEBldr, GDBIndexSection, DWARFLinkerBase::OutputFileType::Object, 463 OutFile, 464 [&](const Twine &Warning, StringRef Context, const DWARFDie *) {}); 465 Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName); 466 if (Err) 467 errs() 468 << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!" 469 << toString(std::move(Err)) << "\n"; 470 return Streamer; 471 } 472 473 static void emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer, 474 DWARFUnit &Unit) { 475 DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit); 476 Streamer.emitUnit(Unit, *UnitDIE); 477 } 478 479 static void emitDWOBuilder(const std::string &DWOName, 480 DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter, 481 DWARFUnit &SplitCU, DWARFUnit &CU, 482 DebugLocWriter &LocWriter, 483 DebugStrOffsetsWriter &StrOffstsWriter, 484 DebugStrWriter &StrWriter, GDBIndex &GDBIndexSection, 485 DebugRangesSectionWriter &TempRangesSectionWriter) { 486 // Populate debug_info and debug_abbrev for current dwo into StringRef. 487 DWODIEBuilder.generateAbbrevs(); 488 DWODIEBuilder.finish(); 489 490 SmallVector<char, 20> OutBuffer; 491 std::shared_ptr<raw_svector_ostream> ObjOS = 492 std::make_shared<raw_svector_ostream>(OutBuffer); 493 const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile(); 494 auto TheTriple = std::make_unique<Triple>(File->makeTriple()); 495 std::unique_ptr<DIEStreamer> Streamer = 496 createDIEStreamer(*TheTriple, *ObjOS, "DwoStreamerInitAug2", 497 DWODIEBuilder, GDBIndexSection); 498 if (SplitCU.getContext().getMaxDWOVersion() >= 5) { 499 for (std::unique_ptr<llvm::DWARFUnit> &CU : 500 SplitCU.getContext().dwo_info_section_units()) { 501 if (!CU->isTypeUnit()) 502 continue; 503 emitUnit(DWODIEBuilder, *Streamer, *CU.get()); 504 } 505 emitUnit(DWODIEBuilder, *Streamer, SplitCU); 506 } else { 507 for (std::unique_ptr<llvm::DWARFUnit> &CU : 508 SplitCU.getContext().dwo_compile_units()) 509 emitUnit(DWODIEBuilder, *Streamer, *CU.get()); 510 511 // emit debug_types sections for dwarf4 512 for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector()) 513 emitUnit(DWODIEBuilder, *Streamer, *CU); 514 } 515 516 Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(), 517 SplitCU.getContext().getMaxVersion()); 518 Streamer->finish(); 519 520 std::unique_ptr<MemoryBuffer> ObjectMemBuffer = 521 MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false); 522 std::unique_ptr<object::ObjectFile> Obj = cantFail( 523 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()), 524 "error creating in-memory object"); 525 526 DWARFRewriter::OverriddenSectionsMap OverriddenSections; 527 for (const SectionRef &Secs : Obj->sections()) { 528 StringRef Contents = cantFail(Secs.getContents()); 529 StringRef Name = cantFail(Secs.getName()); 530 DWARFSectionKind Kind = 531 StringSwitch<DWARFSectionKind>(Name) 532 .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV) 533 .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO) 534 .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES) 535 .Default(DWARFSectionKind::DW_SECT_EXT_unknown); 536 if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown) 537 continue; 538 OverriddenSections[Kind] = Contents; 539 } 540 Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter, 541 StrOffstsWriter, StrWriter, TempRangesSectionWriter); 542 } 543 544 using DWARFUnitVec = std::vector<DWARFUnit *>; 545 using CUPartitionVector = std::vector<DWARFUnitVec>; 546 /// Partitions CUs in to buckets. Bucket size is controlled by 547 /// cu-processing-batch-size. All the CUs that have cross CU reference reference 548 /// as a source are put in to the same initial bucket. 549 static CUPartitionVector partitionCUs(DWARFContext &DwCtx) { 550 CUPartitionVector Vec(2); 551 unsigned Counter = 0; 552 const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev(); 553 for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) { 554 Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet = 555 Abbr->getAbbreviationDeclarationSet(CU->getAbbreviationsOffset()); 556 if (!AbbrDeclSet) { 557 consumeError(AbbrDeclSet.takeError()); 558 return Vec; 559 } 560 bool CrossCURefFound = false; 561 for (const DWARFAbbreviationDeclaration &Decl : *AbbrDeclSet.get()) { 562 for (const DWARFAbbreviationDeclaration::AttributeSpec &Attr : 563 Decl.attributes()) { 564 if (Attr.Form == dwarf::DW_FORM_ref_addr) { 565 CrossCURefFound = true; 566 break; 567 } 568 } 569 if (CrossCURefFound) 570 break; 571 } 572 if (CrossCURefFound) { 573 Vec[0].push_back(CU.get()); 574 } else { 575 ++Counter; 576 Vec.back().push_back(CU.get()); 577 } 578 if (Counter % opts::BatchSize == 0 && !Vec.back().empty()) 579 Vec.push_back({}); 580 } 581 return Vec; 582 } 583 584 void DWARFRewriter::updateDebugInfo() { 585 ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info"); 586 if (!DebugInfo) 587 return; 588 589 ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>(); 590 StrWriter = std::make_unique<DebugStrWriter>(*BC.DwCtx, false); 591 StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>(BC); 592 593 /// Stores and serializes information that will be put into the 594 /// .debug_addr DWARF section. 595 std::unique_ptr<DebugAddrWriter> FinalAddrWriter; 596 597 if (BC.isDWARF5Used()) { 598 FinalAddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC); 599 RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>(); 600 } else { 601 FinalAddrWriter = std::make_unique<DebugAddrWriter>(&BC); 602 } 603 604 if (BC.isDWARFLegacyUsed()) { 605 LegacyRangesSectionWriter = std::make_unique<DebugRangesSectionWriter>(); 606 LegacyRangesSectionWriter->initSection(); 607 } 608 609 uint32_t CUIndex = 0; 610 std::mutex AccessMutex; 611 // Needs to be invoked in the same order as CUs are processed. 612 llvm::DenseMap<uint64_t, uint64_t> LocListWritersIndexByCU; 613 auto createRangeLocListAddressWriters = [&](DWARFUnit &CU) { 614 std::lock_guard<std::mutex> Lock(AccessMutex); 615 const uint16_t DwarfVersion = CU.getVersion(); 616 if (DwarfVersion >= 5) { 617 auto AddrW = std::make_unique<DebugAddrWriterDwarf5>( 618 &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase()); 619 RangeListsSectionWriter->setAddressWriter(AddrW.get()); 620 LocListWritersByCU[CUIndex] = 621 std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false, *AddrW); 622 623 if (std::optional<uint64_t> DWOId = CU.getDWOId()) { 624 assert(RangeListsWritersByCU.count(*DWOId) == 0 && 625 "RangeLists writer for DWO unit already exists."); 626 auto DWORangeListsSectionWriter = 627 std::make_unique<DebugRangeListsSectionWriter>(); 628 DWORangeListsSectionWriter->initSection(CU); 629 DWORangeListsSectionWriter->setAddressWriter(AddrW.get()); 630 RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter); 631 } 632 AddressWritersByCU[CU.getOffset()] = std::move(AddrW); 633 } else { 634 auto AddrW = 635 std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize()); 636 AddressWritersByCU[CU.getOffset()] = std::move(AddrW); 637 LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>(); 638 if (std::optional<uint64_t> DWOId = CU.getDWOId()) { 639 assert(LegacyRangesWritersByCU.count(*DWOId) == 0 && 640 "LegacyRangeLists writer for DWO unit already exists."); 641 auto LegacyRangesSectionWriterByCU = 642 std::make_unique<DebugRangesSectionWriter>(); 643 LegacyRangesSectionWriterByCU->initSection(CU); 644 LegacyRangesWritersByCU[*DWOId] = 645 std::move(LegacyRangesSectionWriterByCU); 646 } 647 } 648 LocListWritersIndexByCU[CU.getOffset()] = CUIndex++; 649 }; 650 651 DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC, 652 *StrWriter); 653 GDBIndex GDBIndexSection(BC); 654 auto processSplitCU = [&](DWARFUnit &Unit, DWARFUnit &SplitCU, 655 DebugRangesSectionWriter &TempRangesSectionWriter, 656 DebugAddrWriter &AddressWriter, 657 const std::string &DWOName, 658 const std::optional<std::string> &DwarfOutputPath, 659 DIEBuilder &DWODIEBuilder) { 660 DWODIEBuilder.buildDWOUnit(SplitCU); 661 DebugStrOffsetsWriter DWOStrOffstsWriter(BC); 662 DebugStrWriter DWOStrWriter((SplitCU).getContext(), true); 663 DWODIEBuilder.updateDWONameCompDirForTypes( 664 DWOStrOffstsWriter, DWOStrWriter, SplitCU, DwarfOutputPath, DWOName); 665 DebugLoclistWriter DebugLocDWoWriter(Unit, Unit.getVersion(), true, 666 AddressWriter); 667 668 updateUnitDebugInfo(SplitCU, DWODIEBuilder, DebugLocDWoWriter, 669 TempRangesSectionWriter, AddressWriter); 670 DebugLocDWoWriter.finalize(DWODIEBuilder, 671 *DWODIEBuilder.getUnitDIEbyUnit(SplitCU)); 672 if (Unit.getVersion() >= 5) 673 TempRangesSectionWriter.finalizeSection(); 674 675 emitDWOBuilder(DWOName, DWODIEBuilder, *this, SplitCU, Unit, 676 DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter, 677 GDBIndexSection, TempRangesSectionWriter); 678 }; 679 auto processMainBinaryCU = [&](DWARFUnit &Unit, DIEBuilder &DIEBlder) { 680 std::optional<DWARFUnit *> SplitCU; 681 std::optional<uint64_t> RangesBase; 682 std::optional<uint64_t> DWOId = Unit.getDWOId(); 683 if (DWOId) 684 SplitCU = BC.getDWOCU(*DWOId); 685 DebugLocWriter &DebugLocWriter = 686 *LocListWritersByCU[LocListWritersIndexByCU[Unit.getOffset()]].get(); 687 DebugRangesSectionWriter &RangesSectionWriter = 688 Unit.getVersion() >= 5 ? *RangeListsSectionWriter.get() 689 : *LegacyRangesSectionWriter.get(); 690 DebugAddrWriter &AddressWriter = 691 *AddressWritersByCU[Unit.getOffset()].get(); 692 if (Unit.getVersion() >= 5) 693 RangeListsSectionWriter->setAddressWriter(&AddressWriter); 694 if (Unit.getVersion() >= 5) { 695 RangesBase = RangesSectionWriter.getSectionOffset() + 696 getDWARF5RngListLocListHeaderSize(); 697 RangesSectionWriter.initSection(Unit); 698 if (!SplitCU) 699 StrOffstsWriter->finalizeSection(Unit, DIEBlder); 700 } else if (SplitCU) { 701 RangesBase = LegacyRangesSectionWriter.get()->getSectionOffset(); 702 } 703 704 updateUnitDebugInfo(Unit, DIEBlder, DebugLocWriter, RangesSectionWriter, 705 AddressWriter, RangesBase); 706 DebugLocWriter.finalize(DIEBlder, *DIEBlder.getUnitDIEbyUnit(Unit)); 707 if (Unit.getVersion() >= 5) 708 RangesSectionWriter.finalizeSection(); 709 }; 710 711 DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable); 712 DIEBlder.buildTypeUnits(StrOffstsWriter.get()); 713 SmallVector<char, 20> OutBuffer; 714 std::unique_ptr<raw_svector_ostream> ObjOS = 715 std::make_unique<raw_svector_ostream>(OutBuffer); 716 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile(); 717 auto TheTriple = std::make_unique<Triple>(File->makeTriple()); 718 std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer( 719 *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection); 720 CUOffsetMap OffsetMap = 721 finalizeTypeSections(DIEBlder, *Streamer, GDBIndexSection); 722 723 CUPartitionVector PartVec = partitionCUs(*BC.DwCtx); 724 const unsigned int ThreadCount = 725 std::min(opts::DebugThreadCount, opts::ThreadCount); 726 for (std::vector<DWARFUnit *> &Vec : PartVec) { 727 DIEBlder.buildCompileUnits(Vec); 728 llvm::SmallVector<std::unique_ptr<DIEBuilder>, 72> DWODIEBuildersByCU; 729 ThreadPoolInterface &ThreadPool = 730 ParallelUtilities::getThreadPool(ThreadCount); 731 for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) { 732 createRangeLocListAddressWriters(*CU); 733 std::optional<DWARFUnit *> SplitCU; 734 std::optional<uint64_t> DWOId = CU->getDWOId(); 735 if (DWOId) 736 SplitCU = BC.getDWOCU(*DWOId); 737 if (!SplitCU) 738 continue; 739 DebugAddrWriter &AddressWriter = 740 *AddressWritersByCU[CU->getOffset()].get(); 741 DebugRangesSectionWriter &TempRangesSectionWriter = 742 CU->getVersion() >= 5 ? *RangeListsWritersByCU[*DWOId].get() 743 : *LegacyRangesWritersByCU[*DWOId].get(); 744 std::optional<std::string> DwarfOutputPath = 745 opts::DwarfOutputPath.empty() 746 ? std::nullopt 747 : std::optional<std::string>(opts::DwarfOutputPath.c_str()); 748 std::string DWOName = DIEBlder.updateDWONameCompDir( 749 *StrOffstsWriter, *StrWriter, *CU, DwarfOutputPath, std::nullopt); 750 auto DWODIEBuilderPtr = std::make_unique<DIEBuilder>( 751 BC, &(**SplitCU).getContext(), DebugNamesTable, CU); 752 DIEBuilder &DWODIEBuilder = 753 *DWODIEBuildersByCU.emplace_back(std::move(DWODIEBuilderPtr)).get(); 754 if (CU->getVersion() >= 5) 755 StrOffstsWriter->finalizeSection(*CU, DIEBlder); 756 // Important to capture CU and SplitCU by value here, otherwise when the 757 // thread is executed at some point after the current iteration of the 758 // loop, dereferencing CU/SplitCU in the call to processSplitCU means it 759 // will dereference a different variable than the one intended, causing a 760 // seg fault. 761 ThreadPool.async([&, DwarfOutputPath, DWOName, CU, SplitCU] { 762 processSplitCU(*CU, **SplitCU, TempRangesSectionWriter, AddressWriter, 763 DWOName, DwarfOutputPath, DWODIEBuilder); 764 }); 765 } 766 ThreadPool.wait(); 767 for (std::unique_ptr<DIEBuilder> &DWODIEBuilderPtr : DWODIEBuildersByCU) 768 DWODIEBuilderPtr->updateDebugNamesTable(); 769 for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) 770 processMainBinaryCU(*CU, DIEBlder); 771 finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap, 772 DIEBlder.getProcessedCUs(), *FinalAddrWriter); 773 } 774 775 DebugNamesTable.emitAccelTable(); 776 777 finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS, OffsetMap, 778 *FinalAddrWriter); 779 GDBIndexSection.updateGdbIndexSection(OffsetMap, CUIndex, 780 *ARangesSectionWriter); 781 } 782 783 void DWARFRewriter::updateUnitDebugInfo( 784 DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter, 785 DebugRangesSectionWriter &RangesSectionWriter, 786 DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase) { 787 // Cache debug ranges so that the offset for identical ranges could be reused. 788 std::map<DebugAddressRangesVector, uint64_t> CachedRanges; 789 790 uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize(); 791 uint64_t NextCUOffset = Unit.getNextUnitOffset(); 792 const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs = 793 DIEBldr.getDIEsByUnit(Unit); 794 795 // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc. 796 auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal, 797 const DIEValue &HighPCVal, uint64_t LowPC, 798 const uint64_t HighPC) { 799 dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc; 800 dwarf::Form FormLowPC = dwarf::DW_FORM_addr; 801 dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc; 802 dwarf::Form FormHighPC = dwarf::DW_FORM_data4; 803 const uint32_t Size = HighPC - LowPC; 804 // Whatever was generated is not low_pc/high_pc, so will reset to 805 // default for size 1. 806 if (!LowPCVal || !HighPCVal) { 807 if (Unit.getVersion() >= 5) 808 FormLowPC = dwarf::DW_FORM_addrx; 809 else if (Unit.isDWOUnit()) 810 FormLowPC = dwarf::DW_FORM_GNU_addr_index; 811 } else { 812 AttrLowPC = LowPCVal.getAttribute(); 813 FormLowPC = LowPCVal.getForm(); 814 AttrHighPC = HighPCVal.getAttribute(); 815 FormHighPC = HighPCVal.getForm(); 816 } 817 818 if (FormLowPC == dwarf::DW_FORM_addrx || 819 FormLowPC == dwarf::DW_FORM_GNU_addr_index) 820 LowPC = AddressWriter.getIndexFromAddress(LowPC, Unit); 821 822 if (LowPCVal) 823 DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC)); 824 else 825 DIEBldr.addValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC)); 826 if (HighPCVal) { 827 DIEBldr.replaceValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size)); 828 } else { 829 DIEBldr.deleteValue(Die, dwarf::DW_AT_ranges); 830 DIEBldr.addValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size)); 831 } 832 }; 833 834 for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) { 835 DIE *Die = DI->Die; 836 switch (Die->getTag()) { 837 case dwarf::DW_TAG_compile_unit: 838 case dwarf::DW_TAG_skeleton_unit: { 839 // For dwarf5 section 3.1.3 840 // The following attributes are not part of a split full compilation unit 841 // entry but instead are inherited (if present) from the corresponding 842 // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, 843 // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base, 844 // DW_AT_addr_base and DW_AT_rnglists_base. 845 if (Unit.getVersion() == 5 && Unit.isDWOUnit()) 846 continue; 847 auto ModuleRangesOrError = getDIEAddressRanges(*Die, Unit); 848 if (!ModuleRangesOrError) { 849 consumeError(ModuleRangesOrError.takeError()); 850 break; 851 } 852 DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError; 853 DebugAddressRangesVector OutputRanges = 854 BC.translateModuleAddressRanges(ModuleRanges); 855 DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc); 856 // For a case where LLD GCs only function used in the CU. 857 // If CU doesn't have DW_AT_low_pc we are not going to convert, 858 // so don't need to do anything. 859 if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo) 860 OutputRanges.push_back({0, 0}); 861 const uint64_t RangesSectionOffset = 862 RangesSectionWriter.addRanges(OutputRanges); 863 // Don't emit the zero low_pc arange. 864 if (!Unit.isDWOUnit() && !OutputRanges.empty() && 865 OutputRanges.back().LowPC) 866 ARangesSectionWriter->addCURanges(Unit.getOffset(), 867 std::move(OutputRanges)); 868 updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset, 869 RangesBase); 870 DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list); 871 if (LineTablePatchMap.count(&Unit)) 872 DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list, 873 StmtListAttrVal.getForm(), 874 DIEInteger(LineTablePatchMap[&Unit])); 875 break; 876 } 877 878 case dwarf::DW_TAG_subprogram: { 879 // Get function address either from ranges or [LowPC, HighPC) pair. 880 uint64_t Address = UINT64_MAX; 881 uint64_t SectionIndex, HighPC; 882 DebugAddressRangesVector FunctionRanges; 883 if (!getLowAndHighPC(*Die, Unit, Address, HighPC, SectionIndex)) { 884 Expected<DWARFAddressRangesVector> RangesOrError = 885 getDIEAddressRanges(*Die, Unit); 886 if (!RangesOrError) { 887 consumeError(RangesOrError.takeError()); 888 break; 889 } 890 DWARFAddressRangesVector Ranges = *RangesOrError; 891 // Not a function definition. 892 if (Ranges.empty()) 893 break; 894 895 for (const DWARFAddressRange &Range : Ranges) { 896 if (const BinaryFunction *Function = 897 BC.getBinaryFunctionAtAddress(Range.LowPC)) 898 FunctionRanges.append(Function->getOutputAddressRanges()); 899 } 900 } else { 901 if (const BinaryFunction *Function = 902 BC.getBinaryFunctionAtAddress(Address)) 903 FunctionRanges = Function->getOutputAddressRanges(); 904 } 905 906 // Clear cached ranges as the new function will have its own set. 907 CachedRanges.clear(); 908 DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc); 909 DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc); 910 if (FunctionRanges.empty()) { 911 if (LowPCVal && HighPCVal) 912 FunctionRanges.push_back({0, HighPCVal.getDIEInteger().getValue()}); 913 else 914 FunctionRanges.push_back({0, 1}); 915 } 916 917 if (FunctionRanges.size() == 1 && !opts::AlwaysConvertToRanges) { 918 updateLowPCHighPC(Die, LowPCVal, HighPCVal, FunctionRanges.back().LowPC, 919 FunctionRanges.back().HighPC); 920 break; 921 } 922 923 updateDWARFObjectAddressRanges( 924 Unit, DIEBldr, *Die, RangesSectionWriter.addRanges(FunctionRanges)); 925 926 break; 927 } 928 case dwarf::DW_TAG_lexical_block: 929 case dwarf::DW_TAG_inlined_subroutine: 930 case dwarf::DW_TAG_try_block: 931 case dwarf::DW_TAG_catch_block: { 932 uint64_t RangesSectionOffset = 0; 933 Expected<DWARFAddressRangesVector> RangesOrError = 934 getDIEAddressRanges(*Die, Unit); 935 const BinaryFunction *Function = 936 RangesOrError && !RangesOrError->empty() 937 ? BC.getBinaryFunctionContainingAddress( 938 RangesOrError->front().LowPC) 939 : nullptr; 940 DebugAddressRangesVector OutputRanges; 941 if (Function) { 942 OutputRanges = translateInputToOutputRanges(*Function, *RangesOrError); 943 LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) { 944 dbgs() << "BOLT-DEBUG: problem with DIE at 0x" 945 << Twine::utohexstr(Die->getOffset()) << " in CU at 0x" 946 << Twine::utohexstr(Unit.getOffset()) << '\n'; 947 }); 948 if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) { 949 RangesSectionOffset = RangesSectionWriter.addRanges( 950 std::move(OutputRanges), CachedRanges); 951 OutputRanges.clear(); 952 } else if (OutputRanges.empty()) { 953 OutputRanges.push_back({0, RangesOrError.get().front().HighPC}); 954 } 955 } else if (!RangesOrError) { 956 consumeError(RangesOrError.takeError()); 957 } else { 958 OutputRanges.push_back({0, !RangesOrError->empty() 959 ? RangesOrError.get().front().HighPC 960 : 0}); 961 } 962 DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc); 963 DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc); 964 if (OutputRanges.size() == 1) { 965 updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC, 966 OutputRanges.back().HighPC); 967 break; 968 } 969 updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset); 970 break; 971 } 972 case dwarf::DW_TAG_call_site: { 973 auto patchPC = [&](DIE *Die, DIEValue &AttrVal, StringRef Entry) -> void { 974 std::optional<uint64_t> Address = getAsAddress(Unit, AttrVal); 975 const BinaryFunction *Function = 976 BC.getBinaryFunctionContainingAddress(*Address); 977 uint64_t UpdatedAddress = *Address; 978 if (Function) 979 UpdatedAddress = 980 Function->translateInputToOutputAddress(UpdatedAddress); 981 982 if (AttrVal.getForm() == dwarf::DW_FORM_addrx) { 983 const uint32_t Index = 984 AddressWriter.getIndexFromAddress(UpdatedAddress, Unit); 985 DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(), 986 DIEInteger(Index)); 987 } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) { 988 DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(), 989 DIEInteger(UpdatedAddress)); 990 } else { 991 errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n"; 992 } 993 }; 994 DIEValue CallPcAttrVal = Die->findAttribute(dwarf::DW_AT_call_pc); 995 if (CallPcAttrVal) 996 patchPC(Die, CallPcAttrVal, "DW_AT_call_pc"); 997 998 DIEValue CallRetPcAttrVal = 999 Die->findAttribute(dwarf::DW_AT_call_return_pc); 1000 if (CallRetPcAttrVal) 1001 patchPC(Die, CallRetPcAttrVal, "DW_AT_call_return_pc"); 1002 1003 break; 1004 } 1005 default: { 1006 // Handle any tag that can have DW_AT_location attribute. 1007 DIEValue LocAttrInfo = Die->findAttribute(dwarf::DW_AT_location); 1008 DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc); 1009 if (LocAttrInfo) { 1010 if (doesFormBelongToClass(LocAttrInfo.getForm(), 1011 DWARFFormValue::FC_Constant, 1012 Unit.getVersion()) || 1013 doesFormBelongToClass(LocAttrInfo.getForm(), 1014 DWARFFormValue::FC_SectionOffset, 1015 Unit.getVersion())) { 1016 uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx 1017 ? LocAttrInfo.getDIELocList().getValue() 1018 : LocAttrInfo.getDIEInteger().getValue(); 1019 DebugLocationsVector InputLL; 1020 1021 std::optional<object::SectionedAddress> SectionAddress = 1022 Unit.getBaseAddress(); 1023 uint64_t BaseAddress = 0; 1024 if (SectionAddress) 1025 BaseAddress = SectionAddress->Address; 1026 1027 if (Unit.getVersion() >= 5 && 1028 LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx) { 1029 std::optional<uint64_t> LocOffset = Unit.getLoclistOffset(Offset); 1030 assert(LocOffset && "Location Offset is invalid."); 1031 Offset = *LocOffset; 1032 } 1033 1034 Error E = Unit.getLocationTable().visitLocationList( 1035 &Offset, [&](const DWARFLocationEntry &Entry) { 1036 switch (Entry.Kind) { 1037 default: 1038 llvm_unreachable("Unsupported DWARFLocationEntry Kind."); 1039 case dwarf::DW_LLE_end_of_list: 1040 return false; 1041 case dwarf::DW_LLE_base_address: { 1042 assert(Entry.SectionIndex == SectionedAddress::UndefSection && 1043 "absolute address expected"); 1044 BaseAddress = Entry.Value0; 1045 break; 1046 } 1047 case dwarf::DW_LLE_offset_pair: 1048 assert( 1049 (Entry.SectionIndex == SectionedAddress::UndefSection && 1050 (!Unit.isDWOUnit() || Unit.getVersion() == 5)) && 1051 "absolute address expected"); 1052 InputLL.emplace_back(DebugLocationEntry{ 1053 BaseAddress + Entry.Value0, BaseAddress + Entry.Value1, 1054 Entry.Loc}); 1055 break; 1056 case dwarf::DW_LLE_start_length: 1057 InputLL.emplace_back(DebugLocationEntry{ 1058 Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc}); 1059 break; 1060 case dwarf::DW_LLE_base_addressx: { 1061 std::optional<object::SectionedAddress> EntryAddress = 1062 Unit.getAddrOffsetSectionItem(Entry.Value0); 1063 assert(EntryAddress && "base Address not found."); 1064 BaseAddress = EntryAddress->Address; 1065 break; 1066 } 1067 case dwarf::DW_LLE_startx_length: { 1068 std::optional<object::SectionedAddress> EntryAddress = 1069 Unit.getAddrOffsetSectionItem(Entry.Value0); 1070 assert(EntryAddress && "Address does not exist."); 1071 InputLL.emplace_back(DebugLocationEntry{ 1072 EntryAddress->Address, 1073 EntryAddress->Address + Entry.Value1, Entry.Loc}); 1074 break; 1075 } 1076 case dwarf::DW_LLE_startx_endx: { 1077 std::optional<object::SectionedAddress> StartAddress = 1078 Unit.getAddrOffsetSectionItem(Entry.Value0); 1079 assert(StartAddress && "Start Address does not exist."); 1080 std::optional<object::SectionedAddress> EndAddress = 1081 Unit.getAddrOffsetSectionItem(Entry.Value1); 1082 assert(EndAddress && "Start Address does not exist."); 1083 InputLL.emplace_back(DebugLocationEntry{ 1084 StartAddress->Address, EndAddress->Address, Entry.Loc}); 1085 break; 1086 } 1087 } 1088 return true; 1089 }); 1090 1091 if (E || InputLL.empty()) { 1092 consumeError(std::move(E)); 1093 errs() << "BOLT-WARNING: empty location list detected at 0x" 1094 << Twine::utohexstr(Offset) << " for DIE at 0x" << Die 1095 << " in CU at 0x" << Twine::utohexstr(Unit.getOffset()) 1096 << '\n'; 1097 } else { 1098 const uint64_t Address = InputLL.front().LowPC; 1099 DebugLocationsVector OutputLL; 1100 if (const BinaryFunction *Function = 1101 BC.getBinaryFunctionContainingAddress(Address)) { 1102 OutputLL = translateInputToOutputLocationList(*Function, InputLL); 1103 LLVM_DEBUG(if (OutputLL.empty()) { 1104 dbgs() << "BOLT-DEBUG: location list translated to an empty " 1105 "one at 0x" 1106 << Die << " in CU at 0x" 1107 << Twine::utohexstr(Unit.getOffset()) << '\n'; 1108 }); 1109 } else { 1110 // It's possible for a subprogram to be removed and to have 1111 // address of 0. Adding this entry to output to preserve debug 1112 // information. 1113 OutputLL = InputLL; 1114 } 1115 DebugLocWriter.addList(DIEBldr, *Die, LocAttrInfo, OutputLL); 1116 } 1117 } else { 1118 assert((doesFormBelongToClass(LocAttrInfo.getForm(), 1119 DWARFFormValue::FC_Exprloc, 1120 Unit.getVersion()) || 1121 doesFormBelongToClass(LocAttrInfo.getForm(), 1122 DWARFFormValue::FC_Block, 1123 Unit.getVersion())) && 1124 "unexpected DW_AT_location form"); 1125 if (Unit.isDWOUnit() || Unit.getVersion() >= 5) { 1126 std::vector<uint8_t> Sblock; 1127 DIEValueList *AttrLocValList; 1128 if (doesFormBelongToClass(LocAttrInfo.getForm(), 1129 DWARFFormValue::FC_Exprloc, 1130 Unit.getVersion())) { 1131 for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) { 1132 Sblock.push_back(Val.getDIEInteger().getValue()); 1133 } 1134 DIELoc *LocAttr = const_cast<DIELoc *>(&LocAttrInfo.getDIELoc()); 1135 AttrLocValList = static_cast<DIEValueList *>(LocAttr); 1136 } else { 1137 for (const DIEValue &Val : LocAttrInfo.getDIEBlock().values()) { 1138 Sblock.push_back(Val.getDIEInteger().getValue()); 1139 } 1140 DIEBlock *BlockAttr = 1141 const_cast<DIEBlock *>(&LocAttrInfo.getDIEBlock()); 1142 AttrLocValList = static_cast<DIEValueList *>(BlockAttr); 1143 } 1144 ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock); 1145 DataExtractor Data( 1146 StringRef((const char *)Expr.data(), Expr.size()), 1147 Unit.getContext().isLittleEndian(), 0); 1148 DWARFExpression LocExpr(Data, Unit.getAddressByteSize(), 1149 Unit.getFormParams().Format); 1150 uint32_t PrevOffset = 0; 1151 DIEValueList *NewAttr; 1152 DIEValue Value; 1153 uint32_t NewExprSize = 0; 1154 DIELoc *Loc = nullptr; 1155 DIEBlock *Block = nullptr; 1156 if (LocAttrInfo.getForm() == dwarf::DW_FORM_exprloc) { 1157 Loc = DIEBldr.allocateDIEValue<DIELoc>(); 1158 NewAttr = Loc; 1159 Value = DIEValue(LocAttrInfo.getAttribute(), 1160 LocAttrInfo.getForm(), Loc); 1161 } else if (doesFormBelongToClass(LocAttrInfo.getForm(), 1162 DWARFFormValue::FC_Block, 1163 Unit.getVersion())) { 1164 Block = DIEBldr.allocateDIEValue<DIEBlock>(); 1165 NewAttr = Block; 1166 Value = DIEValue(LocAttrInfo.getAttribute(), 1167 LocAttrInfo.getForm(), Block); 1168 } else { 1169 errs() << "BOLT-WARNING: Unexpected Form value in Updating " 1170 "DW_AT_Location\n"; 1171 continue; 1172 } 1173 1174 for (const DWARFExpression::Operation &Expr : LocExpr) { 1175 uint32_t CurEndOffset = PrevOffset + 1; 1176 if (Expr.getDescription().Op.size() == 1) 1177 CurEndOffset = Expr.getOperandEndOffset(0); 1178 if (Expr.getDescription().Op.size() == 2) 1179 CurEndOffset = Expr.getOperandEndOffset(1); 1180 if (Expr.getDescription().Op.size() > 2) 1181 errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported " 1182 "number of operands.\n"; 1183 // not addr index, just copy. 1184 if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index || 1185 Expr.getCode() == dwarf::DW_OP_addrx)) { 1186 auto Itr = AttrLocValList->values().begin(); 1187 std::advance(Itr, PrevOffset); 1188 uint32_t CopyNum = CurEndOffset - PrevOffset; 1189 NewExprSize += CopyNum; 1190 while (CopyNum--) { 1191 DIEBldr.addValue(NewAttr, *Itr); 1192 std::advance(Itr, 1); 1193 } 1194 } else { 1195 const uint64_t Index = Expr.getRawOperand(0); 1196 std::optional<object::SectionedAddress> EntryAddress = 1197 Unit.getAddrOffsetSectionItem(Index); 1198 assert(EntryAddress && "Address is not found."); 1199 assert(Index <= std::numeric_limits<uint32_t>::max() && 1200 "Invalid Operand Index."); 1201 const uint32_t AddrIndex = AddressWriter.getIndexFromAddress( 1202 EntryAddress->Address, Unit); 1203 // update Index into .debug_address section for DW_AT_location. 1204 // The Size field is not stored in IR, we need to minus 1 in 1205 // offset for each expr. 1206 SmallString<8> Tmp; 1207 raw_svector_ostream OSE(Tmp); 1208 encodeULEB128(AddrIndex, OSE); 1209 1210 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0), 1211 dwarf::DW_FORM_data1, 1212 DIEInteger(Expr.getCode())); 1213 NewExprSize += 1; 1214 for (uint8_t Byte : Tmp) { 1215 DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0), 1216 dwarf::DW_FORM_data1, DIEInteger(Byte)); 1217 NewExprSize += 1; 1218 } 1219 } 1220 PrevOffset = CurEndOffset; 1221 } 1222 1223 // update the size since the index might be changed 1224 if (Loc) 1225 Loc->setSize(NewExprSize); 1226 else 1227 Block->setSize(NewExprSize); 1228 DIEBldr.replaceValue(Die, LocAttrInfo.getAttribute(), 1229 LocAttrInfo.getForm(), Value); 1230 } 1231 } 1232 } else if (LowPCAttrInfo) { 1233 uint64_t Address = 0; 1234 uint64_t SectionIndex = 0; 1235 if (getLowPC(*Die, Unit, Address, SectionIndex)) { 1236 uint64_t NewAddress = 0; 1237 if (const BinaryFunction *Function = 1238 BC.getBinaryFunctionContainingAddress(Address)) { 1239 NewAddress = Function->translateInputToOutputAddress(Address); 1240 LLVM_DEBUG(dbgs() 1241 << "BOLT-DEBUG: Fixing low_pc 0x" 1242 << Twine::utohexstr(Address) << " for DIE with tag " 1243 << Die->getTag() << " to 0x" 1244 << Twine::utohexstr(NewAddress) << '\n'); 1245 } 1246 1247 dwarf::Form Form = LowPCAttrInfo.getForm(); 1248 assert(Form != dwarf::DW_FORM_LLVM_addrx_offset && 1249 "DW_FORM_LLVM_addrx_offset is not supported"); 1250 std::lock_guard<std::mutex> Lock(DWARFRewriterMutex); 1251 if (Form == dwarf::DW_FORM_addrx || 1252 Form == dwarf::DW_FORM_GNU_addr_index) { 1253 const uint32_t Index = AddressWriter.getIndexFromAddress( 1254 NewAddress ? NewAddress : Address, Unit); 1255 DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(), 1256 LowPCAttrInfo.getForm(), DIEInteger(Index)); 1257 } else { 1258 DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(), 1259 LowPCAttrInfo.getForm(), 1260 DIEInteger(NewAddress)); 1261 } 1262 } else if (opts::Verbosity >= 1) { 1263 errs() << "BOLT-WARNING: unexpected form value for attribute " 1264 "LowPCAttrInfo\n"; 1265 } 1266 } 1267 } 1268 } 1269 } 1270 if (DIEOffset > NextCUOffset) 1271 errs() << "BOLT-WARNING: corrupt DWARF detected at 0x" 1272 << Twine::utohexstr(Unit.getOffset()) << '\n'; 1273 } 1274 1275 void DWARFRewriter::updateDWARFObjectAddressRanges( 1276 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset, 1277 std::optional<uint64_t> RangesBase) { 1278 1279 if (RangesBase) { 1280 // If DW_AT_GNU_ranges_base is present, update it. No further modifications 1281 // are needed for ranges base. 1282 1283 DIEValue RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_GNU_ranges_base); 1284 if (!RangesBaseInfo) { 1285 RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_rnglists_base); 1286 } 1287 1288 if (RangesBaseInfo) { 1289 if (RangesBaseInfo.getAttribute() == dwarf::DW_AT_GNU_ranges_base) { 1290 auto RangesWriterIterator = 1291 LegacyRangesWritersByCU.find(*Unit.getDWOId()); 1292 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() && 1293 "RangesWriter does not exist for DWOId"); 1294 RangesWriterIterator->second->setDie(&Die); 1295 } else { 1296 DIEBldr.replaceValue(&Die, RangesBaseInfo.getAttribute(), 1297 RangesBaseInfo.getForm(), 1298 DIEInteger(static_cast<uint32_t>(*RangesBase))); 1299 } 1300 RangesBase = std::nullopt; 1301 } 1302 } 1303 1304 DIEValue LowPCAttrInfo = Die.findAttribute(dwarf::DW_AT_low_pc); 1305 DIEValue RangesAttrInfo = Die.findAttribute(dwarf::DW_AT_ranges); 1306 if (RangesAttrInfo) { 1307 // Case 1: The object was already non-contiguous and had DW_AT_ranges. 1308 // In this case we simply need to update the value of DW_AT_ranges 1309 // and introduce DW_AT_GNU_ranges_base if required. 1310 // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx 1311 bool NeedConverted = false; 1312 1313 if (Unit.getVersion() >= 5 && 1314 RangesAttrInfo.getForm() == dwarf::DW_FORM_sec_offset) 1315 NeedConverted = true; 1316 1317 if (NeedConverted || RangesAttrInfo.getForm() == dwarf::DW_FORM_rnglistx) 1318 DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx, 1319 DIEInteger(DebugRangesOffset)); 1320 else 1321 DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, RangesAttrInfo.getForm(), 1322 DIEInteger(DebugRangesOffset)); 1323 1324 if (!RangesBase) { 1325 if (LowPCAttrInfo && 1326 LowPCAttrInfo.getForm() != dwarf::DW_FORM_GNU_addr_index && 1327 LowPCAttrInfo.getForm() != dwarf::DW_FORM_addrx) 1328 DIEBldr.replaceValue(&Die, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm(), 1329 DIEInteger(0)); 1330 return; 1331 } 1332 1333 if (!(Die.getTag() == dwarf::DW_TAG_compile_unit || 1334 Die.getTag() == dwarf::DW_TAG_skeleton_unit)) 1335 return; 1336 1337 // If we are at this point we are in the CU/Skeleton CU, and 1338 // DW_AT_GNU_ranges_base or DW_AT_rnglists_base doesn't exist. 1339 if (Unit.getVersion() <= 4) { 1340 DIEBldr.addValue(&Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4, 1341 DIEInteger(INT_MAX)); 1342 auto RangesWriterIterator = 1343 LegacyRangesWritersByCU.find(*Unit.getDWOId()); 1344 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() && 1345 "RangesWriter does not exist for DWOId"); 1346 RangesWriterIterator->second->setDie(&Die); 1347 } else if (Unit.getVersion() >= 5) { 1348 DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base, 1349 dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase)); 1350 } 1351 return; 1352 } 1353 1354 // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back 1355 // to back. Replace with new attributes and patch the DIE. 1356 DIEValue HighPCAttrInfo = Die.findAttribute(dwarf::DW_AT_high_pc); 1357 if (LowPCAttrInfo && HighPCAttrInfo) { 1358 1359 convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, DebugRangesOffset, 1360 LowPCAttrInfo, HighPCAttrInfo, RangesBase); 1361 } else if (!(Unit.isDWOUnit() && 1362 Die.getTag() == dwarf::DW_TAG_compile_unit)) { 1363 if (opts::Verbosity >= 1) 1364 errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x" 1365 << Twine::utohexstr(Unit.getOffset()) << '\n'; 1366 } 1367 } 1368 1369 void DWARFRewriter::updateLineTableOffsets(const MCAssembler &Asm) { 1370 ErrorOr<BinarySection &> DbgInfoSection = 1371 BC.getUniqueSectionByName(".debug_info"); 1372 ErrorOr<BinarySection &> TypeInfoSection = 1373 BC.getUniqueSectionByName(".debug_types"); 1374 assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) || 1375 BC.DwCtx->getNumTypeUnits() == 0) && 1376 "Was not able to retrieve Debug Types section."); 1377 1378 // There is no direct connection between CU and TU, but same offsets, 1379 // encoded in DW_AT_stmt_list, into .debug_line get modified. 1380 // We take advantage of that to map original CU line table offsets to new 1381 // ones. 1382 std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap; 1383 1384 auto GetStatementListValue = 1385 [](const DWARFDie &DIE) -> std::optional<uint64_t> { 1386 std::optional<DWARFFormValue> StmtList = DIE.find(dwarf::DW_AT_stmt_list); 1387 if (!StmtList) 1388 return std::nullopt; 1389 std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList); 1390 assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list."); 1391 return *Offset; 1392 }; 1393 1394 SmallVector<DWARFUnit *, 1> TUs; 1395 for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->info_section_units()) { 1396 if (CU->isTypeUnit()) { 1397 TUs.push_back(CU.get()); 1398 continue; 1399 } 1400 const unsigned CUID = CU->getOffset(); 1401 MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel(); 1402 if (!Label) 1403 continue; 1404 1405 std::optional<uint64_t> StmtOffset = 1406 GetStatementListValue(CU.get()->getUnitDIE()); 1407 if (!StmtOffset) 1408 continue; 1409 1410 const uint64_t LineTableOffset = 1411 Asm.getSymbolOffset(*Label); 1412 DebugLineOffsetMap[*StmtOffset] = LineTableOffset; 1413 assert(DbgInfoSection && ".debug_info section must exist"); 1414 LineTablePatchMap[CU.get()] = LineTableOffset; 1415 } 1416 1417 for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units()) 1418 TUs.push_back(TU.get()); 1419 1420 for (DWARFUnit *TU : TUs) { 1421 std::optional<uint64_t> StmtOffset = 1422 GetStatementListValue(TU->getUnitDIE()); 1423 if (!StmtOffset) 1424 continue; 1425 auto Iter = DebugLineOffsetMap.find(*StmtOffset); 1426 if (Iter == DebugLineOffsetMap.end()) { 1427 // Implementation depends on TU sharing DW_AT_stmt_list with a CU. 1428 // Only case that it hasn't been true was for manually modified assembly 1429 // file. Adding this warning in case assumption is false. 1430 errs() 1431 << "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x" 1432 << Twine::utohexstr(TU->getOffset()) 1433 << " is not sharing " 1434 ".debug_line entry with CU. DW_AT_stmt_list for this TU won't be " 1435 "updated.\n"; 1436 continue; 1437 } 1438 TypeUnitRelocMap[TU] = Iter->second; 1439 } 1440 1441 // Set .debug_info as finalized so it won't be skipped over when 1442 // we process sections while writing out the new binary. This ensures 1443 // that the pending relocations will be processed and not ignored. 1444 if (DbgInfoSection) 1445 DbgInfoSection->setIsFinalized(); 1446 1447 if (TypeInfoSection) 1448 TypeInfoSection->setIsFinalized(); 1449 } 1450 1451 CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder, 1452 DIEStreamer &Streamer, 1453 GDBIndex &GDBIndexSection) { 1454 // update TypeUnit DW_AT_stmt_list with new .debug_line information. 1455 auto updateLineTable = [&](const DWARFUnit &Unit) -> void { 1456 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(Unit); 1457 DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list); 1458 if (!StmtAttrInfo || !TypeUnitRelocMap.count(&Unit)) 1459 return; 1460 DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list, 1461 StmtAttrInfo.getForm(), 1462 DIEInteger(TypeUnitRelocMap[&Unit])); 1463 }; 1464 1465 // generate and populate abbrevs here 1466 DIEBlder.generateAbbrevs(); 1467 DIEBlder.finish(); 1468 DIEBlder.updateDebugNamesTable(); 1469 SmallVector<char, 20> OutBuffer; 1470 std::shared_ptr<raw_svector_ostream> ObjOS = 1471 std::make_shared<raw_svector_ostream>(OutBuffer); 1472 const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile(); 1473 auto TheTriple = std::make_unique<Triple>(File->makeTriple()); 1474 std::unique_ptr<DIEStreamer> TypeStreamer = createDIEStreamer( 1475 *TheTriple, *ObjOS, "TypeStreamer", DIEBlder, GDBIndexSection); 1476 1477 // generate debug_info and CUMap 1478 CUOffsetMap CUMap; 1479 for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) { 1480 if (!CU->isTypeUnit()) 1481 continue; 1482 updateLineTable(*CU.get()); 1483 emitUnit(DIEBlder, Streamer, *CU.get()); 1484 uint32_t StartOffset = CUOffset; 1485 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU.get()); 1486 CUOffset += CU.get()->getHeaderSize(); 1487 CUOffset += UnitDIE->getSize(); 1488 CUMap[CU.get()->getOffset()] = {StartOffset, CUOffset - StartOffset - 4}; 1489 } 1490 1491 // Emit Type Unit of DWARF 4 to .debug_type section 1492 for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) { 1493 updateLineTable(*TU); 1494 emitUnit(DIEBlder, *TypeStreamer, *TU); 1495 } 1496 1497 TypeStreamer->finish(); 1498 1499 std::unique_ptr<MemoryBuffer> ObjectMemBuffer = 1500 MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false); 1501 std::unique_ptr<object::ObjectFile> Obj = cantFail( 1502 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()), 1503 "error creating in-memory object"); 1504 1505 for (const SectionRef &Section : Obj->sections()) { 1506 StringRef Contents = cantFail(Section.getContents()); 1507 StringRef Name = cantFail(Section.getName()); 1508 if (Name == ".debug_types") 1509 BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents), 1510 Contents.size()); 1511 } 1512 return CUMap; 1513 } 1514 1515 void DWARFRewriter::finalizeDebugSections( 1516 DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable, 1517 DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap, 1518 DebugAddrWriter &FinalAddrWriter) { 1519 if (StrWriter->isInitialized()) { 1520 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str"); 1521 std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents = 1522 StrWriter->releaseBuffer(); 1523 BC.registerOrUpdateNoteSection(".debug_str", 1524 copyByteArray(*DebugStrSectionContents), 1525 DebugStrSectionContents->size()); 1526 } 1527 1528 if (StrOffstsWriter->isFinalized()) { 1529 RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets"); 1530 std::unique_ptr<DebugStrOffsetsBufferVector> 1531 DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer(); 1532 BC.registerOrUpdateNoteSection( 1533 ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents), 1534 DebugStrOffsetsSectionContents->size()); 1535 } 1536 1537 if (BC.isDWARFLegacyUsed()) { 1538 std::unique_ptr<DebugBufferVector> RangesSectionContents = 1539 LegacyRangesSectionWriter->releaseBuffer(); 1540 BC.registerOrUpdateNoteSection(".debug_ranges", 1541 copyByteArray(*RangesSectionContents), 1542 RangesSectionContents->size()); 1543 } 1544 1545 if (BC.isDWARF5Used()) { 1546 std::unique_ptr<DebugBufferVector> RangesSectionContents = 1547 RangeListsSectionWriter->releaseBuffer(); 1548 BC.registerOrUpdateNoteSection(".debug_rnglists", 1549 copyByteArray(*RangesSectionContents), 1550 RangesSectionContents->size()); 1551 } 1552 1553 if (BC.isDWARF5Used()) { 1554 std::unique_ptr<DebugBufferVector> LocationListSectionContents = 1555 makeFinalLocListsSection(DWARFVersion::DWARF5); 1556 if (!LocationListSectionContents->empty()) 1557 BC.registerOrUpdateNoteSection( 1558 ".debug_loclists", copyByteArray(*LocationListSectionContents), 1559 LocationListSectionContents->size()); 1560 } 1561 1562 if (BC.isDWARFLegacyUsed()) { 1563 std::unique_ptr<DebugBufferVector> LocationListSectionContents = 1564 makeFinalLocListsSection(DWARFVersion::DWARFLegacy); 1565 if (!LocationListSectionContents->empty()) 1566 BC.registerOrUpdateNoteSection( 1567 ".debug_loc", copyByteArray(*LocationListSectionContents), 1568 LocationListSectionContents->size()); 1569 } 1570 1571 if (FinalAddrWriter.isInitialized()) { 1572 std::unique_ptr<AddressSectionBuffer> AddressSectionContents = 1573 FinalAddrWriter.releaseBuffer(); 1574 BC.registerOrUpdateNoteSection(".debug_addr", 1575 copyByteArray(*AddressSectionContents), 1576 AddressSectionContents->size()); 1577 } 1578 1579 Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion()); 1580 Streamer.finish(); 1581 1582 std::unique_ptr<MemoryBuffer> ObjectMemBuffer = 1583 MemoryBuffer::getMemBuffer(ObjOS.str(), "in-memory object file", false); 1584 std::unique_ptr<object::ObjectFile> Obj = cantFail( 1585 object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()), 1586 "error creating in-memory object"); 1587 1588 for (const SectionRef &Secs : Obj->sections()) { 1589 StringRef Contents = cantFail(Secs.getContents()); 1590 StringRef Name = cantFail(Secs.getName()); 1591 if (Name == ".debug_abbrev") { 1592 BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents), 1593 Contents.size()); 1594 } else if (Name == ".debug_info") { 1595 BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents), 1596 Contents.size()); 1597 } 1598 } 1599 1600 // Skip .debug_aranges if we are re-generating .gdb_index. 1601 if (opts::KeepARanges || !BC.getGdbIndexSection()) { 1602 SmallVector<char, 16> ARangesBuffer; 1603 raw_svector_ostream OS(ARangesBuffer); 1604 1605 auto MAB = std::unique_ptr<MCAsmBackend>( 1606 BC.TheTarget->createMCAsmBackend(*BC.STI, *BC.MRI, MCTargetOptions())); 1607 1608 ARangesSectionWriter->writeARangesSection(OS, CUMap); 1609 const StringRef &ARangesContents = OS.str(); 1610 1611 BC.registerOrUpdateNoteSection(".debug_aranges", 1612 copyByteArray(ARangesContents), 1613 ARangesContents.size()); 1614 } 1615 1616 if (DebugNamesTable.isCreated()) { 1617 RewriteInstance::addToDebugSectionsToOverwrite(".debug_names"); 1618 std::unique_ptr<DebugBufferVector> DebugNamesSectionContents = 1619 DebugNamesTable.releaseBuffer(); 1620 BC.registerOrUpdateNoteSection(".debug_names", 1621 copyByteArray(*DebugNamesSectionContents), 1622 DebugNamesSectionContents->size()); 1623 } 1624 } 1625 1626 void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder, 1627 DIEStreamer &Streamer, 1628 CUOffsetMap &CUMap, 1629 const std::list<DWARFUnit *> &CUs, 1630 DebugAddrWriter &FinalAddrWriter) { 1631 for (DWARFUnit *CU : CUs) { 1632 auto AddressWriterIterator = AddressWritersByCU.find(CU->getOffset()); 1633 assert(AddressWriterIterator != AddressWritersByCU.end() && 1634 "AddressWriter does not exist for CU"); 1635 DebugAddrWriter *AddressWriter = AddressWriterIterator->second.get(); 1636 const size_t BufferOffset = FinalAddrWriter.getBufferSize(); 1637 std::optional<uint64_t> Offset = AddressWriter->finalize(BufferOffset); 1638 /// If Offset already exists in UnmodifiedAddressOffsets, then update with 1639 /// Offset, else update with BufferOffset. 1640 if (Offset) 1641 AddressWriter->updateAddrBase(DIEBlder, *CU, *Offset); 1642 else if (AddressWriter->isInitialized()) 1643 AddressWriter->updateAddrBase(DIEBlder, *CU, BufferOffset); 1644 if (AddressWriter->isInitialized()) { 1645 std::unique_ptr<AddressSectionBuffer> AddressSectionContents = 1646 AddressWriter->releaseBuffer(); 1647 FinalAddrWriter.appendToAddressBuffer(*AddressSectionContents); 1648 } 1649 if (CU->getVersion() != 4) 1650 continue; 1651 std::optional<uint64_t> DWOId = CU->getDWOId(); 1652 if (!DWOId) 1653 continue; 1654 auto RangesWriterIterator = LegacyRangesWritersByCU.find(*DWOId); 1655 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() && 1656 "RangesWriter does not exist for DWOId"); 1657 std::unique_ptr<DebugRangesSectionWriter> &LegacyRangesWriter = 1658 RangesWriterIterator->second; 1659 DIE *Die = LegacyRangesWriter->getDie(); 1660 if (!Die) 1661 continue; 1662 DIEValue DvalGNUBase = Die->findAttribute(dwarf::DW_AT_GNU_ranges_base); 1663 assert(DvalGNUBase && "GNU_ranges_base attribute does not exist for DWOId"); 1664 DIEBlder.replaceValue( 1665 Die, dwarf::DW_AT_GNU_ranges_base, DvalGNUBase.getForm(), 1666 DIEInteger(LegacyRangesSectionWriter->getSectionOffset())); 1667 std::unique_ptr<DebugBufferVector> RangesWritersContents = 1668 LegacyRangesWriter->releaseBuffer(); 1669 LegacyRangesSectionWriter->appendToRangeBuffer(*RangesWritersContents); 1670 } 1671 DIEBlder.generateAbbrevs(); 1672 DIEBlder.finish(); 1673 DIEBlder.updateDebugNamesTable(); 1674 // generate debug_info and CUMap 1675 for (DWARFUnit *CU : CUs) { 1676 emitUnit(DIEBlder, Streamer, *CU); 1677 const uint32_t StartOffset = CUOffset; 1678 DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU); 1679 CUOffset += CU->getHeaderSize(); 1680 CUOffset += UnitDIE->getSize(); 1681 CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4}; 1682 } 1683 } 1684 1685 // Creates all the data structures necessary for creating MCStreamer. 1686 // They are passed by reference because they need to be kept around. 1687 // Also creates known debug sections. These are sections handled by 1688 // handleDebugDataPatching. 1689 namespace { 1690 1691 std::unique_ptr<BinaryContext> 1692 createDwarfOnlyBC(const object::ObjectFile &File) { 1693 return cantFail(BinaryContext::createBinaryContext( 1694 File.makeTriple(), std::make_shared<orc::SymbolStringPool>(), 1695 File.getFileName(), nullptr, false, 1696 DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore, 1697 nullptr, "", WithColor::defaultErrorHandler, 1698 WithColor::defaultWarningHandler), 1699 {llvm::outs(), llvm::errs()})); 1700 } 1701 1702 StringMap<DWARFRewriter::KnownSectionsEntry> 1703 createKnownSectionsMap(const MCObjectFileInfo &MCOFI) { 1704 StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = { 1705 {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}}, 1706 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}}, 1707 {"debug_str_offsets.dwo", 1708 {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}}, 1709 {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}}, 1710 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, 1711 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, 1712 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, 1713 {"debug_loclists.dwo", 1714 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}}, 1715 {"debug_rnglists.dwo", 1716 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}}; 1717 return KnownSectionsTemp; 1718 } 1719 1720 StringRef getSectionName(const SectionRef &Section) { 1721 Expected<StringRef> SectionName = Section.getName(); 1722 assert(SectionName && "Invalid section name."); 1723 StringRef Name = *SectionName; 1724 Name = Name.substr(Name.find_first_not_of("._")); 1725 return Name; 1726 } 1727 1728 // Exctracts an appropriate slice if input is DWP. 1729 // Applies patches or overwrites the section. 1730 std::optional<StringRef> updateDebugData( 1731 DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents, 1732 const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections, 1733 MCStreamer &Streamer, DWARFRewriter &Writer, 1734 const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId, 1735 std::unique_ptr<DebugBufferVector> &OutputBuffer, 1736 DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter, 1737 DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter, 1738 const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) { 1739 1740 using DWOSectionContribution = 1741 const DWARFUnitIndex::Entry::SectionContribution; 1742 auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry, 1743 StringRef OutData, DWARFSectionKind Sec, 1744 uint64_t &DWPOffset) -> StringRef { 1745 if (DWOEntry) { 1746 DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec); 1747 DWPOffset = DWOContrubution->getOffset(); 1748 OutData = OutData.substr(DWPOffset, DWOContrubution->getLength()); 1749 } 1750 return OutData; 1751 }; 1752 1753 auto SectionIter = KnownSections.find(SectionName); 1754 if (SectionIter == KnownSections.end()) 1755 return std::nullopt; 1756 Streamer.switchSection(SectionIter->second.first); 1757 uint64_t DWPOffset = 0; 1758 1759 auto getOverridenSection = 1760 [&](DWARFSectionKind Kind) -> std::optional<StringRef> { 1761 auto Iter = OverridenSections.find(Kind); 1762 if (Iter == OverridenSections.end()) { 1763 errs() 1764 << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden " 1765 "section for: " 1766 << Twine::utohexstr(DWOId) << ".\n"; 1767 return std::nullopt; 1768 } 1769 return Iter->second; 1770 }; 1771 switch (SectionIter->second.second) { 1772 default: { 1773 if (SectionName != "debug_str.dwo") 1774 errs() << "BOLT-WARNING: unsupported debug section: " << SectionName 1775 << "\n"; 1776 if (StrWriter.isInitialized()) { 1777 OutputBuffer = StrWriter.releaseBuffer(); 1778 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()), 1779 OutputBuffer->size()); 1780 } 1781 return SectionContents; 1782 } 1783 case DWARFSectionKind::DW_SECT_INFO: { 1784 return getOverridenSection(DWARFSectionKind::DW_SECT_INFO); 1785 } 1786 case DWARFSectionKind::DW_SECT_EXT_TYPES: { 1787 return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES); 1788 } 1789 case DWARFSectionKind::DW_SECT_STR_OFFSETS: { 1790 if (StrOffstsWriter.isFinalized()) { 1791 OutputBuffer = StrOffstsWriter.releaseBuffer(); 1792 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()), 1793 OutputBuffer->size()); 1794 } 1795 return getSliceData(CUDWOEntry, SectionContents, 1796 DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset); 1797 } 1798 case DWARFSectionKind::DW_SECT_ABBREV: { 1799 return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV); 1800 } 1801 case DWARFSectionKind::DW_SECT_EXT_LOC: 1802 case DWARFSectionKind::DW_SECT_LOCLISTS: { 1803 OutputBuffer = LocWriter.getBuffer(); 1804 // Creating explicit StringRef here, otherwise 1805 // with implicit conversion it will take null byte as end of 1806 // string. 1807 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()), 1808 OutputBuffer->size()); 1809 } 1810 case DWARFSectionKind::DW_SECT_LINE: { 1811 return getSliceData(CUDWOEntry, SectionContents, 1812 DWARFSectionKind::DW_SECT_LINE, DWPOffset); 1813 } 1814 case DWARFSectionKind::DW_SECT_RNGLISTS: { 1815 assert(RangeListsWriter && "RangeListsWriter was not created."); 1816 OutputBuffer = RangeListsWriter->releaseBuffer(); 1817 return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()), 1818 OutputBuffer->size()); 1819 } 1820 } 1821 } 1822 1823 } // namespace 1824 1825 void DWARFRewriter::writeDWOFiles( 1826 DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections, 1827 const std::string &DWOName, DebugLocWriter &LocWriter, 1828 DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter, 1829 DebugRangesSectionWriter &TempRangesSectionWriter) { 1830 // Setup DWP code once. 1831 DWARFContext *DWOCtx = BC.getDWOContext(); 1832 const uint64_t DWOId = *CU.getDWOId(); 1833 const DWARFUnitIndex *CUIndex = nullptr; 1834 bool IsDWP = false; 1835 if (DWOCtx) { 1836 CUIndex = &DWOCtx->getCUIndex(); 1837 IsDWP = !CUIndex->getRows().empty(); 1838 } 1839 1840 // Skipping CUs that we failed to load. 1841 std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId); 1842 if (!DWOCU) { 1843 errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID " 1844 << Twine::utohexstr(DWOId) << " is not found.\n"; 1845 return; 1846 } 1847 1848 std::string CompDir = CU.getCompilationDir(); 1849 1850 if (!opts::DwarfOutputPath.empty()) 1851 CompDir = opts::DwarfOutputPath.c_str(); 1852 else if (!opts::CompDirOverride.empty()) 1853 CompDir = opts::CompDirOverride; 1854 1855 SmallString<16> AbsolutePath; 1856 sys::path::append(AbsolutePath, CompDir); 1857 sys::path::append(AbsolutePath, DWOName); 1858 1859 std::error_code EC; 1860 std::unique_ptr<ToolOutputFile> TempOut = 1861 std::make_unique<ToolOutputFile>(AbsolutePath, EC, sys::fs::OF_None); 1862 1863 const DWARFUnitIndex::Entry *CUDWOEntry = nullptr; 1864 if (IsDWP) 1865 CUDWOEntry = CUIndex->getFromHash(DWOId); 1866 1867 const object::ObjectFile *File = 1868 (*DWOCU)->getContext().getDWARFObj().getFile(); 1869 std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File); 1870 std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os()); 1871 const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo(); 1872 StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI); 1873 1874 DebugRangeListsSectionWriter *RangeListssWriter = nullptr; 1875 if (CU.getVersion() == 5) { 1876 RangeListssWriter = 1877 llvm::dyn_cast<DebugRangeListsSectionWriter>(&TempRangesSectionWriter); 1878 1879 // Handling .debug_rnglists.dwo separately. The original .o/.dwo might not 1880 // have .debug_rnglists so won't be part of the loop below. 1881 if (!RangeListssWriter->empty()) { 1882 std::unique_ptr<DebugBufferVector> OutputData; 1883 if (std::optional<StringRef> OutData = 1884 updateDebugData((*DWOCU)->getContext(), "debug_rnglists.dwo", "", 1885 KnownSections, *Streamer, *this, CUDWOEntry, 1886 DWOId, OutputData, RangeListssWriter, LocWriter, 1887 StrOffstsWriter, StrWriter, OverridenSections)) 1888 Streamer->emitBytes(*OutData); 1889 } 1890 } 1891 1892 for (const SectionRef &Section : File->sections()) { 1893 std::unique_ptr<DebugBufferVector> OutputData; 1894 StringRef SectionName = getSectionName(Section); 1895 if (SectionName == "debug_rnglists.dwo") 1896 continue; 1897 Expected<StringRef> ContentsExp = Section.getContents(); 1898 assert(ContentsExp && "Invalid contents."); 1899 if (std::optional<StringRef> OutData = updateDebugData( 1900 (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections, 1901 *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter, 1902 LocWriter, StrOffstsWriter, StrWriter, OverridenSections)) 1903 Streamer->emitBytes(*OutData); 1904 } 1905 Streamer->finish(); 1906 TempOut->keep(); 1907 } 1908 1909 std::unique_ptr<DebugBufferVector> 1910 DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) { 1911 auto LocBuffer = std::make_unique<DebugBufferVector>(); 1912 auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 1913 auto Writer = 1914 std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream)); 1915 1916 for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc : 1917 LocListWritersByCU) { 1918 DebugLocWriter *LocWriter = Loc.second.get(); 1919 auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter); 1920 1921 // Filter out DWARF4, writing out DWARF5 1922 if (Version == DWARFVersion::DWARF5 && 1923 (!LocListWriter || LocListWriter->getDwarfVersion() <= 4)) 1924 continue; 1925 1926 // Filter out DWARF5, writing out DWARF4 1927 if (Version == DWARFVersion::DWARFLegacy && 1928 (LocListWriter && LocListWriter->getDwarfVersion() >= 5)) 1929 continue; 1930 1931 // Skipping DWARF4/5 split dwarf. 1932 if (LocListWriter && LocListWriter->getDwarfVersion() <= 4) 1933 continue; 1934 std::unique_ptr<DebugBufferVector> CurrCULocationLists = 1935 LocWriter->getBuffer(); 1936 *LocStream << *CurrCULocationLists; 1937 } 1938 1939 return LocBuffer; 1940 } 1941 1942 void DWARFRewriter::convertToRangesPatchDebugInfo( 1943 DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, 1944 uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo, 1945 DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) { 1946 dwarf::Form LowForm = LowPCAttrInfo.getForm(); 1947 dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base; 1948 dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset; 1949 1950 if (Unit.getVersion() >= 5) { 1951 RangeBaseAttribute = dwarf::DW_AT_rnglists_base; 1952 RangesForm = dwarf::DW_FORM_rnglistx; 1953 } else if (Unit.getVersion() < 4) { 1954 RangesForm = dwarf::DW_FORM_data4; 1955 } 1956 bool IsUnitDie = Die.getTag() == dwarf::DW_TAG_compile_unit || 1957 Die.getTag() == dwarf::DW_TAG_skeleton_unit; 1958 if (!IsUnitDie) 1959 DIEBldr.deleteValue(&Die, LowPCAttrInfo.getAttribute()); 1960 1961 // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or 1962 // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is 1963 // when it's absent. 1964 if (IsUnitDie) { 1965 if (LowForm == dwarf::DW_FORM_addrx) { 1966 auto AddrWriterIterator = AddressWritersByCU.find(Unit.getOffset()); 1967 assert(AddrWriterIterator != AddressWritersByCU.end() && 1968 "AddressWriter does not exist for CU"); 1969 DebugAddrWriter *AddrWriter = AddrWriterIterator->second.get(); 1970 const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit); 1971 DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(), 1972 LowPCAttrInfo.getForm(), DIEInteger(Index)); 1973 } else { 1974 DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(), 1975 LowPCAttrInfo.getForm(), DIEInteger(0)); 1976 } 1977 // Original CU didn't have DW_AT_*_base. We converted it's children (or 1978 // dwo), so need to insert it into CU. 1979 if (RangesBase) { 1980 if (Unit.getVersion() >= 5) { 1981 DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset, 1982 DIEInteger(*RangesBase)); 1983 } else { 1984 DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset, 1985 DIEInteger(INT_MAX)); 1986 auto RangesWriterIterator = 1987 LegacyRangesWritersByCU.find(*Unit.getDWOId()); 1988 assert(RangesWriterIterator != LegacyRangesWritersByCU.end() && 1989 "RangesWriter does not exist for DWOId"); 1990 RangesWriterIterator->second->setDie(&Die); 1991 } 1992 } 1993 } 1994 1995 // HighPC was conveted into DW_AT_ranges. 1996 // For DWARF5 we only access ranges through index. 1997 1998 DIEBldr.replaceValue(&Die, HighPCAttrInfo.getAttribute(), dwarf::DW_AT_ranges, 1999 RangesForm, DIEInteger(RangesSectionOffset)); 2000 } 2001