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