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