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 std::optional<AttrInfo> AttrInfoVal = 737 findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base); 738 // Pointing to first one, because it doesn't matter. There are no uses of it 739 // in this CU. 740 if (!isSplitDwarf() && AttrInfoVal) 741 DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset, 742 getDWARF5RngListLocListHeaderSize()); 743 return; 744 } 745 746 std::unique_ptr<DebugBufferVector> LocArrayBuffer = 747 std::make_unique<DebugBufferVector>(); 748 std::unique_ptr<raw_svector_ostream> LocArrayStream = 749 std::make_unique<raw_svector_ostream>(*LocArrayBuffer); 750 751 const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t); 752 // Write out IndexArray 753 for (uint32_t RelativeOffset : RelativeLocListOffsets) 754 support::endian::write( 755 *LocArrayStream, 756 static_cast<uint32_t>(SizeOfArraySection + RelativeOffset), 757 support::little); 758 759 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 760 {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()), 761 5, 8, 0, NumberOfEntries}); 762 *LocStream << *Header; 763 *LocStream << *LocArrayBuffer; 764 *LocStream << *LocBodyBuffer; 765 766 if (!isSplitDwarf()) { 767 if (std::optional<AttrInfo> AttrInfoVal = 768 findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base)) 769 DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset, 770 LoclistBaseOffset + 771 getDWARF5RngListLocListHeaderSize()); 772 else { 773 AbbrevWriter.addAttribute( 774 CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(), 775 dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset); 776 DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(), 777 LoclistBaseOffset + Header->size()); 778 } 779 LoclistBaseOffset += LocBuffer->size(); 780 } 781 clearList(RelativeLocListOffsets); 782 clearList(*LocArrayBuffer); 783 clearList(*LocBodyBuffer); 784 } 785 786 void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 787 DebugAbbrevWriter &AbbrevWriter) { 788 if (DwarfVersion >= 5) 789 finalizeDWARF5(DebugInfoPatcher, AbbrevWriter); 790 } 791 792 DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 793 794 void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 795 Offset -= DWPUnitOffset; 796 std::lock_guard<std::mutex> Lock(WriterMutex); 797 DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 798 } 799 800 void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 801 Offset -= DWPUnitOffset; 802 std::lock_guard<std::mutex> Lock(WriterMutex); 803 auto RetVal = DestinationLabels.insert(Offset); 804 if (!RetVal.second) 805 return; 806 807 DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 808 } 809 810 static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 811 std::string LE64(ByteSize, 0); 812 for (size_t I = 0; I < ByteSize; ++I) { 813 LE64[I] = NewValue & 0xff; 814 NewValue >>= 8; 815 } 816 return LE64; 817 } 818 819 void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 820 uint32_t Value) { 821 std::string StrValue = encodeLE(4, Value); 822 insertNewEntry(DIE, std::move(StrValue)); 823 } 824 825 void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 826 std::string &&Value) { 827 const DWARFAbbreviationDeclaration *AbbrevDecl = 828 DIE.getAbbreviationDeclarationPtr(); 829 830 // In case this DIE has no attributes. 831 uint32_t Offset = DIE.getOffset() + 1; 832 size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 833 if (NumOfAttributes) { 834 std::optional<AttrInfo> Val = 835 findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 836 assert(Val && "Invalid Value."); 837 838 Offset = Val->Offset + Val->Size - DWPUnitOffset; 839 } 840 std::lock_guard<std::mutex> Lock(WriterMutex); 841 DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 842 } 843 844 void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 845 uint32_t DestinationOffset, 846 uint32_t OldValueSize, 847 dwarf::Form Form) { 848 Offset -= DWPUnitOffset; 849 DestinationOffset -= DWPUnitOffset; 850 std::lock_guard<std::mutex> Lock(WriterMutex); 851 DebugPatches.emplace_back( 852 new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 853 } 854 855 void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 856 uint32_t OldValueSize) { 857 Offset -= DWPUnitOffset; 858 std::lock_guard<std::mutex> Lock(WriterMutex); 859 DebugPatches.emplace_back( 860 new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 861 } 862 863 void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 864 Offset -= DWPUnitOffset; 865 std::lock_guard<std::mutex> Lock(WriterMutex); 866 DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 867 } 868 869 void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 870 uint32_t OldValueSize) { 871 Offset -= DWPUnitOffset; 872 std::lock_guard<std::mutex> Lock(WriterMutex); 873 if (OldValueSize == 4) 874 DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 875 else if (OldValueSize == 8) 876 DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 877 else 878 DebugPatches.emplace_back( 879 new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); 880 } 881 882 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 883 std::string &&NewValue, 884 uint32_t OldValueSize) { 885 Patches.emplace_back(Offset, std::move(NewValue)); 886 } 887 888 void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 889 auto Str = std::string(1, Value); 890 Patches.emplace_back(Offset, std::move(Str)); 891 } 892 893 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 894 size_t ByteSize) { 895 Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 896 } 897 898 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 899 uint32_t OldValueSize) { 900 std::string Buff; 901 raw_string_ostream OS(Buff); 902 encodeULEB128(Value, OS, OldValueSize); 903 904 Patches.emplace_back(Offset, std::move(Buff)); 905 } 906 907 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 908 addLEPatch(Offset, NewValue, 8); 909 } 910 911 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 912 uint32_t OldValueSize) { 913 addLEPatch(Offset, NewValue, 4); 914 } 915 916 std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 917 std::string BinaryContentsStr = std::string(BinaryContents); 918 for (const auto &Patch : Patches) { 919 uint32_t Offset = Patch.first; 920 const std::string &ByteSequence = Patch.second; 921 assert(Offset + ByteSequence.size() <= BinaryContents.size() && 922 "Applied patch runs over binary size."); 923 for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 924 BinaryContentsStr[Offset + I] = ByteSequence[I]; 925 } 926 } 927 return BinaryContentsStr; 928 } 929 930 CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 931 bool IsDWOContext) { 932 CUOffsetMap CUMap; 933 llvm::sort(DebugPatches, [](const UniquePatchPtrType &V1, 934 const UniquePatchPtrType &V2) { 935 if (V1.get()->Offset == V2.get()->Offset) { 936 if (V1->Kind == DebugPatchKind::NewDebugEntry && 937 V2->Kind == DebugPatchKind::NewDebugEntry) 938 return reinterpret_cast<const NewDebugEntry *>(V1.get())->CurrentOrder < 939 reinterpret_cast<const NewDebugEntry *>(V2.get())->CurrentOrder; 940 941 // This is a case where we are modifying first entry of next 942 // DIE, and adding a new one. 943 return V1->Kind == DebugPatchKind::NewDebugEntry; 944 } 945 return V1.get()->Offset < V2.get()->Offset; 946 }); 947 948 DWARFUnitVector::compile_unit_range CompileUnits = 949 IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 950 951 for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 952 CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 953 static_cast<uint32_t>(CU->getLength())}; 954 955 // Calculating changes in .debug_info size from Patches to build a map of old 956 // to updated reference destination offsets. 957 uint32_t PreviousOffset = 0; 958 int32_t PreviousChangeInSize = 0; 959 for (UniquePatchPtrType &PatchBase : DebugPatches) { 960 Patch *P = PatchBase.get(); 961 switch (P->Kind) { 962 default: 963 continue; 964 case DebugPatchKind::PatchValue64to32: { 965 PreviousChangeInSize -= 4; 966 break; 967 } 968 case DebugPatchKind::PatchValue32GenericSize: { 969 DebugPatch32GenericSize *DPVS = 970 reinterpret_cast<DebugPatch32GenericSize *>(P); 971 PreviousChangeInSize += 4 - DPVS->OldValueSize; 972 break; 973 } 974 case DebugPatchKind::PatchValueVariable: { 975 DebugPatchVariableSize *DPV = 976 reinterpret_cast<DebugPatchVariableSize *>(P); 977 std::string Temp; 978 raw_string_ostream OS(Temp); 979 encodeULEB128(DPV->Value, OS); 980 PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 981 break; 982 } 983 case DebugPatchKind::DestinationReferenceLabel: { 984 DestinationReferenceLabel *DRL = 985 reinterpret_cast<DestinationReferenceLabel *>(P); 986 OldToNewOffset[DRL->Offset] = 987 DRL->Offset + ChangeInSize + PreviousChangeInSize; 988 break; 989 } 990 case DebugPatchKind::ReferencePatchValue: { 991 // This doesn't look to be a common case, so will always encode as 4 bytes 992 // to reduce algorithmic complexity. 993 DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 994 if (RDP->PatchInfo.IndirectRelative) { 995 PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 996 assert(RDP->PatchInfo.OldValueSize <= 4 && 997 "Variable encoding reference greater than 4 bytes."); 998 } 999 break; 1000 } 1001 case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 1002 DWARFUnitOffsetBaseLabel *BaseLabel = 1003 reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 1004 uint32_t CUOffset = BaseLabel->Offset; 1005 ChangeInSize += PreviousChangeInSize; 1006 uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 1007 CUMap[CUOffset].Offset = CUOffsetUpdate; 1008 CUMap[PreviousOffset].Length += PreviousChangeInSize; 1009 PreviousChangeInSize = 0; 1010 PreviousOffset = CUOffset; 1011 break; 1012 } 1013 case DebugPatchKind::NewDebugEntry: { 1014 NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1015 PreviousChangeInSize += NDE->Value.size(); 1016 break; 1017 } 1018 } 1019 } 1020 CUMap[PreviousOffset].Length += PreviousChangeInSize; 1021 return CUMap; 1022 } 1023 uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 1024 1025 std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 1026 std::string NewBinaryContents; 1027 NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 1028 uint32_t StartOffset = 0; 1029 uint32_t DwarfUnitBaseOffset = 0; 1030 uint32_t OldValueSize = 0; 1031 uint32_t Offset = 0; 1032 std::string ByteSequence; 1033 std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 1034 // Wasting one entry to avoid checks for first. 1035 LengthPatches.push_back({0, 0}); 1036 1037 // Applying all the patches replacing current entry. 1038 // This might change the size of .debug_info section. 1039 for (const UniquePatchPtrType &PatchBase : DebugPatches) { 1040 Patch *P = PatchBase.get(); 1041 switch (P->Kind) { 1042 default: 1043 continue; 1044 case DebugPatchKind::ReferencePatchValue: { 1045 DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 1046 uint32_t DestinationOffset = RDP->DestinationOffset; 1047 assert(OldToNewOffset.count(DestinationOffset) && 1048 "Destination Offset for reference not updated."); 1049 uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 1050 Offset = RDP->Offset; 1051 OldValueSize = RDP->PatchInfo.OldValueSize; 1052 if (RDP->PatchInfo.DirectRelative) { 1053 UpdatedOffset -= DwarfUnitBaseOffset; 1054 ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 1055 // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 1056 // and overflow if later debug information grows. 1057 if (ByteSequence.size() > OldValueSize) 1058 errs() << "BOLT-ERROR: Relative reference of size " 1059 << Twine::utohexstr(OldValueSize) 1060 << " overflows with the new encoding.\n"; 1061 } else if (RDP->PatchInfo.DirectAbsolute) { 1062 ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 1063 } else if (RDP->PatchInfo.IndirectRelative) { 1064 UpdatedOffset -= DwarfUnitBaseOffset; 1065 ByteSequence.clear(); 1066 raw_string_ostream OS(ByteSequence); 1067 encodeULEB128(UpdatedOffset, OS, 4); 1068 } else { 1069 llvm_unreachable("Invalid Reference form."); 1070 } 1071 break; 1072 } 1073 case DebugPatchKind::PatchValue32: { 1074 DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 1075 Offset = P32->Offset; 1076 OldValueSize = 4; 1077 ByteSequence = encodeLE(4, P32->Value); 1078 break; 1079 } 1080 case DebugPatchKind::PatchValue64to32: { 1081 DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 1082 Offset = P64to32->Offset; 1083 OldValueSize = 8; 1084 ByteSequence = encodeLE(4, P64to32->Value); 1085 break; 1086 } 1087 case DebugPatchKind::PatchValue32GenericSize: { 1088 DebugPatch32GenericSize *DPVS = 1089 reinterpret_cast<DebugPatch32GenericSize *>(P); 1090 Offset = DPVS->Offset; 1091 OldValueSize = DPVS->OldValueSize; 1092 ByteSequence = encodeLE(4, DPVS->Value); 1093 break; 1094 } 1095 case DebugPatchKind::PatchValueVariable: { 1096 DebugPatchVariableSize *PV = 1097 reinterpret_cast<DebugPatchVariableSize *>(P); 1098 Offset = PV->Offset; 1099 OldValueSize = PV->OldValueSize; 1100 ByteSequence.clear(); 1101 raw_string_ostream OS(ByteSequence); 1102 encodeULEB128(PV->Value, OS); 1103 break; 1104 } 1105 case DebugPatchKind::PatchValue64: { 1106 DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 1107 Offset = P64->Offset; 1108 OldValueSize = 8; 1109 ByteSequence = encodeLE(8, P64->Value); 1110 break; 1111 } 1112 case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 1113 DWARFUnitOffsetBaseLabel *BaseLabel = 1114 reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 1115 Offset = BaseLabel->Offset; 1116 OldValueSize = 0; 1117 ByteSequence.clear(); 1118 auto &Patch = LengthPatches.back(); 1119 // Length to copy between last patch entry and next compile unit. 1120 uint32_t RemainingLength = Offset - StartOffset; 1121 uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 1122 DwarfUnitBaseOffset = NewCUOffset; 1123 // Length of previous CU = This CU Offset - sizeof(length) - last CU 1124 // Offset. 1125 Patch.second = NewCUOffset - 4 - Patch.first; 1126 LengthPatches.push_back({NewCUOffset, 0}); 1127 break; 1128 } 1129 case DebugPatchKind::NewDebugEntry: { 1130 NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1131 Offset = NDE->Offset; 1132 OldValueSize = 0; 1133 ByteSequence = NDE->Value; 1134 break; 1135 } 1136 } 1137 1138 assert((P->Kind == DebugPatchKind::NewDebugEntry || 1139 Offset + ByteSequence.size() <= BinaryContents.size()) && 1140 "Applied patch runs over binary size."); 1141 uint32_t Length = Offset - StartOffset; 1142 NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 1143 Length); 1144 NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 1145 StartOffset = Offset + OldValueSize; 1146 } 1147 uint32_t Length = BinaryContents.size() - StartOffset; 1148 NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 1149 Length); 1150 DebugPatches.clear(); 1151 1152 // Patching lengths of CUs 1153 auto &Patch = LengthPatches.back(); 1154 Patch.second = NewBinaryContents.size() - 4 - Patch.first; 1155 for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 1156 const auto &Patch = LengthPatches[J]; 1157 ByteSequence = encodeLE(4, Patch.second); 1158 Offset = Patch.first; 1159 for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 1160 NewBinaryContents[Offset + I] = ByteSequence[I]; 1161 } 1162 1163 return NewBinaryContents; 1164 } 1165 1166 void DebugStrOffsetsWriter::initialize( 1167 const DWARFSection &StrOffsetsSection, 1168 const std::optional<StrOffsetsContributionDescriptor> Contr) { 1169 if (!Contr) 1170 return; 1171 1172 const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize(); 1173 assert(DwarfOffsetByteSize == 4 && 1174 "Dwarf String Offsets Byte Size is not supported."); 1175 uint32_t Index = 0; 1176 for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize) 1177 IndexToAddressMap[Index++] = support::endian::read32le( 1178 StrOffsetsSection.Data.data() + Contr->Base + Offset); 1179 } 1180 1181 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) { 1182 assert(IndexToAddressMap.count(Index) > 0 && "Index is not found."); 1183 IndexToAddressMap[Index] = Address; 1184 StrOffsetSectionWasModified = true; 1185 } 1186 1187 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit) { 1188 if (IndexToAddressMap.empty()) 1189 return; 1190 1191 std::optional<AttrInfo> AttrVal = 1192 findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base); 1193 assert(AttrVal && "DW_AT_str_offsets_base not present."); 1194 std::optional<uint64_t> Val = AttrVal->V.getAsSectionOffset(); 1195 assert(Val && "DW_AT_str_offsets_base Value not present."); 1196 auto RetVal = ProcessedBaseOffsets.insert(*Val); 1197 if (RetVal.second) { 1198 // Writing out the header for each section. 1199 support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4, 1200 support::little); 1201 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5), 1202 support::little); 1203 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0), 1204 support::little); 1205 for (const auto &Entry : IndexToAddressMap) 1206 support::endian::write(*StrOffsetsStream, Entry.second, support::little); 1207 } 1208 // Will print error if we already processed this contribution, and now 1209 // skipping it, but it was modified. 1210 if (!RetVal.second && StrOffsetSectionWasModified) 1211 errs() << "BOLT-WARNING: skipping string offsets section for CU at offset " 1212 << Twine::utohexstr(Unit.getOffset()) << ", but it was modified\n"; 1213 1214 StrOffsetSectionWasModified = false; 1215 IndexToAddressMap.clear(); 1216 } 1217 1218 void DebugStrWriter::create() { 1219 StrBuffer = std::make_unique<DebugStrBufferVector>(); 1220 StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 1221 } 1222 1223 void DebugStrWriter::initialize() { 1224 auto StrSection = BC.DwCtx->getDWARFObj().getStrSection(); 1225 (*StrStream) << StrSection; 1226 } 1227 1228 uint32_t DebugStrWriter::addString(StringRef Str) { 1229 std::lock_guard<std::mutex> Lock(WriterMutex); 1230 if (StrBuffer->empty()) 1231 initialize(); 1232 auto Offset = StrBuffer->size(); 1233 (*StrStream) << Str; 1234 StrStream->write_zeros(1); 1235 return Offset; 1236 } 1237 1238 void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 1239 const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 1240 if (!Abbrevs) 1241 return; 1242 1243 const PatchesTy &UnitPatches = Patches[&Unit]; 1244 const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 1245 1246 // We are duplicating abbrev sections, to handle the case where for one CU we 1247 // modify it, but for another we don't. 1248 auto UnitDataPtr = std::make_unique<AbbrevData>(); 1249 AbbrevData &UnitData = *UnitDataPtr.get(); 1250 UnitData.Buffer = std::make_unique<DebugBufferVector>(); 1251 UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 1252 1253 raw_svector_ostream &OS = *UnitData.Stream.get(); 1254 1255 // Returns true if AbbrevData is re-used, false otherwise. 1256 auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 1257 llvm::SHA1 Hasher; 1258 Hasher.update(AbbrevData); 1259 std::array<uint8_t, 20> Hash = Hasher.final(); 1260 StringRef Key((const char *)Hash.data(), Hash.size()); 1261 auto Iter = AbbrevDataCache.find(Key); 1262 if (Iter != AbbrevDataCache.end()) { 1263 UnitsAbbrevData[&Unit] = Iter->second.get(); 1264 return true; 1265 } 1266 AbbrevDataCache[Key] = std::move(UnitDataPtr); 1267 UnitsAbbrevData[&Unit] = &UnitData; 1268 return false; 1269 }; 1270 // Take a fast path if there are no patches to apply. Simply copy the original 1271 // contents. 1272 if (UnitPatches.empty() && AbbrevEntries.empty()) { 1273 StringRef AbbrevSectionContents = 1274 Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 1275 : Unit.getContext().getDWARFObj().getAbbrevSection(); 1276 StringRef AbbrevContents; 1277 1278 const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 1279 if (!CUIndex.getRows().empty()) { 1280 // Handle DWP section contribution. 1281 const DWARFUnitIndex::Entry *DWOEntry = 1282 CUIndex.getFromHash(*Unit.getDWOId()); 1283 if (!DWOEntry) 1284 return; 1285 1286 const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 1287 DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 1288 AbbrevContents = AbbrevSectionContents.substr( 1289 DWOContrubution->getOffset(), DWOContrubution->getLength()); 1290 } else if (!Unit.isDWOUnit()) { 1291 const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 1292 1293 // We know where the unit's abbreviation set starts, but not where it ends 1294 // as such data is not readily available. Hence, we have to build a sorted 1295 // list of start addresses and find the next starting address to determine 1296 // the set boundaries. 1297 // 1298 // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 1299 // we wouldn't have to build our own sorted list for the quick lookup. 1300 if (AbbrevSetOffsets.empty()) { 1301 for (const std::pair<const uint64_t, DWARFAbbreviationDeclarationSet> 1302 &P : *Unit.getContext().getDebugAbbrev()) 1303 AbbrevSetOffsets.push_back(P.first); 1304 sort(AbbrevSetOffsets); 1305 } 1306 auto It = upper_bound(AbbrevSetOffsets, StartOffset); 1307 const uint64_t EndOffset = 1308 It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 1309 AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 1310 } else { 1311 // For DWO unit outside of DWP, we expect the entire section to hold 1312 // abbreviations for this unit only. 1313 AbbrevContents = AbbrevSectionContents; 1314 } 1315 1316 if (!hashAndAddAbbrev(AbbrevContents)) { 1317 OS.reserveExtraSpace(AbbrevContents.size()); 1318 OS << AbbrevContents; 1319 } 1320 return; 1321 } 1322 1323 for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 1324 const DWARFAbbreviationDeclaration &Abbrev = *I; 1325 auto Patch = UnitPatches.find(&Abbrev); 1326 1327 encodeULEB128(Abbrev.getCode(), OS); 1328 encodeULEB128(Abbrev.getTag(), OS); 1329 encodeULEB128(Abbrev.hasChildren(), OS); 1330 for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 1331 Abbrev.attributes()) { 1332 if (Patch != UnitPatches.end()) { 1333 bool Patched = false; 1334 // Patches added later take a precedence over earlier ones. 1335 for (const PatchInfo &PI : llvm::reverse(Patch->second)) { 1336 if (PI.OldAttr != AttrSpec.Attr) 1337 continue; 1338 1339 encodeULEB128(PI.NewAttr, OS); 1340 encodeULEB128(PI.NewAttrForm, OS); 1341 Patched = true; 1342 break; 1343 } 1344 if (Patched) 1345 continue; 1346 } 1347 1348 encodeULEB128(AttrSpec.Attr, OS); 1349 encodeULEB128(AttrSpec.Form, OS); 1350 if (AttrSpec.isImplicitConst()) 1351 encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 1352 } 1353 const auto Entries = AbbrevEntries.find(&Abbrev); 1354 // Adding new Abbrevs for inserted entries. 1355 if (Entries != AbbrevEntries.end()) { 1356 for (const AbbrevEntry &Entry : Entries->second) { 1357 encodeULEB128(Entry.Attr, OS); 1358 encodeULEB128(Entry.Form, OS); 1359 } 1360 } 1361 encodeULEB128(0, OS); 1362 encodeULEB128(0, OS); 1363 } 1364 encodeULEB128(0, OS); 1365 1366 hashAndAddAbbrev(OS.str()); 1367 } 1368 1369 std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 1370 // Used to create determinism for writing out abbrevs. 1371 std::vector<AbbrevData *> Abbrevs; 1372 if (DWOId) { 1373 // We expect abbrev_offset to always be zero for DWO units as there 1374 // should be one CU per DWO, and TUs should share the same abbreviation 1375 // set with the CU. 1376 // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 1377 // can be none zero. Thus we are skipping the check for DWP. 1378 bool IsDWP = !Context.getCUIndex().getRows().empty(); 1379 if (!IsDWP) { 1380 for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 1381 if (Unit->getAbbreviationsOffset() != 0) { 1382 errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 1383 "Unable to update debug info.\n"; 1384 exit(1); 1385 } 1386 } 1387 } 1388 1389 DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 1390 // Issue abbreviations for the DWO CU only. 1391 addUnitAbbreviations(*Unit); 1392 AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 1393 Abbrevs.push_back(Abbrev); 1394 } else { 1395 Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 1396 std::unordered_set<AbbrevData *> ProcessedAbbrevs; 1397 // Add abbreviations from compile and type non-DWO units. 1398 for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 1399 addUnitAbbreviations(*Unit); 1400 AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 1401 if (!ProcessedAbbrevs.insert(Abbrev).second) 1402 continue; 1403 Abbrevs.push_back(Abbrev); 1404 } 1405 } 1406 1407 DebugBufferVector ReturnBuffer; 1408 // Pre-calculate the total size of abbrev section. 1409 uint64_t Size = 0; 1410 for (const AbbrevData *UnitData : Abbrevs) 1411 Size += UnitData->Buffer->size(); 1412 1413 ReturnBuffer.reserve(Size); 1414 1415 uint64_t Pos = 0; 1416 for (AbbrevData *UnitData : Abbrevs) { 1417 ReturnBuffer.append(*UnitData->Buffer); 1418 UnitData->Offset = Pos; 1419 Pos += UnitData->Buffer->size(); 1420 1421 UnitData->Buffer.reset(); 1422 UnitData->Stream.reset(); 1423 } 1424 1425 return std::make_unique<DebugBufferVector>(ReturnBuffer); 1426 } 1427 1428 static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 1429 MCDwarfLineTableParams Params, 1430 int64_t LineDelta, uint64_t Address, 1431 int PointerSize) { 1432 // emit the sequence to set the address 1433 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 1434 OS.emitULEB128IntValue(PointerSize + 1); 1435 OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 1436 OS.emitIntValue(Address, PointerSize); 1437 1438 // emit the sequence for the LineDelta (from 1) and a zero address delta. 1439 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 1440 } 1441 1442 static inline void emitBinaryDwarfLineTable( 1443 MCStreamer *MCOS, MCDwarfLineTableParams Params, 1444 const DWARFDebugLine::LineTable *Table, 1445 const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 1446 if (InputSequences.empty()) 1447 return; 1448 1449 constexpr uint64_t InvalidAddress = UINT64_MAX; 1450 unsigned FileNum = 1; 1451 unsigned LastLine = 1; 1452 unsigned Column = 0; 1453 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1454 unsigned Isa = 0; 1455 unsigned Discriminator = 0; 1456 uint64_t LastAddress = InvalidAddress; 1457 uint64_t PrevEndOfSequence = InvalidAddress; 1458 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1459 1460 auto emitEndOfSequence = [&](uint64_t Address) { 1461 MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1462 FileNum = 1; 1463 LastLine = 1; 1464 Column = 0; 1465 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1466 Isa = 0; 1467 Discriminator = 0; 1468 LastAddress = InvalidAddress; 1469 }; 1470 1471 for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1472 const uint64_t SequenceStart = 1473 Table->Rows[Sequence.FirstIndex].Address.Address; 1474 1475 // Check if we need to mark the end of the sequence. 1476 if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1477 PrevEndOfSequence != SequenceStart) { 1478 emitEndOfSequence(PrevEndOfSequence); 1479 } 1480 1481 for (uint32_t RowIndex = Sequence.FirstIndex; 1482 RowIndex <= Sequence.LastIndex; ++RowIndex) { 1483 const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1484 int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1485 const uint64_t Address = Row.Address.Address; 1486 1487 if (FileNum != Row.File) { 1488 FileNum = Row.File; 1489 MCOS->emitInt8(dwarf::DW_LNS_set_file); 1490 MCOS->emitULEB128IntValue(FileNum); 1491 } 1492 if (Column != Row.Column) { 1493 Column = Row.Column; 1494 MCOS->emitInt8(dwarf::DW_LNS_set_column); 1495 MCOS->emitULEB128IntValue(Column); 1496 } 1497 if (Discriminator != Row.Discriminator && 1498 MCOS->getContext().getDwarfVersion() >= 4) { 1499 Discriminator = Row.Discriminator; 1500 unsigned Size = getULEB128Size(Discriminator); 1501 MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1502 MCOS->emitULEB128IntValue(Size + 1); 1503 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1504 MCOS->emitULEB128IntValue(Discriminator); 1505 } 1506 if (Isa != Row.Isa) { 1507 Isa = Row.Isa; 1508 MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1509 MCOS->emitULEB128IntValue(Isa); 1510 } 1511 if (Row.IsStmt != Flags) { 1512 Flags = Row.IsStmt; 1513 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1514 } 1515 if (Row.BasicBlock) 1516 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1517 if (Row.PrologueEnd) 1518 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1519 if (Row.EpilogueBegin) 1520 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1521 1522 // The end of the sequence is not normal in the middle of the input 1523 // sequence, but could happen, e.g. for assembly code. 1524 if (Row.EndSequence) { 1525 emitEndOfSequence(Address); 1526 } else { 1527 if (LastAddress == InvalidAddress) 1528 emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1529 AsmInfo->getCodePointerSize()); 1530 else 1531 MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1532 1533 LastAddress = Address; 1534 LastLine = Row.Line; 1535 } 1536 1537 Discriminator = 0; 1538 } 1539 PrevEndOfSequence = Sequence.EndAddress; 1540 } 1541 1542 // Finish with the end of the sequence. 1543 if (LastAddress != InvalidAddress) 1544 emitEndOfSequence(PrevEndOfSequence); 1545 } 1546 1547 // This function is similar to the one from MCDwarfLineTable, except it handles 1548 // end-of-sequence entries differently by utilizing line entries with 1549 // DWARF2_FLAG_END_SEQUENCE flag. 1550 static inline void emitDwarfLineTable( 1551 MCStreamer *MCOS, MCSection *Section, 1552 const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1553 unsigned FileNum = 1; 1554 unsigned LastLine = 1; 1555 unsigned Column = 0; 1556 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1557 unsigned Isa = 0; 1558 unsigned Discriminator = 0; 1559 MCSymbol *LastLabel = nullptr; 1560 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1561 1562 // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1563 for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1564 if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1565 MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1566 AsmInfo->getCodePointerSize()); 1567 FileNum = 1; 1568 LastLine = 1; 1569 Column = 0; 1570 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1571 Isa = 0; 1572 Discriminator = 0; 1573 LastLabel = nullptr; 1574 continue; 1575 } 1576 1577 int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1578 1579 if (FileNum != LineEntry.getFileNum()) { 1580 FileNum = LineEntry.getFileNum(); 1581 MCOS->emitInt8(dwarf::DW_LNS_set_file); 1582 MCOS->emitULEB128IntValue(FileNum); 1583 } 1584 if (Column != LineEntry.getColumn()) { 1585 Column = LineEntry.getColumn(); 1586 MCOS->emitInt8(dwarf::DW_LNS_set_column); 1587 MCOS->emitULEB128IntValue(Column); 1588 } 1589 if (Discriminator != LineEntry.getDiscriminator() && 1590 MCOS->getContext().getDwarfVersion() >= 2) { 1591 Discriminator = LineEntry.getDiscriminator(); 1592 unsigned Size = getULEB128Size(Discriminator); 1593 MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1594 MCOS->emitULEB128IntValue(Size + 1); 1595 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1596 MCOS->emitULEB128IntValue(Discriminator); 1597 } 1598 if (Isa != LineEntry.getIsa()) { 1599 Isa = LineEntry.getIsa(); 1600 MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1601 MCOS->emitULEB128IntValue(Isa); 1602 } 1603 if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1604 Flags = LineEntry.getFlags(); 1605 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1606 } 1607 if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1608 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1609 if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1610 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1611 if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1612 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1613 1614 MCSymbol *Label = LineEntry.getLabel(); 1615 1616 // At this point we want to emit/create the sequence to encode the delta 1617 // in line numbers and the increment of the address from the previous 1618 // Label and the current Label. 1619 MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1620 AsmInfo->getCodePointerSize()); 1621 Discriminator = 0; 1622 LastLine = LineEntry.getLine(); 1623 LastLabel = Label; 1624 } 1625 1626 assert(LastLabel == nullptr && "end of sequence expected"); 1627 } 1628 1629 void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1630 std::optional<MCDwarfLineStr> &LineStr, 1631 BinaryContext &BC) const { 1632 if (!RawData.empty()) { 1633 assert(MCLineSections.getMCLineEntries().empty() && 1634 InputSequences.empty() && 1635 "cannot combine raw data with new line entries"); 1636 MCOS->emitLabel(getLabel()); 1637 MCOS->emitBytes(RawData); 1638 return; 1639 } 1640 1641 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1642 1643 // Put out the line tables. 1644 for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1645 emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1646 1647 // Emit line tables for the original code. 1648 emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1649 1650 // This is the end of the section, so set the value of the symbol at the end 1651 // of this section (that was used in a previous expression). 1652 MCOS->emitLabel(LineEndSym); 1653 } 1654 1655 // Helper function to parse .debug_line_str, and populate one we are using. 1656 // For functions that we do not modify we output them as raw data. 1657 // Re-constructing .debug_line_str so that offsets are correct for those 1658 // debug line tables. 1659 // Bonus is that when we output a final binary we can re-use .debug_line_str 1660 // section. So we don't have to do the SHF_ALLOC trick we did with 1661 // .debug_line. 1662 static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, 1663 MCDwarfLineStr &LineStr, 1664 BinaryContext &BC) { 1665 DataExtractor StrData(LineStrSection.getContents(), 1666 BC.DwCtx->isLittleEndian(), 0); 1667 uint64_t Offset = 0; 1668 while (StrData.isValidOffset(Offset)) { 1669 const uint64_t StrOffset = Offset; 1670 Error Err = Error::success(); 1671 const char *CStr = StrData.getCStr(&Offset, &Err); 1672 if (Err) { 1673 errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; 1674 continue; 1675 } 1676 const size_t NewOffset = LineStr.addString(CStr); 1677 assert(StrOffset == NewOffset && 1678 "New offset in .debug_line_str doesn't match original offset"); 1679 } 1680 } 1681 1682 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1683 MCAssembler &Assembler = 1684 static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1685 1686 MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1687 1688 auto &LineTables = BC.getDwarfLineTables(); 1689 1690 // Bail out early so we don't switch to the debug_line section needlessly and 1691 // in doing so create an unnecessary (if empty) section. 1692 if (LineTables.empty()) 1693 return; 1694 // In a v5 non-split line table, put the strings in a separate section. 1695 std::optional<MCDwarfLineStr> LineStr; 1696 ErrorOr<BinarySection &> LineStrSection = 1697 BC.getUniqueSectionByName(".debug_line_str"); 1698 1699 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower 1700 // .debug_line, so need to check if section exists. 1701 if (LineStrSection) { 1702 LineStr.emplace(*BC.Ctx); 1703 parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC); 1704 } 1705 1706 // Switch to the section where the table will be emitted into. 1707 Streamer.switchSection(BC.MOFI->getDwarfLineSection()); 1708 1709 const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); 1710 // Handle the rest of the Compile Units. 1711 for (auto &CUIDTablePair : LineTables) { 1712 Streamer.getContext().setDwarfVersion( 1713 CUIDTablePair.second.getDwarfVersion()); 1714 CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1715 } 1716 1717 // Resetting DWARF version for rest of the flow. 1718 BC.Ctx->setDwarfVersion(DwarfVersion); 1719 1720 // Still need to write the section out for the ExecutionEngine, and temp in 1721 // memory object we are constructing. 1722 if (LineStr) 1723 LineStr->emitSection(&Streamer); 1724 } 1725 1726 } // namespace bolt 1727 } // namespace llvm 1728