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/Core/DIEBuilder.h" 16 #include "bolt/Utils/Utils.h" 17 #include "llvm/BinaryFormat/Dwarf.h" 18 #include "llvm/CodeGen/DIE.h" 19 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 20 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 21 #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" 22 #include "llvm/MC/MCAssembler.h" 23 #include "llvm/MC/MCContext.h" 24 #include "llvm/MC/MCObjectStreamer.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Support/EndianStream.h" 27 #include "llvm/Support/LEB128.h" 28 #include "llvm/Support/SHA1.h" 29 #include <algorithm> 30 #include <cassert> 31 #include <cstdint> 32 #include <functional> 33 #include <memory> 34 #include <optional> 35 #include <unordered_map> 36 #include <vector> 37 38 #define DEBUG_TYPE "bolt-debug-info" 39 40 namespace opts { 41 extern llvm::cl::opt<unsigned> Verbosity; 42 } // namespace opts 43 44 namespace llvm { 45 class MCSymbol; 46 47 namespace bolt { 48 49 static void replaceLocValbyForm(DIEBuilder &DIEBldr, DIE &Die, DIEValue DIEVal, 50 dwarf::Form Format, uint64_t NewVal) { 51 if (Format == dwarf::DW_FORM_loclistx) 52 DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format, 53 DIELocList(NewVal)); 54 else 55 DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format, 56 DIEInteger(NewVal)); 57 } 58 59 std::optional<AttrInfo> 60 findAttributeInfo(const DWARFDie DIE, 61 const DWARFAbbreviationDeclaration *AbbrevDecl, 62 uint32_t Index) { 63 const DWARFUnit &U = *DIE.getDwarfUnit(); 64 uint64_t Offset = 65 AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U); 66 std::optional<DWARFFormValue> Value = 67 AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U); 68 if (!Value) 69 return std::nullopt; 70 // AttributeSpec 71 const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal = 72 AbbrevDecl->attributes().begin() + Index; 73 uint32_t ValSize = 0; 74 std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U); 75 if (ValSizeOpt) { 76 ValSize = static_cast<uint32_t>(*ValSizeOpt); 77 } else { 78 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 79 uint64_t NewOffset = Offset; 80 DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset, 81 U.getFormParams()); 82 // This includes entire size of the entry, which might not be just the 83 // encoding part. For example for DW_AT_loc it will include expression 84 // location. 85 ValSize = NewOffset - Offset; 86 } 87 return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize}; 88 } 89 90 std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE, 91 dwarf::Attribute Attr) { 92 if (!DIE.isValid()) 93 return std::nullopt; 94 const DWARFAbbreviationDeclaration *AbbrevDecl = 95 DIE.getAbbreviationDeclarationPtr(); 96 if (!AbbrevDecl) 97 return std::nullopt; 98 std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr); 99 if (!Index) 100 return std::nullopt; 101 return findAttributeInfo(DIE, AbbrevDecl, *Index); 102 } 103 104 const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 105 106 LLVM_ATTRIBUTE_UNUSED 107 static void printLE64(const std::string &S) { 108 for (uint32_t I = 0, Size = S.size(); I < Size; ++I) { 109 errs() << Twine::utohexstr(S[I]); 110 errs() << Twine::utohexstr((int8_t)S[I]); 111 } 112 errs() << "\n"; 113 } 114 115 // Writes address ranges to Writer as pairs of 64-bit (address, size). 116 // If RelativeRange is true, assumes the address range to be written must be of 117 // the form (begin address, range size), otherwise (begin address, end address). 118 // Terminates the list by writing a pair of two zeroes. 119 // Returns the number of written bytes. 120 static uint64_t 121 writeAddressRanges(raw_svector_ostream &Stream, 122 const DebugAddressRangesVector &AddressRanges, 123 const bool WriteRelativeRanges = false) { 124 for (const DebugAddressRange &Range : AddressRanges) { 125 support::endian::write(Stream, Range.LowPC, llvm::endianness::little); 126 support::endian::write( 127 Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 128 llvm::endianness::little); 129 } 130 // Finish with 0 entries. 131 support::endian::write(Stream, 0ULL, llvm::endianness::little); 132 support::endian::write(Stream, 0ULL, llvm::endianness::little); 133 return AddressRanges.size() * 16 + 16; 134 } 135 136 DebugRangesSectionWriter::DebugRangesSectionWriter() { 137 RangesBuffer = std::make_unique<DebugBufferVector>(); 138 RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 139 140 Kind = RangesWriterKind::DebugRangesWriter; 141 } 142 143 void DebugRangesSectionWriter::initSection() { 144 // Adds an empty range to the buffer. 145 writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 146 } 147 148 uint64_t DebugRangesSectionWriter::addRanges( 149 DebugAddressRangesVector &&Ranges, 150 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 151 if (Ranges.empty()) 152 return getEmptyRangesOffset(); 153 154 const auto RI = CachedRanges.find(Ranges); 155 if (RI != CachedRanges.end()) 156 return RI->second; 157 158 const uint64_t EntryOffset = addRanges(Ranges); 159 CachedRanges.emplace(std::move(Ranges), EntryOffset); 160 161 return EntryOffset; 162 } 163 164 uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) { 165 if (Ranges.empty()) 166 return getEmptyRangesOffset(); 167 168 // Reading the SectionOffset and updating it should be atomic to guarantee 169 // unique and correct offsets in patches. 170 std::lock_guard<std::mutex> Lock(WriterMutex); 171 const uint32_t EntryOffset = RangesBuffer->size(); 172 writeAddressRanges(*RangesStream.get(), Ranges); 173 174 return EntryOffset; 175 } 176 177 uint64_t DebugRangesSectionWriter::getSectionOffset() { 178 std::lock_guard<std::mutex> Lock(WriterMutex); 179 return RangesBuffer->size(); 180 } 181 182 void DebugRangesSectionWriter::appendToRangeBuffer( 183 const DebugBufferVector &CUBuffer) { 184 *RangesStream << CUBuffer; 185 } 186 187 uint64_t DebugRangeListsSectionWriter::addRanges( 188 DebugAddressRangesVector &&Ranges, 189 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 190 return addRanges(Ranges); 191 } 192 193 struct LocListsRangelistsHeader { 194 UnitLengthType UnitLength; // Size of loclist entries section, not including 195 // size of header. 196 VersionType Version; 197 AddressSizeType AddressSize; 198 SegmentSelectorType SegmentSelector; 199 OffsetEntryCountType OffsetEntryCount; 200 }; 201 202 static std::unique_ptr<DebugBufferVector> 203 getDWARF5Header(const LocListsRangelistsHeader &Header) { 204 std::unique_ptr<DebugBufferVector> HeaderBuffer = 205 std::make_unique<DebugBufferVector>(); 206 std::unique_ptr<raw_svector_ostream> HeaderStream = 207 std::make_unique<raw_svector_ostream>(*HeaderBuffer); 208 209 // 7.29 length of the set of entries for this compilation unit, not including 210 // the length field itself 211 const uint32_t HeaderSize = 212 getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType); 213 214 support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize, 215 llvm::endianness::little); 216 support::endian::write(*HeaderStream, Header.Version, 217 llvm::endianness::little); 218 support::endian::write(*HeaderStream, Header.AddressSize, 219 llvm::endianness::little); 220 support::endian::write(*HeaderStream, Header.SegmentSelector, 221 llvm::endianness::little); 222 support::endian::write(*HeaderStream, Header.OffsetEntryCount, 223 llvm::endianness::little); 224 return HeaderBuffer; 225 } 226 227 struct OffsetEntry { 228 uint32_t Index; 229 uint32_t StartOffset; 230 uint32_t EndOffset; 231 }; 232 template <typename DebugVector, typename ListEntry, typename DebugAddressEntry> 233 static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries, 234 DebugAddrWriter &AddrWriter, DWARFUnit &CU, 235 uint32_t &Index, const ListEntry BaseAddressx, 236 const ListEntry OffsetPair, 237 const std::function<void(uint32_t)> &Func) { 238 if (Entries.size() < 2) 239 return false; 240 uint64_t Base = Entries[Index].LowPC; 241 std::vector<OffsetEntry> Offsets; 242 uint8_t TempBuffer[64]; 243 while (Index < Entries.size()) { 244 const DebugAddressEntry &Entry = Entries[Index]; 245 if (Entry.LowPC == 0) 246 break; 247 // In case rnglists or loclists are not sorted. 248 if (Base > Entry.LowPC) 249 break; 250 uint32_t StartOffset = Entry.LowPC - Base; 251 uint32_t EndOffset = Entry.HighPC - Base; 252 if (encodeULEB128(EndOffset, TempBuffer) > 2) 253 break; 254 Offsets.push_back({Index, StartOffset, EndOffset}); 255 ++Index; 256 } 257 258 if (Offsets.size() < 2) { 259 Index -= Offsets.size(); 260 return false; 261 } 262 263 support::endian::write(OS, static_cast<uint8_t>(BaseAddressx), 264 llvm::endianness::little); 265 uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU); 266 encodeULEB128(BaseIndex, OS); 267 for (auto &OffsetEntry : Offsets) { 268 support::endian::write(OS, static_cast<uint8_t>(OffsetPair), 269 llvm::endianness::little); 270 encodeULEB128(OffsetEntry.StartOffset, OS); 271 encodeULEB128(OffsetEntry.EndOffset, OS); 272 Func(OffsetEntry.Index); 273 } 274 return true; 275 } 276 277 uint64_t 278 DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) { 279 std::lock_guard<std::mutex> Lock(WriterMutex); 280 281 RangeEntries.push_back(CurrentOffset); 282 std::sort( 283 Ranges.begin(), Ranges.end(), 284 [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool { 285 return R1.LowPC < R2.LowPC; 286 }); 287 for (unsigned I = 0; I < Ranges.size();) { 288 if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries, 289 DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU, 290 I, dwarf::DW_RLE_base_addressx, 291 dwarf::DW_RLE_offset_pair, 292 [](uint32_t Index) -> void {})) 293 continue; 294 295 const DebugAddressRange &Range = Ranges[I]; 296 support::endian::write(*CUBodyStream, 297 static_cast<uint8_t>(dwarf::DW_RLE_startx_length), 298 llvm::endianness::little); 299 uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU); 300 encodeULEB128(Index, *CUBodyStream); 301 encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream); 302 ++I; 303 } 304 305 support::endian::write(*CUBodyStream, 306 static_cast<uint8_t>(dwarf::DW_RLE_end_of_list), 307 llvm::endianness::little); 308 CurrentOffset = CUBodyBuffer->size(); 309 return RangeEntries.size() - 1; 310 } 311 312 void DebugRangeListsSectionWriter::finalizeSection() { 313 std::unique_ptr<DebugBufferVector> CUArrayBuffer = 314 std::make_unique<DebugBufferVector>(); 315 std::unique_ptr<raw_svector_ostream> CUArrayStream = 316 std::make_unique<raw_svector_ostream>(*CUArrayBuffer); 317 constexpr uint32_t SizeOfArrayEntry = 4; 318 const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry; 319 for (uint32_t Offset : RangeEntries) 320 support::endian::write(*CUArrayStream, Offset + SizeOfArraySection, 321 llvm::endianness::little); 322 323 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 324 {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()), 325 5, 8, 0, static_cast<uint32_t>(RangeEntries.size())}); 326 *RangesStream << *Header; 327 *RangesStream << *CUArrayBuffer; 328 *RangesStream << *CUBodyBuffer; 329 } 330 331 void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) { 332 CUBodyBuffer = std::make_unique<DebugBufferVector>(); 333 CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer); 334 RangeEntries.clear(); 335 CurrentOffset = 0; 336 CU = &Unit; 337 } 338 339 void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 340 DebugAddressRangesVector &&Ranges) { 341 std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 342 CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 343 } 344 345 void DebugARangesSectionWriter::writeARangesSection( 346 raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const { 347 // For reference on the format of the .debug_aranges section, see the DWARF4 348 // specification, section 6.1.4 Lookup by Address 349 // http://www.dwarfstd.org/doc/DWARF4.pdf 350 for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 351 const uint64_t Offset = CUOffsetAddressRangesPair.first; 352 const DebugAddressRangesVector &AddressRanges = 353 CUOffsetAddressRangesPair.second; 354 355 // Emit header. 356 357 // Size of this set: 8 (size of the header) + 4 (padding after header) 358 // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 359 // pair of uint64_t's for the terminating, zero-length range. 360 // Does not include size field itself. 361 uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 362 363 // Header field #1: set size. 364 support::endian::write(RangesStream, Size, llvm::endianness::little); 365 366 // Header field #2: version number, 2 as per the specification. 367 support::endian::write(RangesStream, static_cast<uint16_t>(2), 368 llvm::endianness::little); 369 370 assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map"); 371 // Header field #3: debug info offset of the correspondent compile unit. 372 support::endian::write( 373 RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset), 374 llvm::endianness::little); 375 376 // Header field #4: address size. 377 // 8 since we only write ELF64 binaries for now. 378 RangesStream << char(8); 379 380 // Header field #5: segment size of target architecture. 381 RangesStream << char(0); 382 383 // Padding before address table - 4 bytes in the 64-bit-pointer case. 384 support::endian::write(RangesStream, static_cast<uint32_t>(0), 385 llvm::endianness::little); 386 387 writeAddressRanges(RangesStream, AddressRanges, true); 388 } 389 } 390 391 DebugAddrWriter::DebugAddrWriter(BinaryContext *BC, 392 const uint8_t AddressByteSize) 393 : BC(BC), AddressByteSize(AddressByteSize) { 394 Buffer = std::make_unique<AddressSectionBuffer>(); 395 AddressStream = std::make_unique<raw_svector_ostream>(*Buffer); 396 } 397 398 void DebugAddrWriter::AddressForDWOCU::dump() { 399 std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 400 indexToAdddessEnd()); 401 // Sorting address in increasing order of indices. 402 llvm::sort(SortedMap, llvm::less_first()); 403 for (auto &Pair : SortedMap) 404 dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 405 } 406 uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { 407 std::lock_guard<std::mutex> Lock(WriterMutex); 408 auto Entry = Map.find(Address); 409 if (Entry == Map.end()) { 410 auto Index = Map.getNextIndex(); 411 Entry = Map.insert(Address, Index).first; 412 } 413 return Entry->second; 414 } 415 416 static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter, 417 DWARFUnit &CU, const uint64_t Offset) { 418 DIE *Die = DIEBlder.getUnitDIEbyUnit(CU); 419 DIEValue GnuAddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_GNU_addr_base); 420 DIEValue AddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_addr_base); 421 dwarf::Form BaseAttrForm; 422 dwarf::Attribute BaseAttr; 423 // For cases where Skeleton CU does not have DW_AT_GNU_addr_base 424 if (!GnuAddrBaseAttrInfo && CU.getVersion() < 5) 425 return; 426 427 if (GnuAddrBaseAttrInfo) { 428 BaseAttrForm = GnuAddrBaseAttrInfo.getForm(); 429 BaseAttr = GnuAddrBaseAttrInfo.getAttribute(); 430 } 431 432 if (AddrBaseAttrInfo) { 433 BaseAttrForm = AddrBaseAttrInfo.getForm(); 434 BaseAttr = AddrBaseAttrInfo.getAttribute(); 435 } 436 437 if (GnuAddrBaseAttrInfo || AddrBaseAttrInfo) { 438 DIEBlder.replaceValue(Die, BaseAttr, BaseAttrForm, DIEInteger(Offset)); 439 } else if (CU.getVersion() >= 5) { 440 // A case where we were not using .debug_addr section, but after update 441 // now using it. 442 DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset, 443 DIEInteger(Offset)); 444 } 445 } 446 447 void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU, 448 const uint64_t Offset) { 449 updateAddressBase(DIEBlder, *this, CU, Offset); 450 } 451 452 std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) { 453 if (Map.begin() == Map.end()) 454 return std::nullopt; 455 std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(), 456 Map.indexToAdddessEnd()); 457 // Sorting address in increasing order of indices. 458 llvm::sort(SortedMap, llvm::less_first()); 459 460 uint32_t Counter = 0; 461 auto WriteAddress = [&](uint64_t Address) -> void { 462 ++Counter; 463 switch (AddressByteSize) { 464 default: 465 assert(false && "Address Size is invalid."); 466 break; 467 case 4: 468 support::endian::write(*AddressStream, static_cast<uint32_t>(Address), 469 llvm::endianness::little); 470 break; 471 case 8: 472 support::endian::write(*AddressStream, Address, llvm::endianness::little); 473 break; 474 } 475 }; 476 477 for (const IndexAddressPair &Val : SortedMap) { 478 while (Val.first > Counter) 479 WriteAddress(0); 480 WriteAddress(Val.second); 481 } 482 return std::nullopt; 483 } 484 485 void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU, 486 const uint64_t Offset) { 487 /// Header for DWARF5 has size 8, so we add it to the offset. 488 updateAddressBase(DIEBlder, *this, CU, Offset + HeaderSize); 489 } 490 491 DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets; 492 493 std::optional<uint64_t> 494 DebugAddrWriterDwarf5::finalize(const size_t BufferSize) { 495 // Need to layout all sections within .debug_addr 496 // Within each section sort Address by index. 497 const endianness Endian = BC->DwCtx->isLittleEndian() 498 ? llvm::endianness::little 499 : llvm::endianness::big; 500 const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection(); 501 DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, 502 Endian == llvm::endianness::little, 0); 503 DWARFDebugAddrTable AddrTable; 504 DIDumpOptions DumpOpts; 505 // A case where CU has entry in .debug_addr, but we don't modify addresses 506 // for it. 507 if (Map.begin() == Map.end()) { 508 if (!AddrOffsetSectionBase) 509 return std::nullopt; 510 // Address base offset is to the first entry. 511 // The size of header is 8 bytes. 512 uint64_t Offset = *AddrOffsetSectionBase - HeaderSize; 513 auto Iter = UnmodifiedAddressOffsets.find(Offset); 514 if (Iter != UnmodifiedAddressOffsets.end()) 515 return Iter->second; 516 UnmodifiedAddressOffsets[Offset] = BufferSize; 517 if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize, 518 DumpOpts.WarningHandler)) { 519 DumpOpts.RecoverableErrorHandler(std::move(Err)); 520 return std::nullopt; 521 } 522 uint32_t Index = 0; 523 for (uint64_t Addr : AddrTable.getAddressEntries()) 524 Map.insert(Addr, Index++); 525 } 526 527 std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(), 528 Map.indexToAdddessEnd()); 529 // Sorting address in increasing order of indices. 530 llvm::sort(SortedMap, llvm::less_first()); 531 // Writing out Header 532 const uint32_t Length = SortedMap.size() * AddressByteSize + 4; 533 support::endian::write(*AddressStream, Length, Endian); 534 support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian); 535 support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize), 536 Endian); 537 support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian); 538 539 uint32_t Counter = 0; 540 auto writeAddress = [&](uint64_t Address) -> void { 541 ++Counter; 542 switch (AddressByteSize) { 543 default: 544 llvm_unreachable("Address Size is invalid."); 545 break; 546 case 4: 547 support::endian::write(*AddressStream, static_cast<uint32_t>(Address), 548 Endian); 549 break; 550 case 8: 551 support::endian::write(*AddressStream, Address, Endian); 552 break; 553 } 554 }; 555 556 for (const IndexAddressPair &Val : SortedMap) { 557 while (Val.first > Counter) 558 writeAddress(0); 559 writeAddress(Val.second); 560 } 561 return std::nullopt; 562 } 563 564 void DebugLocWriter::init() { 565 LocBuffer = std::make_unique<DebugBufferVector>(); 566 LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 567 // Writing out empty location list to which all references to empty location 568 // lists will point. 569 if (!LocSectionOffset && DwarfVersion < 5) { 570 const char Zeroes[16] = {0}; 571 *LocStream << StringRef(Zeroes, 16); 572 LocSectionOffset += 16; 573 } 574 } 575 576 uint32_t DebugLocWriter::LocSectionOffset = 0; 577 void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo, 578 DebugLocationsVector &LocList) { 579 if (LocList.empty()) { 580 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), 581 DebugLocWriter::EmptyListOffset); 582 return; 583 } 584 // Since there is a separate DebugLocWriter for each thread, 585 // we don't need a lock to read the SectionOffset and update it. 586 const uint32_t EntryOffset = LocSectionOffset; 587 588 for (const DebugLocationEntry &Entry : LocList) { 589 support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 590 llvm::endianness::little); 591 support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 592 llvm::endianness::little); 593 support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 594 llvm::endianness::little); 595 *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 596 Entry.Expr.size()); 597 LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 598 } 599 LocStream->write_zeros(16); 600 LocSectionOffset += 16; 601 LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen 602 // use 603 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset); 604 } 605 606 std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 607 return std::move(LocBuffer); 608 } 609 610 // DWARF 4: 2.6.2 611 void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {} 612 613 static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { 614 support::endian::write(Stream, static_cast<uint32_t>(4), 615 llvm::endianness::little); 616 support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end), 617 llvm::endianness::little); 618 619 const char Zeroes[16] = {0}; 620 Stream << StringRef(Zeroes, 16); 621 encodeULEB128(0, Stream); 622 support::endian::write(Stream, 623 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 624 llvm::endianness::little); 625 } 626 627 static void writeLegacyLocList(DIEValue &AttrInfo, 628 DebugLocationsVector &LocList, 629 DIEBuilder &DIEBldr, DIE &Die, 630 DebugAddrWriter &AddrWriter, 631 DebugBufferVector &LocBuffer, DWARFUnit &CU, 632 raw_svector_ostream &LocStream) { 633 if (LocList.empty()) { 634 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), 635 DebugLocWriter::EmptyListOffset); 636 return; 637 } 638 639 const uint32_t EntryOffset = LocBuffer.size(); 640 for (const DebugLocationEntry &Entry : LocList) { 641 support::endian::write(LocStream, 642 static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 643 llvm::endianness::little); 644 const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 645 encodeULEB128(Index, LocStream); 646 647 support::endian::write(LocStream, 648 static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 649 llvm::endianness::little); 650 support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()), 651 llvm::endianness::little); 652 LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 653 Entry.Expr.size()); 654 } 655 support::endian::write(LocStream, 656 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 657 llvm::endianness::little); 658 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset); 659 } 660 661 static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo, 662 DebugLocationsVector &LocList, DIE &Die, 663 DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter, 664 DebugBufferVector &LocBodyBuffer, 665 std::vector<uint32_t> &RelativeLocListOffsets, 666 DWARFUnit &CU, 667 raw_svector_ostream &LocBodyStream) { 668 669 replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx, 670 NumberOfEntries); 671 672 RelativeLocListOffsets.push_back(LocBodyBuffer.size()); 673 ++NumberOfEntries; 674 if (LocList.empty()) { 675 writeEmptyListDwarf5(LocBodyStream); 676 return; 677 } 678 679 std::vector<uint64_t> OffsetsArray; 680 auto writeExpression = [&](uint32_t Index) -> void { 681 const DebugLocationEntry &Entry = LocList[Index]; 682 encodeULEB128(Entry.Expr.size(), LocBodyStream); 683 LocBodyStream << StringRef( 684 reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size()); 685 }; 686 for (unsigned I = 0; I < LocList.size();) { 687 if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries, 688 DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU, 689 I, dwarf::DW_LLE_base_addressx, 690 dwarf::DW_LLE_offset_pair, 691 writeExpression)) 692 continue; 693 694 const DebugLocationEntry &Entry = LocList[I]; 695 support::endian::write(LocBodyStream, 696 static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 697 llvm::endianness::little); 698 const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 699 encodeULEB128(Index, LocBodyStream); 700 encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream); 701 writeExpression(I); 702 ++I; 703 } 704 705 support::endian::write(LocBodyStream, 706 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 707 llvm::endianness::little); 708 } 709 710 void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die, 711 DIEValue &AttrInfo, 712 DebugLocationsVector &LocList) { 713 if (DwarfVersion < 5) 714 writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer, 715 CU, *LocStream); 716 else 717 writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr, 718 AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU, 719 *LocBodyStream); 720 } 721 722 uint32_t DebugLoclistWriter::LoclistBaseOffset = 0; 723 void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) { 724 if (LocBodyBuffer->empty()) { 725 DIEValue LocListBaseAttrInfo = 726 Die.findAttribute(dwarf::DW_AT_loclists_base); 727 // Pointing to first one, because it doesn't matter. There are no uses of it 728 // in this CU. 729 if (!isSplitDwarf() && LocListBaseAttrInfo.getType()) 730 DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base, 731 LocListBaseAttrInfo.getForm(), 732 DIEInteger(getDWARF5RngListLocListHeaderSize())); 733 return; 734 } 735 736 std::unique_ptr<DebugBufferVector> LocArrayBuffer = 737 std::make_unique<DebugBufferVector>(); 738 std::unique_ptr<raw_svector_ostream> LocArrayStream = 739 std::make_unique<raw_svector_ostream>(*LocArrayBuffer); 740 741 const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t); 742 // Write out IndexArray 743 for (uint32_t RelativeOffset : RelativeLocListOffsets) 744 support::endian::write( 745 *LocArrayStream, 746 static_cast<uint32_t>(SizeOfArraySection + RelativeOffset), 747 llvm::endianness::little); 748 749 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 750 {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()), 751 5, 8, 0, NumberOfEntries}); 752 *LocStream << *Header; 753 *LocStream << *LocArrayBuffer; 754 *LocStream << *LocBodyBuffer; 755 756 if (!isSplitDwarf()) { 757 DIEValue LocListBaseAttrInfo = 758 Die.findAttribute(dwarf::DW_AT_loclists_base); 759 if (LocListBaseAttrInfo.getType()) { 760 DIEBldr.replaceValue( 761 &Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(), 762 DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize())); 763 } else { 764 DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base, 765 dwarf::DW_FORM_sec_offset, 766 DIEInteger(LoclistBaseOffset + Header->size())); 767 } 768 LoclistBaseOffset += LocBuffer->size(); 769 } 770 clearList(RelativeLocListOffsets); 771 clearList(*LocArrayBuffer); 772 clearList(*LocBodyBuffer); 773 } 774 775 void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) { 776 if (DwarfVersion >= 5) 777 finalizeDWARF5(DIEBldr, Die); 778 } 779 780 static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 781 std::string LE64(ByteSize, 0); 782 for (size_t I = 0; I < ByteSize; ++I) { 783 LE64[I] = NewValue & 0xff; 784 NewValue >>= 8; 785 } 786 return LE64; 787 } 788 789 void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 790 std::string &&NewValue, 791 uint32_t OldValueSize) { 792 Patches.emplace_back(Offset, std::move(NewValue)); 793 } 794 795 void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 796 auto Str = std::string(1, Value); 797 Patches.emplace_back(Offset, std::move(Str)); 798 } 799 800 void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 801 size_t ByteSize) { 802 Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 803 } 804 805 void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 806 uint32_t OldValueSize) { 807 std::string Buff; 808 raw_string_ostream OS(Buff); 809 encodeULEB128(Value, OS, OldValueSize); 810 811 Patches.emplace_back(Offset, std::move(Buff)); 812 } 813 814 void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 815 addLEPatch(Offset, NewValue, 8); 816 } 817 818 void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 819 uint32_t OldValueSize) { 820 addLEPatch(Offset, NewValue, 4); 821 } 822 823 std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 824 std::string BinaryContentsStr = std::string(BinaryContents); 825 for (const auto &Patch : Patches) { 826 uint32_t Offset = Patch.first; 827 const std::string &ByteSequence = Patch.second; 828 assert(Offset + ByteSequence.size() <= BinaryContents.size() && 829 "Applied patch runs over binary size."); 830 for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 831 BinaryContentsStr[Offset + I] = ByteSequence[I]; 832 } 833 } 834 return BinaryContentsStr; 835 } 836 837 void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) { 838 if (Unit.getVersion() < 5) 839 return; 840 const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection(); 841 const std::optional<StrOffsetsContributionDescriptor> &Contr = 842 Unit.getStringOffsetsTableContribution(); 843 if (!Contr) 844 return; 845 const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize(); 846 assert(DwarfOffsetByteSize == 4 && 847 "Dwarf String Offsets Byte Size is not supported."); 848 StrOffsets.reserve(Contr->Size); 849 for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize) 850 StrOffsets.push_back(support::endian::read32le( 851 StrOffsetsSection.Data.data() + Contr->Base + Offset)); 852 } 853 854 void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address, 855 const DWARFUnit &Unit) { 856 assert(DebugStrOffsetFinalized.count(Unit.getOffset()) == 0 && 857 "Cannot update address map since debug_str_offsets was already " 858 "finalized for this CU."); 859 IndexToAddressMap[Index] = Address; 860 StrOffsetSectionWasModified = true; 861 } 862 863 void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit, 864 DIEBuilder &DIEBldr) { 865 std::optional<AttrInfo> AttrVal = 866 findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base); 867 if (!AttrVal && !Unit.isDWOUnit()) 868 return; 869 std::optional<uint64_t> Val = std::nullopt; 870 if (AttrVal) { 871 Val = AttrVal->V.getAsSectionOffset(); 872 } else { 873 if (!Unit.isDWOUnit()) 874 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: " 875 "DW_AT_str_offsets_base Value not present\n"; 876 Val = 0; 877 } 878 DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit); 879 DIEValue StrListBaseAttrInfo = 880 Die.findAttribute(dwarf::DW_AT_str_offsets_base); 881 auto RetVal = ProcessedBaseOffsets.find(*Val); 882 // Handling re-use of str-offsets section. 883 if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) { 884 initialize(Unit); 885 // Update String Offsets that were modified. 886 for (const auto &Entry : IndexToAddressMap) 887 StrOffsets[Entry.first] = Entry.second; 888 // Writing out the header for each section. 889 support::endian::write(*StrOffsetsStream, 890 static_cast<uint32_t>(StrOffsets.size() * 4 + 4), 891 llvm::endianness::little); 892 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5), 893 llvm::endianness::little); 894 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0), 895 llvm::endianness::little); 896 897 uint64_t BaseOffset = StrOffsetsBuffer->size(); 898 ProcessedBaseOffsets[*Val] = BaseOffset; 899 if (StrListBaseAttrInfo.getType()) 900 DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base, 901 StrListBaseAttrInfo.getForm(), 902 DIEInteger(BaseOffset)); 903 for (const uint32_t Offset : StrOffsets) 904 support::endian::write(*StrOffsetsStream, Offset, 905 llvm::endianness::little); 906 } else { 907 DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base, 908 StrListBaseAttrInfo.getForm(), 909 DIEInteger(RetVal->second)); 910 } 911 912 StrOffsetSectionWasModified = false; 913 assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second && 914 "debug_str_offsets was already finalized for this CU."); 915 clear(); 916 } 917 918 void DebugStrWriter::create() { 919 StrBuffer = std::make_unique<DebugStrBufferVector>(); 920 StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 921 } 922 923 void DebugStrWriter::initialize() { 924 StringRef StrSection; 925 if (IsDWO) 926 StrSection = DwCtx.getDWARFObj().getStrDWOSection(); 927 else 928 StrSection = DwCtx.getDWARFObj().getStrSection(); 929 (*StrStream) << StrSection; 930 } 931 932 uint32_t DebugStrWriter::addString(StringRef Str) { 933 std::lock_guard<std::mutex> Lock(WriterMutex); 934 if (StrBuffer->empty()) 935 initialize(); 936 auto Offset = StrBuffer->size(); 937 (*StrStream) << Str; 938 StrStream->write_zeros(1); 939 return Offset; 940 } 941 942 static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 943 MCDwarfLineTableParams Params, 944 int64_t LineDelta, uint64_t Address, 945 int PointerSize) { 946 // emit the sequence to set the address 947 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 948 OS.emitULEB128IntValue(PointerSize + 1); 949 OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 950 OS.emitIntValue(Address, PointerSize); 951 952 // emit the sequence for the LineDelta (from 1) and a zero address delta. 953 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 954 } 955 956 static inline void emitBinaryDwarfLineTable( 957 MCStreamer *MCOS, MCDwarfLineTableParams Params, 958 const DWARFDebugLine::LineTable *Table, 959 const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 960 if (InputSequences.empty()) 961 return; 962 963 constexpr uint64_t InvalidAddress = UINT64_MAX; 964 unsigned FileNum = 1; 965 unsigned LastLine = 1; 966 unsigned Column = 0; 967 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 968 unsigned Isa = 0; 969 unsigned Discriminator = 0; 970 uint64_t LastAddress = InvalidAddress; 971 uint64_t PrevEndOfSequence = InvalidAddress; 972 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 973 974 auto emitEndOfSequence = [&](uint64_t Address) { 975 MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 976 FileNum = 1; 977 LastLine = 1; 978 Column = 0; 979 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 980 Isa = 0; 981 Discriminator = 0; 982 LastAddress = InvalidAddress; 983 }; 984 985 for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 986 const uint64_t SequenceStart = 987 Table->Rows[Sequence.FirstIndex].Address.Address; 988 989 // Check if we need to mark the end of the sequence. 990 if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 991 PrevEndOfSequence != SequenceStart) { 992 emitEndOfSequence(PrevEndOfSequence); 993 } 994 995 for (uint32_t RowIndex = Sequence.FirstIndex; 996 RowIndex <= Sequence.LastIndex; ++RowIndex) { 997 const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 998 int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 999 const uint64_t Address = Row.Address.Address; 1000 1001 if (FileNum != Row.File) { 1002 FileNum = Row.File; 1003 MCOS->emitInt8(dwarf::DW_LNS_set_file); 1004 MCOS->emitULEB128IntValue(FileNum); 1005 } 1006 if (Column != Row.Column) { 1007 Column = Row.Column; 1008 MCOS->emitInt8(dwarf::DW_LNS_set_column); 1009 MCOS->emitULEB128IntValue(Column); 1010 } 1011 if (Discriminator != Row.Discriminator && 1012 MCOS->getContext().getDwarfVersion() >= 4) { 1013 Discriminator = Row.Discriminator; 1014 unsigned Size = getULEB128Size(Discriminator); 1015 MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1016 MCOS->emitULEB128IntValue(Size + 1); 1017 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1018 MCOS->emitULEB128IntValue(Discriminator); 1019 } 1020 if (Isa != Row.Isa) { 1021 Isa = Row.Isa; 1022 MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1023 MCOS->emitULEB128IntValue(Isa); 1024 } 1025 if (Row.IsStmt != Flags) { 1026 Flags = Row.IsStmt; 1027 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1028 } 1029 if (Row.BasicBlock) 1030 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1031 if (Row.PrologueEnd) 1032 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1033 if (Row.EpilogueBegin) 1034 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1035 1036 // The end of the sequence is not normal in the middle of the input 1037 // sequence, but could happen, e.g. for assembly code. 1038 if (Row.EndSequence) { 1039 emitEndOfSequence(Address); 1040 } else { 1041 if (LastAddress == InvalidAddress) 1042 emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1043 AsmInfo->getCodePointerSize()); 1044 else 1045 MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1046 1047 LastAddress = Address; 1048 LastLine = Row.Line; 1049 } 1050 1051 Discriminator = 0; 1052 } 1053 PrevEndOfSequence = Sequence.EndAddress; 1054 } 1055 1056 // Finish with the end of the sequence. 1057 if (LastAddress != InvalidAddress) 1058 emitEndOfSequence(PrevEndOfSequence); 1059 } 1060 1061 // This function is similar to the one from MCDwarfLineTable, except it handles 1062 // end-of-sequence entries differently by utilizing line entries with 1063 // DWARF2_FLAG_END_SEQUENCE flag. 1064 static inline void emitDwarfLineTable( 1065 MCStreamer *MCOS, MCSection *Section, 1066 const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1067 unsigned FileNum = 1; 1068 unsigned LastLine = 1; 1069 unsigned Column = 0; 1070 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1071 unsigned Isa = 0; 1072 unsigned Discriminator = 0; 1073 MCSymbol *LastLabel = nullptr; 1074 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1075 1076 // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1077 for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1078 if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1079 MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1080 AsmInfo->getCodePointerSize()); 1081 FileNum = 1; 1082 LastLine = 1; 1083 Column = 0; 1084 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1085 Isa = 0; 1086 Discriminator = 0; 1087 LastLabel = nullptr; 1088 continue; 1089 } 1090 1091 int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1092 1093 if (FileNum != LineEntry.getFileNum()) { 1094 FileNum = LineEntry.getFileNum(); 1095 MCOS->emitInt8(dwarf::DW_LNS_set_file); 1096 MCOS->emitULEB128IntValue(FileNum); 1097 } 1098 if (Column != LineEntry.getColumn()) { 1099 Column = LineEntry.getColumn(); 1100 MCOS->emitInt8(dwarf::DW_LNS_set_column); 1101 MCOS->emitULEB128IntValue(Column); 1102 } 1103 if (Discriminator != LineEntry.getDiscriminator() && 1104 MCOS->getContext().getDwarfVersion() >= 2) { 1105 Discriminator = LineEntry.getDiscriminator(); 1106 unsigned Size = getULEB128Size(Discriminator); 1107 MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1108 MCOS->emitULEB128IntValue(Size + 1); 1109 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1110 MCOS->emitULEB128IntValue(Discriminator); 1111 } 1112 if (Isa != LineEntry.getIsa()) { 1113 Isa = LineEntry.getIsa(); 1114 MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1115 MCOS->emitULEB128IntValue(Isa); 1116 } 1117 if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1118 Flags = LineEntry.getFlags(); 1119 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1120 } 1121 if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1122 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1123 if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1124 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1125 if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1126 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1127 1128 MCSymbol *Label = LineEntry.getLabel(); 1129 1130 // At this point we want to emit/create the sequence to encode the delta 1131 // in line numbers and the increment of the address from the previous 1132 // Label and the current Label. 1133 MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1134 AsmInfo->getCodePointerSize()); 1135 Discriminator = 0; 1136 LastLine = LineEntry.getLine(); 1137 LastLabel = Label; 1138 } 1139 1140 assert(LastLabel == nullptr && "end of sequence expected"); 1141 } 1142 1143 void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1144 std::optional<MCDwarfLineStr> &LineStr, 1145 BinaryContext &BC) const { 1146 if (!RawData.empty()) { 1147 assert(MCLineSections.getMCLineEntries().empty() && 1148 InputSequences.empty() && 1149 "cannot combine raw data with new line entries"); 1150 MCOS->emitLabel(getLabel()); 1151 MCOS->emitBytes(RawData); 1152 return; 1153 } 1154 1155 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1156 1157 // Put out the line tables. 1158 for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1159 emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1160 1161 // Emit line tables for the original code. 1162 emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1163 1164 // This is the end of the section, so set the value of the symbol at the end 1165 // of this section (that was used in a previous expression). 1166 MCOS->emitLabel(LineEndSym); 1167 } 1168 1169 // Helper function to parse .debug_line_str, and populate one we are using. 1170 // For functions that we do not modify we output them as raw data. 1171 // Re-constructing .debug_line_str so that offsets are correct for those 1172 // debug line tables. 1173 // Bonus is that when we output a final binary we can re-use .debug_line_str 1174 // section. So we don't have to do the SHF_ALLOC trick we did with 1175 // .debug_line. 1176 static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, 1177 MCDwarfLineStr &LineStr, 1178 BinaryContext &BC) { 1179 DataExtractor StrData(LineStrSection.getContents(), 1180 BC.DwCtx->isLittleEndian(), 0); 1181 uint64_t Offset = 0; 1182 while (StrData.isValidOffset(Offset)) { 1183 const uint64_t StrOffset = Offset; 1184 Error Err = Error::success(); 1185 const char *CStr = StrData.getCStr(&Offset, &Err); 1186 if (Err) { 1187 BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; 1188 continue; 1189 } 1190 const size_t NewOffset = LineStr.addString(CStr); 1191 assert(StrOffset == NewOffset && 1192 "New offset in .debug_line_str doesn't match original offset"); 1193 (void)StrOffset; 1194 (void)NewOffset; 1195 } 1196 } 1197 1198 void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1199 MCAssembler &Assembler = 1200 static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1201 1202 MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1203 1204 auto &LineTables = BC.getDwarfLineTables(); 1205 1206 // Bail out early so we don't switch to the debug_line section needlessly and 1207 // in doing so create an unnecessary (if empty) section. 1208 if (LineTables.empty()) 1209 return; 1210 // In a v5 non-split line table, put the strings in a separate section. 1211 std::optional<MCDwarfLineStr> LineStr; 1212 ErrorOr<BinarySection &> LineStrSection = 1213 BC.getUniqueSectionByName(".debug_line_str"); 1214 1215 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower 1216 // .debug_line, so need to check if section exists. 1217 if (LineStrSection) { 1218 LineStr.emplace(*BC.Ctx); 1219 parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC); 1220 } 1221 1222 // Switch to the section where the table will be emitted into. 1223 Streamer.switchSection(BC.MOFI->getDwarfLineSection()); 1224 1225 const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); 1226 // Handle the rest of the Compile Units. 1227 for (auto &CUIDTablePair : LineTables) { 1228 Streamer.getContext().setDwarfVersion( 1229 CUIDTablePair.second.getDwarfVersion()); 1230 CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1231 } 1232 1233 // Resetting DWARF version for rest of the flow. 1234 BC.Ctx->setDwarfVersion(DwarfVersion); 1235 1236 // Still need to write the section out for the ExecutionEngine, and temp in 1237 // memory object we are constructing. 1238 if (LineStr) 1239 LineStr->emitSection(&Streamer); 1240 } 1241 1242 } // namespace bolt 1243 } // namespace llvm 1244