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