1 //===- bolt/Core/DebugData.cpp - Debugging information handling -----------===// 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 // This file implements functions and classes for handling debug info. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "bolt/Core/DebugData.h" 14 #include "bolt/Core/BinaryContext.h" 15 #include "bolt/Rewrite/RewriteInstance.h" 16 #include "bolt/Utils/Utils.h" 17 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 18 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 19 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" 20 #include "llvm/MC/MCAssembler.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCObjectStreamer.h" 23 #include "llvm/Support/CommandLine.h" 24 #include "llvm/Support/EndianStream.h" 25 #include "llvm/Support/LEB128.h" 26 #include "llvm/Support/SHA1.h" 27 #include <algorithm> 28 #include <cassert> 29 #include <cstdint> 30 #include <functional> 31 #include <limits> 32 #include <unordered_map> 33 #include <vector> 34 35 #define DEBUG_TYPE "bolt-debug-info" 36 37 namespace opts { 38 extern llvm::cl::opt<unsigned> Verbosity; 39 } // namespace opts 40 41 namespace llvm { 42 class MCSymbol; 43 44 namespace bolt { 45 46 std::optional<AttrInfo> 47 findAttributeInfo(const DWARFDie DIE, 48 const DWARFAbbreviationDeclaration *AbbrevDecl, 49 uint32_t Index) { 50 const DWARFUnit &U = *DIE.getDwarfUnit(); 51 uint64_t Offset = 52 AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U); 53 std::optional<DWARFFormValue> Value = 54 AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U); 55 if (!Value) 56 return std::nullopt; 57 // AttributeSpec 58 const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal = 59 AbbrevDecl->attributes().begin() + Index; 60 uint32_t ValSize = 0; 61 std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U); 62 if (ValSizeOpt) { 63 ValSize = static_cast<uint32_t>(*ValSizeOpt); 64 } else { 65 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 66 uint64_t NewOffset = Offset; 67 DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset, 68 U.getFormParams()); 69 // This includes entire size of the entry, which might not be just the 70 // encoding part. For example for DW_AT_loc it will include expression 71 // location. 72 ValSize = NewOffset - Offset; 73 } 74 return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize}; 75 } 76 77 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE, 78 dwarf::Attribute Attr) { 79 if (!DIE.isValid()) 80 return std::nullopt; 81 const DWARFAbbreviationDeclaration *AbbrevDecl = 82 DIE.getAbbreviationDeclarationPtr(); 83 if (!AbbrevDecl) 84 return std::nullopt; 85 std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr); 86 if (!Index) 87 return std::nullopt; 88 return findAttributeInfo(DIE, AbbrevDecl, *Index); 89 } 90 91 const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 92 93 LLVM_ATTRIBUTE_UNUSED 94 static void printLE64(const std::string &S) { 95 for (uint32_t I = 0, Size = S.size(); I < Size; ++I) { 96 errs() << Twine::utohexstr(S[I]); 97 errs() << Twine::utohexstr((int8_t)S[I]); 98 } 99 errs() << "\n"; 100 } 101 102 // Writes address ranges to Writer as pairs of 64-bit (address, size). 103 // If RelativeRange is true, assumes the address range to be written must be of 104 // the form (begin address, range size), otherwise (begin address, end address). 105 // Terminates the list by writing a pair of two zeroes. 106 // Returns the number of written bytes. 107 static uint64_t 108 writeAddressRanges(raw_svector_ostream &Stream, 109 const DebugAddressRangesVector &AddressRanges, 110 const bool WriteRelativeRanges = false) { 111 for (const DebugAddressRange &Range : AddressRanges) { 112 support::endian::write(Stream, Range.LowPC, support::little); 113 support::endian::write( 114 Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 115 support::little); 116 } 117 // Finish with 0 entries. 118 support::endian::write(Stream, 0ULL, support::little); 119 support::endian::write(Stream, 0ULL, support::little); 120 return AddressRanges.size() * 16 + 16; 121 } 122 123 DebugRangesSectionWriter::DebugRangesSectionWriter() { 124 RangesBuffer = std::make_unique<DebugBufferVector>(); 125 RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 126 127 // Add an empty range as the first entry; 128 SectionOffset += 129 writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 130 Kind = RangesWriterKind::DebugRangesWriter; 131 } 132 133 uint64_t DebugRangesSectionWriter::addRanges( 134 DebugAddressRangesVector &&Ranges, 135 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 136 if (Ranges.empty()) 137 return getEmptyRangesOffset(); 138 139 const auto RI = CachedRanges.find(Ranges); 140 if (RI != CachedRanges.end()) 141 return RI->second; 142 143 const uint64_t EntryOffset = addRanges(Ranges); 144 CachedRanges.emplace(std::move(Ranges), EntryOffset); 145 146 return EntryOffset; 147 } 148 149 uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) { 150 if (Ranges.empty()) 151 return getEmptyRangesOffset(); 152 153 // Reading the SectionOffset and updating it should be atomic to guarantee 154 // unique and correct offsets in patches. 155 std::lock_guard<std::mutex> Lock(WriterMutex); 156 const uint32_t EntryOffset = SectionOffset; 157 SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges); 158 159 return EntryOffset; 160 } 161 162 uint64_t DebugRangesSectionWriter::getSectionOffset() { 163 std::lock_guard<std::mutex> Lock(WriterMutex); 164 return SectionOffset; 165 } 166 167 DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr; 168 169 uint64_t DebugRangeListsSectionWriter::addRanges( 170 DebugAddressRangesVector &&Ranges, 171 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 172 return addRanges(Ranges); 173 } 174 175 struct LocListsRangelistsHeader { 176 UnitLengthType UnitLength; // Size of loclist entris section, not including 177 // size of header. 178 VersionType Version; 179 AddressSizeType AddressSize; 180 SegmentSelectorType SegmentSelector; 181 OffsetEntryCountType OffsetEntryCount; 182 }; 183 184 static std::unique_ptr<DebugBufferVector> 185 getDWARF5Header(const LocListsRangelistsHeader &Header) { 186 std::unique_ptr<DebugBufferVector> HeaderBuffer = 187 std::make_unique<DebugBufferVector>(); 188 std::unique_ptr<raw_svector_ostream> HeaderStream = 189 std::make_unique<raw_svector_ostream>(*HeaderBuffer); 190 191 // 7.29 length of the set of entries for this compilation unit, not including 192 // the length field itself 193 const uint32_t HeaderSize = 194 getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType); 195 196 support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize, 197 support::little); 198 support::endian::write(*HeaderStream, Header.Version, support::little); 199 support::endian::write(*HeaderStream, Header.AddressSize, support::little); 200 support::endian::write(*HeaderStream, Header.SegmentSelector, 201 support::little); 202 support::endian::write(*HeaderStream, Header.OffsetEntryCount, 203 support::little); 204 return HeaderBuffer; 205 } 206 207 struct OffsetEntry { 208 uint32_t Index; 209 uint32_t StartOffset; 210 uint32_t EndOffset; 211 }; 212 template <typename DebugVector, typename ListEntry, typename DebugAddressEntry> 213 static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries, 214 DebugAddrWriter &AddrWriter, DWARFUnit &CU, 215 uint32_t &Index, const ListEntry BaseAddressx, 216 const ListEntry OffsetPair, const ListEntry EndOfList, 217 const std::function<void(uint32_t)> &Func) { 218 if (Entries.size() < 2) 219 return false; 220 uint64_t Base = Entries[Index].LowPC; 221 std::vector<OffsetEntry> Offsets; 222 uint8_t TempBuffer[64]; 223 while (Index < Entries.size()) { 224 const DebugAddressEntry &Entry = Entries[Index]; 225 if (Entry.LowPC == 0) 226 break; 227 assert(Base <= Entry.LowPC && "Entry base is higher than low PC"); 228 uint32_t StartOffset = Entry.LowPC - Base; 229 uint32_t EndOffset = Entry.HighPC - Base; 230 if (encodeULEB128(EndOffset, TempBuffer) > 2) 231 break; 232 Offsets.push_back({Index, StartOffset, EndOffset}); 233 ++Index; 234 } 235 236 if (Offsets.size() < 2) { 237 Index -= Offsets.size(); 238 return false; 239 } 240 241 support::endian::write(OS, static_cast<uint8_t>(BaseAddressx), 242 support::little); 243 uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU); 244 encodeULEB128(BaseIndex, OS); 245 for (auto &OffsetEntry : Offsets) { 246 support::endian::write(OS, static_cast<uint8_t>(OffsetPair), 247 support::little); 248 encodeULEB128(OffsetEntry.StartOffset, OS); 249 encodeULEB128(OffsetEntry.EndOffset, OS); 250 Func(OffsetEntry.Index); 251 } 252 support::endian::write(OS, static_cast<uint8_t>(EndOfList), support::little); 253 return true; 254 } 255 256 uint64_t 257 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) { 258 std::lock_guard<std::mutex> Lock(WriterMutex); 259 260 RangeEntries.push_back(CurrentOffset); 261 bool WrittenStartxLength = false; 262 std::sort( 263 Ranges.begin(), Ranges.end(), 264 [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool { 265 return R1.LowPC < R2.LowPC; 266 }); 267 for (unsigned I = 0; I < Ranges.size();) { 268 WrittenStartxLength = false; 269 if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries, 270 DebugAddressRange>( 271 *CUBodyStream, Ranges, *AddrWriter, *CU, I, 272 dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair, 273 dwarf::DW_RLE_end_of_list, [](uint32_t Index) -> void {})) 274 continue; 275 276 const DebugAddressRange &Range = Ranges[I]; 277 support::endian::write(*CUBodyStream, 278 static_cast<uint8_t>(dwarf::DW_RLE_startx_length), 279 support::little); 280 uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU); 281 encodeULEB128(Index, *CUBodyStream); 282 encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream); 283 ++I; 284 WrittenStartxLength = true; 285 } 286 if (WrittenStartxLength) 287 support::endian::write(*CUBodyStream, 288 static_cast<uint8_t>(dwarf::DW_RLE_end_of_list), 289 support::little); 290 CurrentOffset = CUBodyBuffer->size(); 291 return RangeEntries.size() - 1; 292 } 293 294 void DebugRangeListsSectionWriter::finalizeSection() { 295 std::unique_ptr<DebugBufferVector> CUArrayBuffer = 296 std::make_unique<DebugBufferVector>(); 297 std::unique_ptr<raw_svector_ostream> CUArrayStream = 298 std::make_unique<raw_svector_ostream>(*CUArrayBuffer); 299 constexpr uint32_t SizeOfArrayEntry = 4; 300 const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry; 301 for (uint32_t Offset : RangeEntries) 302 support::endian::write(*CUArrayStream, Offset + SizeOfArraySection, 303 support::little); 304 305 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 306 {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()), 307 5, 8, 0, static_cast<uint32_t>(RangeEntries.size())}); 308 *RangesStream << *Header; 309 *RangesStream << *CUArrayBuffer; 310 *RangesStream << *CUBodyBuffer; 311 SectionOffset = RangesBuffer->size(); 312 } 313 314 void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) { 315 CUBodyBuffer = std::make_unique<DebugBufferVector>(); 316 CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer); 317 RangeEntries.clear(); 318 CurrentOffset = 0; 319 CU = &Unit; 320 } 321 322 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 323 DebugAddressRangesVector &&Ranges) { 324 std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 325 CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 326 } 327 328 void DebugARangesSectionWriter::writeARangesSection( 329 raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const { 330 // For reference on the format of the .debug_aranges section, see the DWARF4 331 // specification, section 6.1.4 Lookup by Address 332 // http://www.dwarfstd.org/doc/DWARF4.pdf 333 for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 334 const uint64_t Offset = CUOffsetAddressRangesPair.first; 335 const DebugAddressRangesVector &AddressRanges = 336 CUOffsetAddressRangesPair.second; 337 338 // Emit header. 339 340 // Size of this set: 8 (size of the header) + 4 (padding after header) 341 // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 342 // pair of uint64_t's for the terminating, zero-length range. 343 // Does not include size field itself. 344 uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 345 346 // Header field #1: set size. 347 support::endian::write(RangesStream, Size, support::little); 348 349 // Header field #2: version number, 2 as per the specification. 350 support::endian::write(RangesStream, static_cast<uint16_t>(2), 351 support::little); 352 353 assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map"); 354 // Header field #3: debug info offset of the correspondent compile unit. 355 support::endian::write( 356 RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset), 357 support::little); 358 359 // Header field #4: address size. 360 // 8 since we only write ELF64 binaries for now. 361 RangesStream << char(8); 362 363 // Header field #5: segment size of target architecture. 364 RangesStream << char(0); 365 366 // Padding before address table - 4 bytes in the 64-bit-pointer case. 367 support::endian::write(RangesStream, static_cast<uint32_t>(0), 368 support::little); 369 370 writeAddressRanges(RangesStream, AddressRanges, true); 371 } 372 } 373 374 DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; } 375 376 void DebugAddrWriter::AddressForDWOCU::dump() { 377 std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 378 indexToAdddessEnd()); 379 // Sorting address in increasing order of indices. 380 llvm::sort(SortedMap, llvm::less_first()); 381 for (auto &Pair : SortedMap) 382 dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 383 } 384 uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { 385 std::lock_guard<std::mutex> Lock(WriterMutex); 386 const uint64_t CUID = getCUID(CU); 387 if (!AddressMaps.count(CUID)) 388 AddressMaps[CUID] = AddressForDWOCU(); 389 390 AddressForDWOCU &Map = AddressMaps[CUID]; 391 auto Entry = Map.find(Address); 392 if (Entry == Map.end()) { 393 auto Index = Map.getNextIndex(); 394 Entry = Map.insert(Address, Index).first; 395 } 396 return Entry->second; 397 } 398 399 // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 400 // Case2) Address is in the map but Index is higher or equal. Need to update 401 // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 402 // update AddressToIndex and IndexToAddress 403 void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 404 DWARFUnit &CU) { 405 std::lock_guard<std::mutex> Lock(WriterMutex); 406 const uint64_t CUID = getCUID(CU); 407 AddressForDWOCU &Map = AddressMaps[CUID]; 408 auto Entry = Map.find(Address); 409 if (Entry != Map.end()) { 410 if (Entry->second > Index) 411 Map.updateAddressToIndex(Address, Index); 412 Map.updateIndexToAddrss(Address, Index); 413 } else { 414 Map.insert(Address, Index); 415 } 416 } 417 418 AddressSectionBuffer DebugAddrWriter::finalize() { 419 // Need to layout all sections within .debug_addr 420 // Within each section sort Address by index. 421 AddressSectionBuffer Buffer; 422 raw_svector_ostream AddressStream(Buffer); 423 for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 424 // Handling the case wehre debug information is a mix of Debug fission and 425 // monolitic. 426 if (!CU->getDWOId()) 427 continue; 428 const uint64_t CUID = getCUID(*CU.get()); 429 auto AM = AddressMaps.find(CUID); 430 // Adding to map even if it did not contribute to .debug_addr. 431 // The Skeleton CU might still have DW_AT_GNU_addr_base. 432 DWOIdToOffsetMap[CUID] = Buffer.size(); 433 // If does not exist this CUs DWO section didn't contribute to .debug_addr. 434 if (AM == AddressMaps.end()) 435 continue; 436 std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 437 AM->second.indexToAdddessEnd()); 438 // Sorting address in increasing order of indices. 439 llvm::sort(SortedMap, llvm::less_first()); 440 441 uint8_t AddrSize = CU->getAddressByteSize(); 442 uint32_t Counter = 0; 443 auto WriteAddress = [&](uint64_t Address) -> void { 444 ++Counter; 445 switch (AddrSize) { 446 default: 447 assert(false && "Address Size is invalid."); 448 break; 449 case 4: 450 support::endian::write(AddressStream, static_cast<uint32_t>(Address), 451 support::little); 452 break; 453 case 8: 454 support::endian::write(AddressStream, Address, support::little); 455 break; 456 } 457 }; 458 459 for (const IndexAddressPair &Val : SortedMap) { 460 while (Val.first > Counter) 461 WriteAddress(0); 462 WriteAddress(Val.second); 463 } 464 } 465 466 return Buffer; 467 } 468 AddressSectionBuffer DebugAddrWriterDwarf5::finalize() { 469 // Need to layout all sections within .debug_addr 470 // Within each section sort Address by index. 471 AddressSectionBuffer Buffer; 472 raw_svector_ostream AddressStream(Buffer); 473 const endianness Endian = 474 BC->DwCtx->isLittleEndian() ? support::little : support::big; 475 const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection(); 476 DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0); 477 DWARFDebugAddrTable AddrTable; 478 DIDumpOptions DumpOpts; 479 constexpr uint32_t HeaderSize = 8; 480 DenseMap<uint64_t, uint64_t> UnmodifiedAddressOffsets; 481 for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 482 const uint64_t CUID = getCUID(*CU.get()); 483 const uint8_t AddrSize = CU->getAddressByteSize(); 484 auto AMIter = AddressMaps.find(CUID); 485 // A case where CU has entry in .debug_addr, but we don't modify addresses 486 // for it. 487 if (AMIter == AddressMaps.end()) { 488 AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; 489 std::optional<uint64_t> BaseOffset = CU->getAddrOffsetSectionBase(); 490 if (!BaseOffset) 491 continue; 492 // Address base offset is to the first entry. 493 // The size of header is 8 bytes. 494 uint64_t Offset = *BaseOffset - HeaderSize; 495 auto Iter = UnmodifiedAddressOffsets.find(Offset); 496 if (Iter != UnmodifiedAddressOffsets.end()) { 497 DWOIdToOffsetMap[CUID] = Iter->getSecond(); 498 continue; 499 } 500 UnmodifiedAddressOffsets[Offset] = Buffer.size() + HeaderSize; 501 if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize, 502 DumpOpts.WarningHandler)) { 503 DumpOpts.RecoverableErrorHandler(std::move(Err)); 504 continue; 505 } 506 507 uint32_t Index = 0; 508 for (uint64_t Addr : AddrTable.getAddressEntries()) 509 AMIter->second.insert(Addr, Index++); 510 } 511 512 DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize; 513 514 std::vector<IndexAddressPair> SortedMap( 515 AMIter->second.indexToAddressBegin(), 516 AMIter->second.indexToAdddessEnd()); 517 // Sorting address in increasing order of indices. 518 llvm::sort(SortedMap, llvm::less_first()); 519 // Writing out Header 520 const uint32_t Length = SortedMap.size() * AddrSize + 4; 521 support::endian::write(AddressStream, Length, Endian); 522 support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian); 523 support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize), 524 Endian); 525 support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian); 526 527 uint32_t Counter = 0; 528 auto writeAddress = [&](uint64_t Address) -> void { 529 ++Counter; 530 switch (AddrSize) { 531 default: 532 llvm_unreachable("Address Size is invalid."); 533 break; 534 case 4: 535 support::endian::write(AddressStream, static_cast<uint32_t>(Address), 536 Endian); 537 break; 538 case 8: 539 support::endian::write(AddressStream, Address, Endian); 540 break; 541 } 542 }; 543 544 for (const IndexAddressPair &Val : SortedMap) { 545 while (Val.first > Counter) 546 writeAddress(0); 547 writeAddress(Val.second); 548 } 549 } 550 551 return Buffer; 552 } 553 554 uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) { 555 const uint64_t CUID = getCUID(Unit); 556 assert(CUID && "Can't get offset, not a skeleton CU."); 557 auto Iter = DWOIdToOffsetMap.find(CUID); 558 assert(Iter != DWOIdToOffsetMap.end() && 559 "Offset in to.debug_addr was not found for DWO ID."); 560 return Iter->second; 561 } 562 563 uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) { 564 auto Iter = DWOIdToOffsetMap.find(getCUID(Unit)); 565 assert(Iter != DWOIdToOffsetMap.end() && 566 "Offset in to.debug_addr was not found for CU ID."); 567 return Iter->second; 568 } 569 570 void DebugLocWriter::init() { 571 LocBuffer = std::make_unique<DebugBufferVector>(); 572 LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 573 // Writing out empty location list to which all references to empty location 574 // lists will point. 575 if (!LocSectionOffset && DwarfVersion < 5) { 576 const char Zeroes[16] = {0}; 577 *LocStream << StringRef(Zeroes, 16); 578 LocSectionOffset += 16; 579 } 580 } 581 582 uint32_t DebugLocWriter::LocSectionOffset = 0; 583 void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList, 584 DebugInfoBinaryPatcher &DebugInfoPatcher, 585 DebugAbbrevWriter &AbbrevWriter) { 586 const uint64_t AttrOffset = AttrVal.Offset; 587 if (LocList.empty()) { 588 DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); 589 return; 590 } 591 // Since there is a separate DebugLocWriter for each thread, 592 // we don't need a lock to read the SectionOffset and update it. 593 const uint32_t EntryOffset = LocSectionOffset; 594 595 for (const DebugLocationEntry &Entry : LocList) { 596 support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 597 support::little); 598 support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 599 support::little); 600 support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 601 support::little); 602 *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 603 Entry.Expr.size()); 604 LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 605 } 606 LocStream->write_zeros(16); 607 LocSectionOffset += 16; 608 LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 609 DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); 610 } 611 612 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 613 return std::move(LocBuffer); 614 } 615 616 // DWARF 4: 2.6.2 617 void DebugLocWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 618 DebugAbbrevWriter &AbbrevWriter) {} 619 620 static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { 621 support::endian::write(Stream, static_cast<uint32_t>(4), support::little); 622 support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end), 623 support::little); 624 625 const char Zeroes[16] = {0}; 626 Stream << StringRef(Zeroes, 16); 627 encodeULEB128(0, Stream); 628 support::endian::write( 629 Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little); 630 } 631 632 static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList, 633 DebugInfoBinaryPatcher &DebugInfoPatcher, 634 DebugAddrWriter &AddrWriter, 635 DebugBufferVector &LocBuffer, DWARFUnit &CU, 636 raw_svector_ostream &LocStream) { 637 const uint64_t AttrOffset = AttrVal.Offset; 638 if (LocList.empty()) { 639 DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); 640 return; 641 } 642 643 const uint32_t EntryOffset = LocBuffer.size(); 644 for (const DebugLocationEntry &Entry : LocList) { 645 support::endian::write(LocStream, 646 static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 647 support::little); 648 const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 649 encodeULEB128(Index, LocStream); 650 651 support::endian::write(LocStream, 652 static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 653 support::little); 654 support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()), 655 support::little); 656 LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 657 Entry.Expr.size()); 658 } 659 support::endian::write(LocStream, 660 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 661 support::little); 662 DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); 663 } 664 665 static void writeDWARF5LocList( 666 uint32_t &NumberOfEntries, AttrInfo &AttrVal, DebugLocationsVector &LocList, 667 DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter, 668 DebugAddrWriter &AddrWriter, DebugBufferVector &LocBodyBuffer, 669 std::vector<uint32_t> &RelativeLocListOffsets, DWARFUnit &CU, 670 raw_svector_ostream &LocBodyStream) { 671 if (AttrVal.V.getForm() != dwarf::DW_FORM_loclistx) { 672 AbbrevWriter.addAttributePatch(CU, AttrVal.AbbrevDecl, 673 dwarf::DW_AT_location, dwarf::DW_AT_location, 674 dwarf::DW_FORM_loclistx); 675 } 676 DebugInfoPatcher.addUDataPatch(AttrVal.Offset, NumberOfEntries, AttrVal.Size); 677 RelativeLocListOffsets.push_back(LocBodyBuffer.size()); 678 ++NumberOfEntries; 679 if (LocList.empty()) { 680 writeEmptyListDwarf5(LocBodyStream); 681 return; 682 } 683 684 std::vector<uint64_t> OffsetsArray; 685 bool WrittenStartxLength = false; 686 auto writeExpression = [&](uint32_t Index) -> void { 687 const DebugLocationEntry &Entry = LocList[Index]; 688 encodeULEB128(Entry.Expr.size(), LocBodyStream); 689 LocBodyStream << StringRef( 690 reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size()); 691 }; 692 for (unsigned I = 0; I < LocList.size();) { 693 WrittenStartxLength = false; 694 if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries, 695 DebugLocationEntry>( 696 LocBodyStream, LocList, AddrWriter, CU, I, 697 dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair, 698 dwarf::DW_LLE_end_of_list, writeExpression)) 699 continue; 700 701 const DebugLocationEntry &Entry = LocList[I]; 702 support::endian::write(LocBodyStream, 703 static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 704 support::little); 705 const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 706 encodeULEB128(Index, LocBodyStream); 707 encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream); 708 writeExpression(I); 709 ++I; 710 WrittenStartxLength = true; 711 } 712 713 if (WrittenStartxLength) 714 support::endian::write(LocBodyStream, 715 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 716 support::little); 717 } 718 719 void DebugLoclistWriter::addList(AttrInfo &AttrVal, 720 DebugLocationsVector &LocList, 721 DebugInfoBinaryPatcher &DebugInfoPatcher, 722 DebugAbbrevWriter &AbbrevWriter) { 723 if (DwarfVersion < 5) 724 writeLegacyLocList(AttrVal, LocList, DebugInfoPatcher, *AddrWriter, 725 *LocBuffer, CU, *LocStream); 726 else 727 writeDWARF5LocList(NumberOfEntries, AttrVal, LocList, DebugInfoPatcher, 728 AbbrevWriter, *AddrWriter, *LocBodyBuffer, 729 RelativeLocListOffsets, CU, *LocBodyStream); 730 } 731 732 uint32_t DebugLoclistWriter::LoclistBaseOffset = 0; 733 void DebugLoclistWriter::finalizeDWARF5( 734 DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) { 735 if (LocBodyBuffer->empty()) 736 return; 737 738 std::unique_ptr<DebugBufferVector> LocArrayBuffer = 739 std::make_unique<DebugBufferVector>(); 740 std::unique_ptr<raw_svector_ostream> LocArrayStream = 741 std::make_unique<raw_svector_ostream>(*LocArrayBuffer); 742 743 const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t); 744 // Write out IndexArray 745 for (uint32_t RelativeOffset : RelativeLocListOffsets) 746 support::endian::write( 747 *LocArrayStream, 748 static_cast<uint32_t>(SizeOfArraySection + RelativeOffset), 749 support::little); 750 751 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 752 {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()), 753 5, 8, 0, NumberOfEntries}); 754 *LocStream << *Header; 755 *LocStream << *LocArrayBuffer; 756 *LocStream << *LocBodyBuffer; 757 758 if (!isSplitDwarf()) { 759 if (std::optional<AttrInfo> AttrInfoVal = 760 findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base)) 761 DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset, 762 LoclistBaseOffset + 763 getDWARF5RngListLocListHeaderSize()); 764 else { 765 AbbrevWriter.addAttribute( 766 CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(), 767 dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset); 768 DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(), 769 LoclistBaseOffset + Header->size()); 770 } 771 LoclistBaseOffset += LocBuffer->size(); 772 } 773 clearList(RelativeLocListOffsets); 774 clearList(*LocArrayBuffer); 775 clearList(*LocBodyBuffer); 776 } 777 778 void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 779 DebugAbbrevWriter &AbbrevWriter) { 780 if (DwarfVersion >= 5) 781 finalizeDWARF5(DebugInfoPatcher, AbbrevWriter); 782 } 783 784 DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 785 786 void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 787 Offset -= DWPUnitOffset; 788 std::lock_guard<std::mutex> Lock(WriterMutex); 789 DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 790 } 791 792 void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 793 Offset -= DWPUnitOffset; 794 std::lock_guard<std::mutex> Lock(WriterMutex); 795 auto RetVal = DestinationLabels.insert(Offset); 796 if (!RetVal.second) 797 return; 798 799 DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 800 } 801 802 static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 803 std::string LE64(ByteSize, 0); 804 for (size_t I = 0; I < ByteSize; ++I) { 805 LE64[I] = NewValue & 0xff; 806 NewValue >>= 8; 807 } 808 return LE64; 809 } 810 811 void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 812 uint32_t Value) { 813 std::string StrValue = encodeLE(4, Value); 814 insertNewEntry(DIE, std::move(StrValue)); 815 } 816 817 void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 818 std::string &&Value) { 819 const DWARFAbbreviationDeclaration *AbbrevDecl = 820 DIE.getAbbreviationDeclarationPtr(); 821 822 // In case this DIE has no attributes. 823 uint32_t Offset = DIE.getOffset() + 1; 824 size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 825 if (NumOfAttributes) { 826 std::optional<AttrInfo> Val = 827 findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 828 assert(Val && "Invalid Value."); 829 830 Offset = Val->Offset + Val->Size - DWPUnitOffset; 831 } 832 std::lock_guard<std::mutex> Lock(WriterMutex); 833 DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 834 } 835 836 void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 837 uint32_t DestinationOffset, 838 uint32_t OldValueSize, 839 dwarf::Form Form) { 840 Offset -= DWPUnitOffset; 841 DestinationOffset -= DWPUnitOffset; 842 std::lock_guard<std::mutex> Lock(WriterMutex); 843 DebugPatches.emplace_back( 844 new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 845 } 846 847 void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 848 uint32_t OldValueSize) { 849 Offset -= DWPUnitOffset; 850 std::lock_guard<std::mutex> Lock(WriterMutex); 851 DebugPatches.emplace_back( 852 new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 853 } 854 855 void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 856 Offset -= DWPUnitOffset; 857 std::lock_guard<std::mutex> Lock(WriterMutex); 858 DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 859 } 860 861 void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 862 uint32_t OldValueSize) { 863 Offset -= DWPUnitOffset; 864 std::lock_guard<std::mutex> Lock(WriterMutex); 865 if (OldValueSize == 4) 866 DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 867 else if (OldValueSize == 8) 868 DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 869 else 870 DebugPatches.emplace_back( 871 new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); 872 } 873 874 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 875 std::string &&NewValue, 876 uint32_t OldValueSize) { 877 Patches.emplace_back(Offset, std::move(NewValue)); 878 } 879 880 void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 881 auto Str = std::string(1, Value); 882 Patches.emplace_back(Offset, std::move(Str)); 883 } 884 885 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 886 size_t ByteSize) { 887 Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 888 } 889 890 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 891 uint32_t OldValueSize) { 892 std::string Buff; 893 raw_string_ostream OS(Buff); 894 encodeULEB128(Value, OS, OldValueSize); 895 896 Patches.emplace_back(Offset, std::move(Buff)); 897 } 898 899 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 900 addLEPatch(Offset, NewValue, 8); 901 } 902 903 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 904 uint32_t OldValueSize) { 905 addLEPatch(Offset, NewValue, 4); 906 } 907 908 std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 909 std::string BinaryContentsStr = std::string(BinaryContents); 910 for (const auto &Patch : Patches) { 911 uint32_t Offset = Patch.first; 912 const std::string &ByteSequence = Patch.second; 913 assert(Offset + ByteSequence.size() <= BinaryContents.size() && 914 "Applied patch runs over binary size."); 915 for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 916 BinaryContentsStr[Offset + I] = ByteSequence[I]; 917 } 918 } 919 return BinaryContentsStr; 920 } 921 922 CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 923 bool IsDWOContext) { 924 CUOffsetMap CUMap; 925 llvm::sort(DebugPatches, [](const UniquePatchPtrType &V1, 926 const UniquePatchPtrType &V2) { 927 if (V1.get()->Offset == V2.get()->Offset) { 928 if (V1->Kind == DebugPatchKind::NewDebugEntry && 929 V2->Kind == DebugPatchKind::NewDebugEntry) 930 return reinterpret_cast<const NewDebugEntry *>(V1.get())->CurrentOrder < 931 reinterpret_cast<const NewDebugEntry *>(V2.get())->CurrentOrder; 932 933 // This is a case where we are modifying first entry of next 934 // DIE, and adding a new one. 935 return V1->Kind == DebugPatchKind::NewDebugEntry; 936 } 937 return V1.get()->Offset < V2.get()->Offset; 938 }); 939 940 DWARFUnitVector::compile_unit_range CompileUnits = 941 IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 942 943 for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 944 CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 945 static_cast<uint32_t>(CU->getLength())}; 946 947 // Calculating changes in .debug_info size from Patches to build a map of old 948 // to updated reference destination offsets. 949 uint32_t PreviousOffset = 0; 950 int32_t PreviousChangeInSize = 0; 951 for (UniquePatchPtrType &PatchBase : DebugPatches) { 952 Patch *P = PatchBase.get(); 953 switch (P->Kind) { 954 default: 955 continue; 956 case DebugPatchKind::PatchValue64to32: { 957 PreviousChangeInSize -= 4; 958 break; 959 } 960 case DebugPatchKind::PatchValue32GenericSize: { 961 DebugPatch32GenericSize *DPVS = 962 reinterpret_cast<DebugPatch32GenericSize *>(P); 963 PreviousChangeInSize += 4 - DPVS->OldValueSize; 964 break; 965 } 966 case DebugPatchKind::PatchValueVariable: { 967 DebugPatchVariableSize *DPV = 968 reinterpret_cast<DebugPatchVariableSize *>(P); 969 std::string Temp; 970 raw_string_ostream OS(Temp); 971 encodeULEB128(DPV->Value, OS); 972 PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 973 break; 974 } 975 case DebugPatchKind::DestinationReferenceLabel: { 976 DestinationReferenceLabel *DRL = 977 reinterpret_cast<DestinationReferenceLabel *>(P); 978 OldToNewOffset[DRL->Offset] = 979 DRL->Offset + ChangeInSize + PreviousChangeInSize; 980 break; 981 } 982 case DebugPatchKind::ReferencePatchValue: { 983 // This doesn't look to be a common case, so will always encode as 4 bytes 984 // to reduce algorithmic complexity. 985 DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 986 if (RDP->PatchInfo.IndirectRelative) { 987 PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 988 assert(RDP->PatchInfo.OldValueSize <= 4 && 989 "Variable encoding reference greater than 4 bytes."); 990 } 991 break; 992 } 993 case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 994 DWARFUnitOffsetBaseLabel *BaseLabel = 995 reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 996 uint32_t CUOffset = BaseLabel->Offset; 997 ChangeInSize += PreviousChangeInSize; 998 uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 999 CUMap[CUOffset].Offset = CUOffsetUpdate; 1000 CUMap[PreviousOffset].Length += PreviousChangeInSize; 1001 PreviousChangeInSize = 0; 1002 PreviousOffset = CUOffset; 1003 break; 1004 } 1005 case DebugPatchKind::NewDebugEntry: { 1006 NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1007 PreviousChangeInSize += NDE->Value.size(); 1008 break; 1009 } 1010 } 1011 } 1012 CUMap[PreviousOffset].Length += PreviousChangeInSize; 1013 return CUMap; 1014 } 1015 uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 1016 1017 std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 1018 std::string NewBinaryContents; 1019 NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 1020 uint32_t StartOffset = 0; 1021 uint32_t DwarfUnitBaseOffset = 0; 1022 uint32_t OldValueSize = 0; 1023 uint32_t Offset = 0; 1024 std::string ByteSequence; 1025 std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 1026 // Wasting one entry to avoid checks for first. 1027 LengthPatches.push_back({0, 0}); 1028 1029 // Applying all the patches replacing current entry. 1030 // This might change the size of .debug_info section. 1031 for (const UniquePatchPtrType &PatchBase : DebugPatches) { 1032 Patch *P = PatchBase.get(); 1033 switch (P->Kind) { 1034 default: 1035 continue; 1036 case DebugPatchKind::ReferencePatchValue: { 1037 DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 1038 uint32_t DestinationOffset = RDP->DestinationOffset; 1039 assert(OldToNewOffset.count(DestinationOffset) && 1040 "Destination Offset for reference not updated."); 1041 uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 1042 Offset = RDP->Offset; 1043 OldValueSize = RDP->PatchInfo.OldValueSize; 1044 if (RDP->PatchInfo.DirectRelative) { 1045 UpdatedOffset -= DwarfUnitBaseOffset; 1046 ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 1047 // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 1048 // and overflow if later debug information grows. 1049 if (ByteSequence.size() > OldValueSize) 1050 errs() << "BOLT-ERROR: Relative reference of size " 1051 << Twine::utohexstr(OldValueSize) 1052 << " overflows with the new encoding.\n"; 1053 } else if (RDP->PatchInfo.DirectAbsolute) { 1054 ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 1055 } else if (RDP->PatchInfo.IndirectRelative) { 1056 UpdatedOffset -= DwarfUnitBaseOffset; 1057 ByteSequence.clear(); 1058 raw_string_ostream OS(ByteSequence); 1059 encodeULEB128(UpdatedOffset, OS, 4); 1060 } else { 1061 llvm_unreachable("Invalid Reference form."); 1062 } 1063 break; 1064 } 1065 case DebugPatchKind::PatchValue32: { 1066 DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 1067 Offset = P32->Offset; 1068 OldValueSize = 4; 1069 ByteSequence = encodeLE(4, P32->Value); 1070 break; 1071 } 1072 case DebugPatchKind::PatchValue64to32: { 1073 DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 1074 Offset = P64to32->Offset; 1075 OldValueSize = 8; 1076 ByteSequence = encodeLE(4, P64to32->Value); 1077 break; 1078 } 1079 case DebugPatchKind::PatchValue32GenericSize: { 1080 DebugPatch32GenericSize *DPVS = 1081 reinterpret_cast<DebugPatch32GenericSize *>(P); 1082 Offset = DPVS->Offset; 1083 OldValueSize = DPVS->OldValueSize; 1084 ByteSequence = encodeLE(4, DPVS->Value); 1085 break; 1086 } 1087 case DebugPatchKind::PatchValueVariable: { 1088 DebugPatchVariableSize *PV = 1089 reinterpret_cast<DebugPatchVariableSize *>(P); 1090 Offset = PV->Offset; 1091 OldValueSize = PV->OldValueSize; 1092 ByteSequence.clear(); 1093 raw_string_ostream OS(ByteSequence); 1094 encodeULEB128(PV->Value, OS); 1095 break; 1096 } 1097 case DebugPatchKind::PatchValue64: { 1098 DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 1099 Offset = P64->Offset; 1100 OldValueSize = 8; 1101 ByteSequence = encodeLE(8, P64->Value); 1102 break; 1103 } 1104 case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 1105 DWARFUnitOffsetBaseLabel *BaseLabel = 1106 reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 1107 Offset = BaseLabel->Offset; 1108 OldValueSize = 0; 1109 ByteSequence.clear(); 1110 auto &Patch = LengthPatches.back(); 1111 // Length to copy between last patch entry and next compile unit. 1112 uint32_t RemainingLength = Offset - StartOffset; 1113 uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 1114 DwarfUnitBaseOffset = NewCUOffset; 1115 // Length of previous CU = This CU Offset - sizeof(length) - last CU 1116 // Offset. 1117 Patch.second = NewCUOffset - 4 - Patch.first; 1118 LengthPatches.push_back({NewCUOffset, 0}); 1119 break; 1120 } 1121 case DebugPatchKind::NewDebugEntry: { 1122 NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1123 Offset = NDE->Offset; 1124 OldValueSize = 0; 1125 ByteSequence = NDE->Value; 1126 break; 1127 } 1128 } 1129 1130 assert((P->Kind == DebugPatchKind::NewDebugEntry || 1131 Offset + ByteSequence.size() <= BinaryContents.size()) && 1132 "Applied patch runs over binary size."); 1133 uint32_t Length = Offset - StartOffset; 1134 NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 1135 Length); 1136 NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 1137 StartOffset = Offset + OldValueSize; 1138 } 1139 uint32_t Length = BinaryContents.size() - StartOffset; 1140 NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 1141 Length); 1142 DebugPatches.clear(); 1143 1144 // Patching lengths of CUs 1145 auto &Patch = LengthPatches.back(); 1146 Patch.second = NewBinaryContents.size() - 4 - Patch.first; 1147 for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 1148 const auto &Patch = LengthPatches[J]; 1149 ByteSequence = encodeLE(4, Patch.second); 1150 Offset = Patch.first; 1151 for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 1152 NewBinaryContents[Offset + I] = ByteSequence[I]; 1153 } 1154 1155 return NewBinaryContents; 1156 } 1157 1158 void DebugStrOffsetsWriter::initialize( 1159 const DWARFSection &StrOffsetsSection, 1160 const std::optional<StrOffsetsContributionDescriptor> Contr) { 1161 if (!Contr) 1162 return; 1163 1164 const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize(); 1165 assert(DwarfOffsetByteSize == 4 && 1166 "Dwarf String Offsets Byte Size is not supported."); 1167 uint32_t Index = 0; 1168 for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize) 1169 IndexToAddressMap[Index++] = *reinterpret_cast<const uint32_t *>( 1170 StrOffsetsSection.Data.data() + Contr->Base + Offset); 1171 } 1172 1173 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) { 1174 assert(IndexToAddressMap.count(Index) > 0 && "Index is not found."); 1175 IndexToAddressMap[Index] = Address; 1176 StrOffsetSectionWasModified = true; 1177 } 1178 1179 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit) { 1180 if (IndexToAddressMap.empty()) 1181 return; 1182 1183 std::optional<AttrInfo> AttrVal = 1184 findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base); 1185 assert(AttrVal && "DW_AT_str_offsets_base not present."); 1186 std::optional<uint64_t> Val = AttrVal->V.getAsSectionOffset(); 1187 assert(Val && "DW_AT_str_offsets_base Value not present."); 1188 auto RetVal = ProcessedBaseOffsets.insert(*Val); 1189 if (RetVal.second) { 1190 // Writing out the header for each section. 1191 support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4, 1192 support::little); 1193 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5), 1194 support::little); 1195 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0), 1196 support::little); 1197 for (const auto &Entry : IndexToAddressMap) 1198 support::endian::write(*StrOffsetsStream, Entry.second, support::little); 1199 } 1200 // Will print error if we already processed this contribution, and now 1201 // skipping it, but it was modified. 1202 if (!RetVal.second && StrOffsetSectionWasModified) 1203 errs() << "BOLT-WARNING: skipping string offsets section for CU at offset " 1204 << Twine::utohexstr(Unit.getOffset()) << ", but it was modified\n"; 1205 1206 StrOffsetSectionWasModified = false; 1207 IndexToAddressMap.clear(); 1208 } 1209 1210 void DebugStrWriter::create() { 1211 StrBuffer = std::make_unique<DebugStrBufferVector>(); 1212 StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 1213 } 1214 1215 void DebugStrWriter::initialize() { 1216 auto StrSection = BC.DwCtx->getDWARFObj().getStrSection(); 1217 (*StrStream) << StrSection; 1218 } 1219 1220 uint32_t DebugStrWriter::addString(StringRef Str) { 1221 std::lock_guard<std::mutex> Lock(WriterMutex); 1222 if (StrBuffer->empty()) 1223 initialize(); 1224 auto Offset = StrBuffer->size(); 1225 (*StrStream) << Str; 1226 StrStream->write_zeros(1); 1227 return Offset; 1228 } 1229 1230 void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 1231 const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 1232 if (!Abbrevs) 1233 return; 1234 1235 const PatchesTy &UnitPatches = Patches[&Unit]; 1236 const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 1237 1238 // We are duplicating abbrev sections, to handle the case where for one CU we 1239 // modify it, but for another we don't. 1240 auto UnitDataPtr = std::make_unique<AbbrevData>(); 1241 AbbrevData &UnitData = *UnitDataPtr.get(); 1242 UnitData.Buffer = std::make_unique<DebugBufferVector>(); 1243 UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 1244 1245 raw_svector_ostream &OS = *UnitData.Stream.get(); 1246 1247 // Returns true if AbbrevData is re-used, false otherwise. 1248 auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 1249 llvm::SHA1 Hasher; 1250 Hasher.update(AbbrevData); 1251 std::array<uint8_t, 20> Hash = Hasher.final(); 1252 StringRef Key((const char *)Hash.data(), Hash.size()); 1253 auto Iter = AbbrevDataCache.find(Key); 1254 if (Iter != AbbrevDataCache.end()) { 1255 UnitsAbbrevData[&Unit] = Iter->second.get(); 1256 return true; 1257 } 1258 AbbrevDataCache[Key] = std::move(UnitDataPtr); 1259 UnitsAbbrevData[&Unit] = &UnitData; 1260 return false; 1261 }; 1262 // Take a fast path if there are no patches to apply. Simply copy the original 1263 // contents. 1264 if (UnitPatches.empty() && AbbrevEntries.empty()) { 1265 StringRef AbbrevSectionContents = 1266 Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 1267 : Unit.getContext().getDWARFObj().getAbbrevSection(); 1268 StringRef AbbrevContents; 1269 1270 const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 1271 if (!CUIndex.getRows().empty()) { 1272 // Handle DWP section contribution. 1273 const DWARFUnitIndex::Entry *DWOEntry = 1274 CUIndex.getFromHash(*Unit.getDWOId()); 1275 if (!DWOEntry) 1276 return; 1277 1278 const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 1279 DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 1280 AbbrevContents = AbbrevSectionContents.substr( 1281 DWOContrubution->getOffset(), DWOContrubution->getLength()); 1282 } else if (!Unit.isDWOUnit()) { 1283 const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 1284 1285 // We know where the unit's abbreviation set starts, but not where it ends 1286 // as such data is not readily available. Hence, we have to build a sorted 1287 // list of start addresses and find the next starting address to determine 1288 // the set boundaries. 1289 // 1290 // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 1291 // we wouldn't have to build our own sorted list for the quick lookup. 1292 if (AbbrevSetOffsets.empty()) { 1293 for (const std::pair<const uint64_t, DWARFAbbreviationDeclarationSet> 1294 &P : *Unit.getContext().getDebugAbbrev()) 1295 AbbrevSetOffsets.push_back(P.first); 1296 sort(AbbrevSetOffsets); 1297 } 1298 auto It = upper_bound(AbbrevSetOffsets, StartOffset); 1299 const uint64_t EndOffset = 1300 It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 1301 AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 1302 } else { 1303 // For DWO unit outside of DWP, we expect the entire section to hold 1304 // abbreviations for this unit only. 1305 AbbrevContents = AbbrevSectionContents; 1306 } 1307 1308 if (!hashAndAddAbbrev(AbbrevContents)) { 1309 OS.reserveExtraSpace(AbbrevContents.size()); 1310 OS << AbbrevContents; 1311 } 1312 return; 1313 } 1314 1315 for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 1316 const DWARFAbbreviationDeclaration &Abbrev = *I; 1317 auto Patch = UnitPatches.find(&Abbrev); 1318 1319 encodeULEB128(Abbrev.getCode(), OS); 1320 encodeULEB128(Abbrev.getTag(), OS); 1321 encodeULEB128(Abbrev.hasChildren(), OS); 1322 for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 1323 Abbrev.attributes()) { 1324 if (Patch != UnitPatches.end()) { 1325 bool Patched = false; 1326 // Patches added later take a precedence over earlier ones. 1327 for (const PatchInfo &PI : llvm::reverse(Patch->second)) { 1328 if (PI.OldAttr != AttrSpec.Attr) 1329 continue; 1330 1331 encodeULEB128(PI.NewAttr, OS); 1332 encodeULEB128(PI.NewAttrForm, OS); 1333 Patched = true; 1334 break; 1335 } 1336 if (Patched) 1337 continue; 1338 } 1339 1340 encodeULEB128(AttrSpec.Attr, OS); 1341 encodeULEB128(AttrSpec.Form, OS); 1342 if (AttrSpec.isImplicitConst()) 1343 encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 1344 } 1345 const auto Entries = AbbrevEntries.find(&Abbrev); 1346 // Adding new Abbrevs for inserted entries. 1347 if (Entries != AbbrevEntries.end()) { 1348 for (const AbbrevEntry &Entry : Entries->second) { 1349 encodeULEB128(Entry.Attr, OS); 1350 encodeULEB128(Entry.Form, OS); 1351 } 1352 } 1353 encodeULEB128(0, OS); 1354 encodeULEB128(0, OS); 1355 } 1356 encodeULEB128(0, OS); 1357 1358 hashAndAddAbbrev(OS.str()); 1359 } 1360 1361 std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 1362 // Used to create determinism for writing out abbrevs. 1363 std::vector<AbbrevData *> Abbrevs; 1364 if (DWOId) { 1365 // We expect abbrev_offset to always be zero for DWO units as there 1366 // should be one CU per DWO, and TUs should share the same abbreviation 1367 // set with the CU. 1368 // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 1369 // can be none zero. Thus we are skipping the check for DWP. 1370 bool IsDWP = !Context.getCUIndex().getRows().empty(); 1371 if (!IsDWP) { 1372 for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 1373 if (Unit->getAbbreviationsOffset() != 0) { 1374 errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 1375 "Unable to update debug info.\n"; 1376 exit(1); 1377 } 1378 } 1379 } 1380 1381 DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 1382 // Issue abbreviations for the DWO CU only. 1383 addUnitAbbreviations(*Unit); 1384 AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 1385 Abbrevs.push_back(Abbrev); 1386 } else { 1387 Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 1388 std::unordered_set<AbbrevData *> ProcessedAbbrevs; 1389 // Add abbreviations from compile and type non-DWO units. 1390 for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 1391 addUnitAbbreviations(*Unit); 1392 AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 1393 if (!ProcessedAbbrevs.insert(Abbrev).second) 1394 continue; 1395 Abbrevs.push_back(Abbrev); 1396 } 1397 } 1398 1399 DebugBufferVector ReturnBuffer; 1400 // Pre-calculate the total size of abbrev section. 1401 uint64_t Size = 0; 1402 for (const AbbrevData *UnitData : Abbrevs) 1403 Size += UnitData->Buffer->size(); 1404 1405 ReturnBuffer.reserve(Size); 1406 1407 uint64_t Pos = 0; 1408 for (AbbrevData *UnitData : Abbrevs) { 1409 ReturnBuffer.append(*UnitData->Buffer); 1410 UnitData->Offset = Pos; 1411 Pos += UnitData->Buffer->size(); 1412 1413 UnitData->Buffer.reset(); 1414 UnitData->Stream.reset(); 1415 } 1416 1417 return std::make_unique<DebugBufferVector>(ReturnBuffer); 1418 } 1419 1420 static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 1421 MCDwarfLineTableParams Params, 1422 int64_t LineDelta, uint64_t Address, 1423 int PointerSize) { 1424 // emit the sequence to set the address 1425 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 1426 OS.emitULEB128IntValue(PointerSize + 1); 1427 OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 1428 OS.emitIntValue(Address, PointerSize); 1429 1430 // emit the sequence for the LineDelta (from 1) and a zero address delta. 1431 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 1432 } 1433 1434 static inline void emitBinaryDwarfLineTable( 1435 MCStreamer *MCOS, MCDwarfLineTableParams Params, 1436 const DWARFDebugLine::LineTable *Table, 1437 const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 1438 if (InputSequences.empty()) 1439 return; 1440 1441 constexpr uint64_t InvalidAddress = UINT64_MAX; 1442 unsigned FileNum = 1; 1443 unsigned LastLine = 1; 1444 unsigned Column = 0; 1445 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1446 unsigned Isa = 0; 1447 unsigned Discriminator = 0; 1448 uint64_t LastAddress = InvalidAddress; 1449 uint64_t PrevEndOfSequence = InvalidAddress; 1450 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1451 1452 auto emitEndOfSequence = [&](uint64_t Address) { 1453 MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1454 FileNum = 1; 1455 LastLine = 1; 1456 Column = 0; 1457 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1458 Isa = 0; 1459 Discriminator = 0; 1460 LastAddress = InvalidAddress; 1461 }; 1462 1463 for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1464 const uint64_t SequenceStart = 1465 Table->Rows[Sequence.FirstIndex].Address.Address; 1466 1467 // Check if we need to mark the end of the sequence. 1468 if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1469 PrevEndOfSequence != SequenceStart) { 1470 emitEndOfSequence(PrevEndOfSequence); 1471 } 1472 1473 for (uint32_t RowIndex = Sequence.FirstIndex; 1474 RowIndex <= Sequence.LastIndex; ++RowIndex) { 1475 const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1476 int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1477 const uint64_t Address = Row.Address.Address; 1478 1479 if (FileNum != Row.File) { 1480 FileNum = Row.File; 1481 MCOS->emitInt8(dwarf::DW_LNS_set_file); 1482 MCOS->emitULEB128IntValue(FileNum); 1483 } 1484 if (Column != Row.Column) { 1485 Column = Row.Column; 1486 MCOS->emitInt8(dwarf::DW_LNS_set_column); 1487 MCOS->emitULEB128IntValue(Column); 1488 } 1489 if (Discriminator != Row.Discriminator && 1490 MCOS->getContext().getDwarfVersion() >= 4) { 1491 Discriminator = Row.Discriminator; 1492 unsigned Size = getULEB128Size(Discriminator); 1493 MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1494 MCOS->emitULEB128IntValue(Size + 1); 1495 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1496 MCOS->emitULEB128IntValue(Discriminator); 1497 } 1498 if (Isa != Row.Isa) { 1499 Isa = Row.Isa; 1500 MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1501 MCOS->emitULEB128IntValue(Isa); 1502 } 1503 if (Row.IsStmt != Flags) { 1504 Flags = Row.IsStmt; 1505 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1506 } 1507 if (Row.BasicBlock) 1508 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1509 if (Row.PrologueEnd) 1510 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1511 if (Row.EpilogueBegin) 1512 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1513 1514 // The end of the sequence is not normal in the middle of the input 1515 // sequence, but could happen, e.g. for assembly code. 1516 if (Row.EndSequence) { 1517 emitEndOfSequence(Address); 1518 } else { 1519 if (LastAddress == InvalidAddress) 1520 emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1521 AsmInfo->getCodePointerSize()); 1522 else 1523 MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1524 1525 LastAddress = Address; 1526 LastLine = Row.Line; 1527 } 1528 1529 Discriminator = 0; 1530 } 1531 PrevEndOfSequence = Sequence.EndAddress; 1532 } 1533 1534 // Finish with the end of the sequence. 1535 if (LastAddress != InvalidAddress) 1536 emitEndOfSequence(PrevEndOfSequence); 1537 } 1538 1539 // This function is similar to the one from MCDwarfLineTable, except it handles 1540 // end-of-sequence entries differently by utilizing line entries with 1541 // DWARF2_FLAG_END_SEQUENCE flag. 1542 static inline void emitDwarfLineTable( 1543 MCStreamer *MCOS, MCSection *Section, 1544 const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1545 unsigned FileNum = 1; 1546 unsigned LastLine = 1; 1547 unsigned Column = 0; 1548 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1549 unsigned Isa = 0; 1550 unsigned Discriminator = 0; 1551 MCSymbol *LastLabel = nullptr; 1552 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1553 1554 // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1555 for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1556 if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1557 MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1558 AsmInfo->getCodePointerSize()); 1559 FileNum = 1; 1560 LastLine = 1; 1561 Column = 0; 1562 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1563 Isa = 0; 1564 Discriminator = 0; 1565 LastLabel = nullptr; 1566 continue; 1567 } 1568 1569 int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1570 1571 if (FileNum != LineEntry.getFileNum()) { 1572 FileNum = LineEntry.getFileNum(); 1573 MCOS->emitInt8(dwarf::DW_LNS_set_file); 1574 MCOS->emitULEB128IntValue(FileNum); 1575 } 1576 if (Column != LineEntry.getColumn()) { 1577 Column = LineEntry.getColumn(); 1578 MCOS->emitInt8(dwarf::DW_LNS_set_column); 1579 MCOS->emitULEB128IntValue(Column); 1580 } 1581 if (Discriminator != LineEntry.getDiscriminator() && 1582 MCOS->getContext().getDwarfVersion() >= 2) { 1583 Discriminator = LineEntry.getDiscriminator(); 1584 unsigned Size = getULEB128Size(Discriminator); 1585 MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1586 MCOS->emitULEB128IntValue(Size + 1); 1587 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1588 MCOS->emitULEB128IntValue(Discriminator); 1589 } 1590 if (Isa != LineEntry.getIsa()) { 1591 Isa = LineEntry.getIsa(); 1592 MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1593 MCOS->emitULEB128IntValue(Isa); 1594 } 1595 if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1596 Flags = LineEntry.getFlags(); 1597 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1598 } 1599 if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1600 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1601 if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1602 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1603 if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1604 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1605 1606 MCSymbol *Label = LineEntry.getLabel(); 1607 1608 // At this point we want to emit/create the sequence to encode the delta 1609 // in line numbers and the increment of the address from the previous 1610 // Label and the current Label. 1611 MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1612 AsmInfo->getCodePointerSize()); 1613 Discriminator = 0; 1614 LastLine = LineEntry.getLine(); 1615 LastLabel = Label; 1616 } 1617 1618 assert(LastLabel == nullptr && "end of sequence expected"); 1619 } 1620 1621 void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1622 std::optional<MCDwarfLineStr> &LineStr, 1623 BinaryContext &BC) const { 1624 if (!RawData.empty()) { 1625 assert(MCLineSections.getMCLineEntries().empty() && 1626 InputSequences.empty() && 1627 "cannot combine raw data with new line entries"); 1628 MCOS->emitLabel(getLabel()); 1629 MCOS->emitBytes(RawData); 1630 1631 // Emit fake relocation for RuntimeDyld to always allocate the section. 1632 // 1633 // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1634 // without relocations. 1635 MCOS->emitRelocDirective( 1636 *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1637 MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1638 1639 return; 1640 } 1641 1642 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1643 1644 // Put out the line tables. 1645 for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1646 emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1647 1648 // Emit line tables for the original code. 1649 emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1650 1651 // This is the end of the section, so set the value of the symbol at the end 1652 // of this section (that was used in a previous expression). 1653 MCOS->emitLabel(LineEndSym); 1654 } 1655 1656 // Helper function to parse .debug_line_str, and populate one we are using. 1657 // For functions that we do not modify we output them as raw data. 1658 // Re-constructing .debug_line_str so that offsets are correct for those 1659 // debut line tables. 1660 // Bonus is that when we output a final binary we can re-use .debug_line_str 1661 // section. So we don't have to do the SHF_ALLOC trick we did with 1662 // .debug_line. 1663 static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, 1664 MCDwarfLineStr &LineStr, 1665 BinaryContext &BC, 1666 MCStreamer &Streamer) { 1667 DataExtractor StrData(LineStrSection.getContents(), 1668 BC.DwCtx->isLittleEndian(), 0); 1669 uint64_t Offset = 0; 1670 while (StrData.isValidOffset(Offset)) { 1671 Error Err = Error::success(); 1672 const char *CStr = StrData.getCStr(&Offset, &Err); 1673 if (Err) { 1674 errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; 1675 continue; 1676 } 1677 LineStr.emitRef(&Streamer, CStr); 1678 } 1679 } 1680 1681 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1682 MCAssembler &Assembler = 1683 static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1684 1685 MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1686 1687 auto &LineTables = BC.getDwarfLineTables(); 1688 1689 // Bail out early so we don't switch to the debug_line section needlessly and 1690 // in doing so create an unnecessary (if empty) section. 1691 if (LineTables.empty()) 1692 return; 1693 // In a v5 non-split line table, put the strings in a separate section. 1694 std::optional<MCDwarfLineStr> LineStr; 1695 ErrorOr<BinarySection &> LineStrSection = 1696 BC.getUniqueSectionByName(".debug_line_str"); 1697 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower 1698 // .debug_line 1699 if (LineStrSection) { 1700 LineStr.emplace(*BC.Ctx); 1701 parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer); 1702 } 1703 1704 // Switch to the section where the table will be emitted into. 1705 Streamer.switchSection(BC.MOFI->getDwarfLineSection()); 1706 1707 const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); 1708 // Handle the rest of the Compile Units. 1709 for (auto &CUIDTablePair : LineTables) { 1710 Streamer.getContext().setDwarfVersion( 1711 CUIDTablePair.second.getDwarfVersion()); 1712 CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1713 } 1714 1715 // Resetting DWARF version for rest of the flow. 1716 BC.Ctx->setDwarfVersion(DwarfVersion); 1717 1718 // Still need to write the section out for the ExecutionEngine, and temp in 1719 // memory object we are constructing. 1720 if (LineStr) { 1721 LineStr->emitSection(&Streamer); 1722 SmallString<0> Data = LineStr->getFinalizedData(); 1723 BC.registerOrUpdateNoteSection(".debug_line_str", copyByteArray(Data.str()), 1724 Data.size()); 1725 } 1726 } 1727 1728 } // namespace bolt 1729 } // namespace llvm 1730