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