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