1a34c753fSRafael Auler //===- DebugData.cpp - Representation and writing of debugging information. ==// 2a34c753fSRafael Auler // 3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a34c753fSRafael Auler // 7a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8a34c753fSRafael Auler // 9a34c753fSRafael Auler //===----------------------------------------------------------------------===// 10a34c753fSRafael Auler 11a34c753fSRafael Auler #include "bolt/Core/DebugData.h" 12a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h" 13a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h" 14a34c753fSRafael Auler #include "bolt/Utils/Utils.h" 15a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h" 16a34c753fSRafael Auler #include "llvm/MC/MCSymbol.h" 17a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 18a34c753fSRafael Auler #include "llvm/Support/EndianStream.h" 19a34c753fSRafael Auler #include "llvm/Support/LEB128.h" 20a34c753fSRafael Auler #include <algorithm> 21a34c753fSRafael Auler #include <cassert> 22a34c753fSRafael Auler #include <cstdint> 23a34c753fSRafael Auler #include <limits> 24a34c753fSRafael Auler 25a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info" 26a34c753fSRafael Auler 27a34c753fSRafael Auler namespace opts { 28a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity; 29a34c753fSRafael Auler } 30a34c753fSRafael Auler 31a34c753fSRafael Auler namespace llvm { 32a34c753fSRafael Auler namespace bolt { 33a34c753fSRafael Auler 34a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 35a34c753fSRafael Auler 36a34c753fSRafael Auler namespace { 37a34c753fSRafael Auler 38a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size). 39a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of 40a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address). 41a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes. 42a34c753fSRafael Auler // Returns the number of written bytes. 43*40c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream, 44a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges, 45a34c753fSRafael Auler const bool WriteRelativeRanges = false) { 46a34c753fSRafael Auler for (const DebugAddressRange &Range : AddressRanges) { 47a34c753fSRafael Auler support::endian::write(Stream, Range.LowPC, support::little); 48a34c753fSRafael Auler support::endian::write( 49a34c753fSRafael Auler Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 50a34c753fSRafael Auler support::little); 51a34c753fSRafael Auler } 52a34c753fSRafael Auler // Finish with 0 entries. 53a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 54a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 55a34c753fSRafael Auler return AddressRanges.size() * 16 + 16; 56a34c753fSRafael Auler } 57a34c753fSRafael Auler 58a34c753fSRafael Auler } // namespace 59a34c753fSRafael Auler 60a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() { 61a34c753fSRafael Auler RangesBuffer = std::make_unique<DebugBufferVector>(); 62a34c753fSRafael Auler RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 63a34c753fSRafael Auler 64a34c753fSRafael Auler // Add an empty range as the first entry; 65a34c753fSRafael Auler SectionOffset += 66a34c753fSRafael Auler writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 67a34c753fSRafael Auler } 68a34c753fSRafael Auler 69a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges( 70a34c753fSRafael Auler DebugAddressRangesVector &&Ranges, 71a34c753fSRafael Auler std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 72a34c753fSRafael Auler if (Ranges.empty()) 73a34c753fSRafael Auler return getEmptyRangesOffset(); 74a34c753fSRafael Auler 75a34c753fSRafael Auler const auto RI = CachedRanges.find(Ranges); 76a34c753fSRafael Auler if (RI != CachedRanges.end()) 77a34c753fSRafael Auler return RI->second; 78a34c753fSRafael Auler 79a34c753fSRafael Auler const uint64_t EntryOffset = addRanges(Ranges); 80a34c753fSRafael Auler CachedRanges.emplace(std::move(Ranges), EntryOffset); 81a34c753fSRafael Auler 82a34c753fSRafael Auler return EntryOffset; 83a34c753fSRafael Auler } 84a34c753fSRafael Auler 85a34c753fSRafael Auler uint64_t 86a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) { 87a34c753fSRafael Auler if (Ranges.empty()) 88a34c753fSRafael Auler return getEmptyRangesOffset(); 89a34c753fSRafael Auler 90a34c753fSRafael Auler // Reading the SectionOffset and updating it should be atomic to guarantee 91a34c753fSRafael Auler // unique and correct offsets in patches. 92a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 93a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 94a34c753fSRafael Auler SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges); 95a34c753fSRafael Auler 96a34c753fSRafael Auler return EntryOffset; 97a34c753fSRafael Auler } 98a34c753fSRafael Auler 99a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() { 100a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 101a34c753fSRafael Auler return SectionOffset; 102a34c753fSRafael Auler } 103a34c753fSRafael Auler 104a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 105a34c753fSRafael Auler DebugAddressRangesVector &&Ranges) { 106a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 107a34c753fSRafael Auler CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 108a34c753fSRafael Auler } 109a34c753fSRafael Auler 110a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection( 111a34c753fSRafael Auler raw_svector_ostream &RangesStream) const { 112a34c753fSRafael Auler // For reference on the format of the .debug_aranges section, see the DWARF4 113a34c753fSRafael Auler // specification, section 6.1.4 Lookup by Address 114a34c753fSRafael Auler // http://www.dwarfstd.org/doc/DWARF4.pdf 115a34c753fSRafael Auler for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 116a34c753fSRafael Auler const uint64_t Offset = CUOffsetAddressRangesPair.first; 117a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges = 118a34c753fSRafael Auler CUOffsetAddressRangesPair.second; 119a34c753fSRafael Auler 120a34c753fSRafael Auler // Emit header. 121a34c753fSRafael Auler 122a34c753fSRafael Auler // Size of this set: 8 (size of the header) + 4 (padding after header) 123a34c753fSRafael Auler // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 124a34c753fSRafael Auler // pair of uint64_t's for the terminating, zero-length range. 125a34c753fSRafael Auler // Does not include size field itself. 126a34c753fSRafael Auler uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 127a34c753fSRafael Auler 128a34c753fSRafael Auler // Header field #1: set size. 129a34c753fSRafael Auler support::endian::write(RangesStream, Size, support::little); 130a34c753fSRafael Auler 131a34c753fSRafael Auler // Header field #2: version number, 2 as per the specification. 132a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint16_t>(2), 133a34c753fSRafael Auler support::little); 134a34c753fSRafael Auler 135a34c753fSRafael Auler // Header field #3: debug info offset of the correspondent compile unit. 136a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint32_t>(Offset), 137a34c753fSRafael Auler support::little); 138a34c753fSRafael Auler 139a34c753fSRafael Auler // Header field #4: address size. 140a34c753fSRafael Auler // 8 since we only write ELF64 binaries for now. 141a34c753fSRafael Auler RangesStream << char(8); 142a34c753fSRafael Auler 143a34c753fSRafael Auler // Header field #5: segment size of target architecture. 144a34c753fSRafael Auler RangesStream << char(0); 145a34c753fSRafael Auler 146a34c753fSRafael Auler // Padding before address table - 4 bytes in the 64-bit-pointer case. 147a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint32_t>(0), 148a34c753fSRafael Auler support::little); 149a34c753fSRafael Auler 150a34c753fSRafael Auler writeAddressRanges(RangesStream, AddressRanges, true); 151a34c753fSRafael Auler } 152a34c753fSRafael Auler } 153a34c753fSRafael Auler 154a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; } 155a34c753fSRafael Auler 156a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() { 157a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 158a34c753fSRafael Auler indexToAdddessEnd()); 159a34c753fSRafael Auler // Sorting address in increasing order of indices. 160a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 161a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 162a34c753fSRafael Auler return A.first < B.first; 163a34c753fSRafael Auler }); 164a34c753fSRafael Auler for (auto &Pair : SortedMap) 165a34c753fSRafael Auler dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 166a34c753fSRafael Auler } 167a34c753fSRafael Auler uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, 168a34c753fSRafael Auler uint64_t DWOId) { 169a34c753fSRafael Auler if (!AddressMaps.count(DWOId)) 170a34c753fSRafael Auler AddressMaps[DWOId] = AddressForDWOCU(); 171a34c753fSRafael Auler 172a34c753fSRafael Auler AddressForDWOCU &Map = AddressMaps[DWOId]; 173a34c753fSRafael Auler auto Entry = Map.find(Address); 174a34c753fSRafael Auler if (Entry == Map.end()) { 175a34c753fSRafael Auler auto Index = Map.getNextIndex(); 176a34c753fSRafael Auler Entry = Map.insert(Address, Index).first; 177a34c753fSRafael Auler } 178a34c753fSRafael Auler return Entry->second; 179a34c753fSRafael Auler } 180a34c753fSRafael Auler 181a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 182a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update 183a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 184a34c753fSRafael Auler // update AddressToIndex and IndexToAddress 185a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 186a34c753fSRafael Auler uint64_t DWOId) { 187a34c753fSRafael Auler AddressForDWOCU &Map = AddressMaps[DWOId]; 188a34c753fSRafael Auler auto Entry = Map.find(Address); 189a34c753fSRafael Auler if (Entry != Map.end()) { 190a34c753fSRafael Auler if (Entry->second > Index) 191a34c753fSRafael Auler Map.updateAddressToIndex(Address, Index); 192a34c753fSRafael Auler Map.updateIndexToAddrss(Address, Index); 193a34c753fSRafael Auler } else 194a34c753fSRafael Auler Map.insert(Address, Index); 195a34c753fSRafael Auler } 196a34c753fSRafael Auler 197a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() { 198a34c753fSRafael Auler // Need to layout all sections within .debug_addr 199a34c753fSRafael Auler // Within each section sort Address by index. 200a34c753fSRafael Auler AddressSectionBuffer Buffer; 201a34c753fSRafael Auler raw_svector_ostream AddressStream(Buffer); 202a34c753fSRafael Auler for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 203a34c753fSRafael Auler Optional<uint64_t> DWOId = CU->getDWOId(); 204a34c753fSRafael Auler // Handling the case wehre debug information is a mix of Debug fission and 205a34c753fSRafael Auler // monolitic. 206a34c753fSRafael Auler if (!DWOId) 207a34c753fSRafael Auler continue; 208a34c753fSRafael Auler auto AM = AddressMaps.find(*DWOId); 209a34c753fSRafael Auler // Adding to map even if it did not contribute to .debug_addr. 210a34c753fSRafael Auler // The Skeleton CU will still have DW_AT_GNU_addr_base. 211a34c753fSRafael Auler DWOIdToOffsetMap[*DWOId] = Buffer.size(); 212a34c753fSRafael Auler // If does not exist this CUs DWO section didn't contribute to .debug_addr. 213a34c753fSRafael Auler if (AM == AddressMaps.end()) 214a34c753fSRafael Auler continue; 215a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 216a34c753fSRafael Auler AM->second.indexToAdddessEnd()); 217a34c753fSRafael Auler // Sorting address in increasing order of indices. 218a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 219a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 220a34c753fSRafael Auler return A.first < B.first; 221a34c753fSRafael Auler }); 222a34c753fSRafael Auler 223a34c753fSRafael Auler uint8_t AddrSize = CU->getAddressByteSize(); 224a34c753fSRafael Auler uint32_t Counter = 0; 225a34c753fSRafael Auler auto WriteAddress = [&](uint64_t Address) -> void { 226a34c753fSRafael Auler ++Counter; 227a34c753fSRafael Auler switch (AddrSize) { 228a34c753fSRafael Auler default: 229a34c753fSRafael Auler assert(false && "Address Size is invalid."); 230a34c753fSRafael Auler break; 231a34c753fSRafael Auler case 4: 232a34c753fSRafael Auler support::endian::write(AddressStream, static_cast<uint32_t>(Address), 233a34c753fSRafael Auler support::little); 234a34c753fSRafael Auler break; 235a34c753fSRafael Auler case 8: 236a34c753fSRafael Auler support::endian::write(AddressStream, Address, support::little); 237a34c753fSRafael Auler break; 238a34c753fSRafael Auler } 239a34c753fSRafael Auler }; 240a34c753fSRafael Auler 241a34c753fSRafael Auler for (const IndexAddressPair &Val : SortedMap) { 242a34c753fSRafael Auler while (Val.first > Counter) 243a34c753fSRafael Auler WriteAddress(0); 244a34c753fSRafael Auler WriteAddress(Val.second); 245a34c753fSRafael Auler } 246a34c753fSRafael Auler } 247a34c753fSRafael Auler 248a34c753fSRafael Auler return Buffer; 249a34c753fSRafael Auler } 250a34c753fSRafael Auler 251a34c753fSRafael Auler uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) { 252a34c753fSRafael Auler auto Iter = DWOIdToOffsetMap.find(DWOId); 253a34c753fSRafael Auler assert(Iter != DWOIdToOffsetMap.end() && 254a34c753fSRafael Auler "Offset in to.debug_addr was not found for DWO ID."); 255a34c753fSRafael Auler return Iter->second; 256a34c753fSRafael Auler } 257a34c753fSRafael Auler 258a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) { 259a34c753fSRafael Auler LocBuffer = std::make_unique<DebugBufferVector>(); 260a34c753fSRafael Auler LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 261a34c753fSRafael Auler } 262a34c753fSRafael Auler 263a34c753fSRafael Auler void DebugLocWriter::addList(uint64_t AttrOffset, 264a34c753fSRafael Auler DebugLocationsVector &&LocList) { 265a34c753fSRafael Auler if (LocList.empty()) { 266a34c753fSRafael Auler EmptyAttrLists.push_back(AttrOffset); 267a34c753fSRafael Auler return; 268a34c753fSRafael Auler } 269a34c753fSRafael Auler // Since there is a separate DebugLocWriter for each thread, 270a34c753fSRafael Auler // we don't need a lock to read the SectionOffset and update it. 271a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 272a34c753fSRafael Auler 273a34c753fSRafael Auler for (const DebugLocationEntry &Entry : LocList) { 274a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 275a34c753fSRafael Auler support::little); 276a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 277a34c753fSRafael Auler support::little); 278a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 279a34c753fSRafael Auler support::little); 280a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 281a34c753fSRafael Auler Entry.Expr.size()); 282a34c753fSRafael Auler SectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 283a34c753fSRafael Auler } 284a34c753fSRafael Auler LocStream->write_zeros(16); 285a34c753fSRafael Auler SectionOffset += 16; 286a34c753fSRafael Auler LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 287a34c753fSRafael Auler } 288a34c753fSRafael Auler 289a34c753fSRafael Auler void DebugLoclistWriter::addList(uint64_t AttrOffset, 290a34c753fSRafael Auler DebugLocationsVector &&LocList) { 291a34c753fSRafael Auler Patches.push_back({AttrOffset, std::move(LocList)}); 292a34c753fSRafael Auler } 293a34c753fSRafael Auler 294a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 295a34c753fSRafael Auler return std::move(LocBuffer); 296a34c753fSRafael Auler } 297a34c753fSRafael Auler 298a34c753fSRafael Auler // DWARF 4: 2.6.2 299a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset, 300a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 301a34c753fSRafael Auler for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) { 302a34c753fSRafael Auler uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset; 303a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset, 304a34c753fSRafael Auler Offset); 305a34c753fSRafael Auler } 306a34c753fSRafael Auler 307a34c753fSRafael Auler for (uint64_t DebugInfoAttrOffset : EmptyAttrLists) 308a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset, 309a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 310a34c753fSRafael Auler } 311a34c753fSRafael Auler 312a34c753fSRafael Auler void DebugLoclistWriter::finalize(uint64_t SectionOffset, 313a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 314a34c753fSRafael Auler for (LocPatch &Patch : Patches) { 315a34c753fSRafael Auler if (Patch.LocList.empty()) { 316a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, 317a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 318a34c753fSRafael Auler continue; 319a34c753fSRafael Auler } 320a34c753fSRafael Auler const uint32_t EntryOffset = LocBuffer->size(); 321a34c753fSRafael Auler for (const DebugLocationEntry &Entry : Patch.LocList) { 322a34c753fSRafael Auler support::endian::write(*LocStream, 323a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 324a34c753fSRafael Auler support::little); 325a34c753fSRafael Auler uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId); 326a34c753fSRafael Auler encodeULEB128(Index, *LocStream); 327a34c753fSRafael Auler 328a34c753fSRafael Auler // TODO: Support DWARF5 329a34c753fSRafael Auler support::endian::write(*LocStream, 330a34c753fSRafael Auler static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 331a34c753fSRafael Auler support::little); 332a34c753fSRafael Auler support::endian::write(*LocStream, 333a34c753fSRafael Auler static_cast<uint16_t>(Entry.Expr.size()), 334a34c753fSRafael Auler support::little); 335a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 336a34c753fSRafael Auler Entry.Expr.size()); 337a34c753fSRafael Auler } 338a34c753fSRafael Auler support::endian::write(*LocStream, 339a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 340a34c753fSRafael Auler support::little); 341a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); 342a34c753fSRafael Auler clearList(Patch.LocList); 343a34c753fSRafael Auler } 344a34c753fSRafael Auler clearList(Patches); 345a34c753fSRafael Auler } 346a34c753fSRafael Auler 347a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 348a34c753fSRafael Auler 349a34c753fSRafael Auler void SimpleBinaryPatcher::addBinaryPatch(uint32_t Offset, 350a34c753fSRafael Auler const std::string &NewValue) { 351a34c753fSRafael Auler Patches.emplace_back(Offset, NewValue); 352a34c753fSRafael Auler } 353a34c753fSRafael Auler 354a34c753fSRafael Auler void SimpleBinaryPatcher::addBytePatch(uint32_t Offset, uint8_t Value) { 355a34c753fSRafael Auler Patches.emplace_back(Offset, std::string(1, Value)); 356a34c753fSRafael Auler } 357a34c753fSRafael Auler 358a34c753fSRafael Auler void SimpleBinaryPatcher::addLEPatch(uint32_t Offset, uint64_t NewValue, 359a34c753fSRafael Auler size_t ByteSize) { 360a34c753fSRafael Auler std::string LE64(ByteSize, 0); 361a34c753fSRafael Auler for (size_t I = 0; I < ByteSize; ++I) { 362a34c753fSRafael Auler LE64[I] = NewValue & 0xff; 363a34c753fSRafael Auler NewValue >>= 8; 364a34c753fSRafael Auler } 365a34c753fSRafael Auler Patches.emplace_back(Offset, LE64); 366a34c753fSRafael Auler } 367a34c753fSRafael Auler 368*40c2e0faSMaksim Panchenko void SimpleBinaryPatcher::addUDataPatch(uint32_t Offset, uint64_t Value, 369*40c2e0faSMaksim Panchenko uint64_t Size) { 370a34c753fSRafael Auler std::string Buff; 371a34c753fSRafael Auler raw_string_ostream OS(Buff); 372a34c753fSRafael Auler encodeULEB128(Value, OS, Size); 373a34c753fSRafael Auler 374a34c753fSRafael Auler Patches.emplace_back(Offset, OS.str()); 375a34c753fSRafael Auler } 376a34c753fSRafael Auler 377a34c753fSRafael Auler void SimpleBinaryPatcher::addLE64Patch(uint32_t Offset, uint64_t NewValue) { 378a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 379a34c753fSRafael Auler } 380a34c753fSRafael Auler 381a34c753fSRafael Auler void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) { 382a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 383a34c753fSRafael Auler } 384a34c753fSRafael Auler 385a34c753fSRafael Auler void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents, 386a34c753fSRafael Auler uint32_t DWPOffset = 0) { 387a34c753fSRafael Auler for (const auto &Patch : Patches) { 388a34c753fSRafael Auler uint32_t Offset = Patch.first - DWPOffset; 389a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 390a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 391a34c753fSRafael Auler "Applied patch runs over binary size."); 392a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 393a34c753fSRafael Auler BinaryContents[Offset + I] = ByteSequence[I]; 394a34c753fSRafael Auler } 395a34c753fSRafael Auler } 396a34c753fSRafael Auler } 397a34c753fSRafael Auler 398a34c753fSRafael Auler void DebugStrWriter::create() { 399a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 400a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 401a34c753fSRafael Auler } 402a34c753fSRafael Auler 403a34c753fSRafael Auler void DebugStrWriter::initialize() { 404a34c753fSRafael Auler auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); 405a34c753fSRafael Auler (*StrStream) << StrSection; 406a34c753fSRafael Auler } 407a34c753fSRafael Auler 408a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 409a34c753fSRafael Auler if (StrBuffer->empty()) 410a34c753fSRafael Auler initialize(); 411a34c753fSRafael Auler auto Offset = StrBuffer->size(); 412a34c753fSRafael Auler (*StrStream) << Str; 413a34c753fSRafael Auler StrStream->write_zeros(1); 414a34c753fSRafael Auler return Offset; 415a34c753fSRafael Auler } 416a34c753fSRafael Auler 417a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 418a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 419a34c753fSRafael Auler if (!Abbrevs) 420a34c753fSRafael Auler return; 421a34c753fSRafael Auler 422a34c753fSRafael Auler // Multiple units may share the same abbreviations. Only add abbreviations 423a34c753fSRafael Auler // for the first unit and reuse them. 424a34c753fSRafael Auler const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset(); 42545f94abcSMaksim Panchenko if (UnitsAbbrevData.find(AbbrevOffset) != UnitsAbbrevData.end()) 426a34c753fSRafael Auler return; 427a34c753fSRafael Auler 42845f94abcSMaksim Panchenko AbbrevData &UnitData = UnitsAbbrevData[AbbrevOffset]; 429a34c753fSRafael Auler UnitData.Buffer = std::make_unique<DebugBufferVector>(); 430a34c753fSRafael Auler UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 431a34c753fSRafael Auler 43245f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 433a34c753fSRafael Auler 434a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 435a34c753fSRafael Auler 436a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 437a34c753fSRafael Auler // contents. 438a34c753fSRafael Auler if (UnitPatches.empty()) { 439a34c753fSRafael Auler StringRef AbbrevSectionContents = 440a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 441a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 442a34c753fSRafael Auler StringRef AbbrevContents; 443a34c753fSRafael Auler 444a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 445a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 446a34c753fSRafael Auler // Handle DWP section contribution. 447a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 448a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 449a34c753fSRafael Auler if (!DWOEntry) 450a34c753fSRafael Auler return; 451a34c753fSRafael Auler 452a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 453a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 454a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 455a34c753fSRafael Auler DWOContrubution->Length); 45645f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 457a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 45845f94abcSMaksim Panchenko 45945f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 46045f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 46145f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 46245f94abcSMaksim Panchenko // the set boundaries. 46345f94abcSMaksim Panchenko // 46445f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 46545f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 46645f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 46745f94abcSMaksim Panchenko llvm::for_each( 46845f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 46945f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 47045f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 47145f94abcSMaksim Panchenko }); 47245f94abcSMaksim Panchenko llvm::sort(AbbrevSetOffsets); 47345f94abcSMaksim Panchenko } 47445f94abcSMaksim Panchenko auto It = llvm::upper_bound(AbbrevSetOffsets, StartOffset); 47545f94abcSMaksim Panchenko const uint64_t EndOffset = 47645f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 477a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 47845f94abcSMaksim Panchenko } else { 47945f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 48045f94abcSMaksim Panchenko // abbreviations for this unit only. 48145f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 482a34c753fSRafael Auler } 483a34c753fSRafael Auler 484a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 485a34c753fSRafael Auler OS << AbbrevContents; 486a34c753fSRafael Auler 487a34c753fSRafael Auler return; 488a34c753fSRafael Auler } 489a34c753fSRafael Auler 490a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 491a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 492a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 493a34c753fSRafael Auler 494a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 495a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 496a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 497a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 498a34c753fSRafael Auler Abbrev.attributes()) { 499a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 500a34c753fSRafael Auler bool Patched = false; 501a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 502a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 503a34c753fSRafael Auler ++I) { 504a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 505a34c753fSRafael Auler continue; 506a34c753fSRafael Auler 507a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 508a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 509a34c753fSRafael Auler Patched = true; 510a34c753fSRafael Auler break; 511a34c753fSRafael Auler } 512a34c753fSRafael Auler if (Patched) 513a34c753fSRafael Auler continue; 514a34c753fSRafael Auler } 515a34c753fSRafael Auler 516a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 517a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 518a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 519a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 520a34c753fSRafael Auler } 521a34c753fSRafael Auler 522a34c753fSRafael Auler encodeULEB128(0, OS); 523a34c753fSRafael Auler encodeULEB128(0, OS); 524a34c753fSRafael Auler } 525a34c753fSRafael Auler encodeULEB128(0, OS); 526a34c753fSRafael Auler } 527a34c753fSRafael Auler 528a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 52945f94abcSMaksim Panchenko if (DWOId) { 53045f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 53145f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 53245f94abcSMaksim Panchenko // set with the CU. 5331417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 5341417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 53545f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 5361417f607SAlexander Yermolovich if (!IsDWP) { 53745f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 53845f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 53945f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 54045f94abcSMaksim Panchenko "Unable to update debug info.\n"; 54145f94abcSMaksim Panchenko exit(1); 54245f94abcSMaksim Panchenko } 54345f94abcSMaksim Panchenko } 54445f94abcSMaksim Panchenko } 54545f94abcSMaksim Panchenko 54645f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 54745f94abcSMaksim Panchenko addUnitAbbreviations(*Context.getDWOCompileUnitForHash(*DWOId)); 54845f94abcSMaksim Panchenko } else { 54945f94abcSMaksim Panchenko // Add abbreviations from compile and type non-DWO units. 55045f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) 55145f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 55245f94abcSMaksim Panchenko } 55345f94abcSMaksim Panchenko 554a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 555a34c753fSRafael Auler 556a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 557a34c753fSRafael Auler uint64_t Size = 0; 55845f94abcSMaksim Panchenko for (const auto &KV : UnitsAbbrevData) { 559a34c753fSRafael Auler const AbbrevData &UnitData = KV.second; 560a34c753fSRafael Auler Size += UnitData.Buffer->size(); 561a34c753fSRafael Auler } 562a34c753fSRafael Auler ReturnBuffer.reserve(Size); 563a34c753fSRafael Auler 564a34c753fSRafael Auler uint64_t Pos = 0; 56545f94abcSMaksim Panchenko for (auto &KV : UnitsAbbrevData) { 566a34c753fSRafael Auler AbbrevData &UnitData = KV.second; 567a34c753fSRafael Auler ReturnBuffer.append(*UnitData.Buffer); 568a34c753fSRafael Auler UnitData.Offset = Pos; 569a34c753fSRafael Auler Pos += UnitData.Buffer->size(); 570a34c753fSRafael Auler 571a34c753fSRafael Auler UnitData.Buffer.reset(); 572a34c753fSRafael Auler UnitData.Stream.reset(); 573a34c753fSRafael Auler } 574a34c753fSRafael Auler 575a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 576a34c753fSRafael Auler } 577a34c753fSRafael Auler 578a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 579a34c753fSRafael Auler MCDwarfLineTableParams Params, 580a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 581a34c753fSRafael Auler int PointerSize) { 582a34c753fSRafael Auler // emit the sequence to set the address 583a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 584a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 585a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 586a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 587a34c753fSRafael Auler 588a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 589a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 590a34c753fSRafael Auler } 591a34c753fSRafael Auler 592a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 593a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 594a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 595a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 596a34c753fSRafael Auler if (InputSequences.empty()) 597a34c753fSRafael Auler return; 598a34c753fSRafael Auler 599a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 600a34c753fSRafael Auler unsigned FileNum = 1; 601a34c753fSRafael Auler unsigned LastLine = 1; 602a34c753fSRafael Auler unsigned Column = 0; 603a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 604a34c753fSRafael Auler unsigned Isa = 0; 605a34c753fSRafael Auler unsigned Discriminator = 0; 606a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 607a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 608a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 609a34c753fSRafael Auler 610a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 611a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 612a34c753fSRafael Auler FileNum = 1; 613a34c753fSRafael Auler LastLine = 1; 614a34c753fSRafael Auler Column = 0; 615a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 616a34c753fSRafael Auler Isa = 0; 617a34c753fSRafael Auler Discriminator = 0; 618a34c753fSRafael Auler LastAddress = InvalidAddress; 619a34c753fSRafael Auler }; 620a34c753fSRafael Auler 621a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 622a34c753fSRafael Auler const uint64_t SequenceStart = 623a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 624a34c753fSRafael Auler 625a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 626a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 627a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 628a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 629a34c753fSRafael Auler } 630a34c753fSRafael Auler 631a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 632a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 633a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 634a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 635a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 636a34c753fSRafael Auler 637a34c753fSRafael Auler if (FileNum != Row.File) { 638a34c753fSRafael Auler FileNum = Row.File; 639a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 640a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 641a34c753fSRafael Auler } 642a34c753fSRafael Auler if (Column != Row.Column) { 643a34c753fSRafael Auler Column = Row.Column; 644a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 645a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 646a34c753fSRafael Auler } 647a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 648a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 649a34c753fSRafael Auler Discriminator = Row.Discriminator; 650a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 651a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 652a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 653a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 654a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 655a34c753fSRafael Auler } 656a34c753fSRafael Auler if (Isa != Row.Isa) { 657a34c753fSRafael Auler Isa = Row.Isa; 658a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 659a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 660a34c753fSRafael Auler } 661a34c753fSRafael Auler if (Row.IsStmt != Flags) { 662a34c753fSRafael Auler Flags = Row.IsStmt; 663a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 664a34c753fSRafael Auler } 665a34c753fSRafael Auler if (Row.BasicBlock) 666a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 667a34c753fSRafael Auler if (Row.PrologueEnd) 668a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 669a34c753fSRafael Auler if (Row.EpilogueBegin) 670a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 671a34c753fSRafael Auler 672a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 673a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 674a34c753fSRafael Auler if (Row.EndSequence) { 675a34c753fSRafael Auler emitEndOfSequence(Address); 676a34c753fSRafael Auler } else { 677a34c753fSRafael Auler if (LastAddress == InvalidAddress) 678a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 679a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 680a34c753fSRafael Auler else 681a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 682a34c753fSRafael Auler 683a34c753fSRafael Auler LastAddress = Address; 684a34c753fSRafael Auler LastLine = Row.Line; 685a34c753fSRafael Auler } 686a34c753fSRafael Auler 687a34c753fSRafael Auler Discriminator = 0; 688a34c753fSRafael Auler } 689a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 690a34c753fSRafael Auler } 691a34c753fSRafael Auler 692a34c753fSRafael Auler // Finish with the end of the sequence. 693a34c753fSRafael Auler if (LastAddress != InvalidAddress) 694a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 695a34c753fSRafael Auler } 696a34c753fSRafael Auler 697a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 698a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 699a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 700a34c753fSRafael Auler static inline void emitDwarfLineTable( 701a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 702a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 703a34c753fSRafael Auler unsigned FileNum = 1; 704a34c753fSRafael Auler unsigned LastLine = 1; 705a34c753fSRafael Auler unsigned Column = 0; 706a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 707a34c753fSRafael Auler unsigned Isa = 0; 708a34c753fSRafael Auler unsigned Discriminator = 0; 709a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 710a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 711a34c753fSRafael Auler 712a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 713a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 714a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 715a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 716a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 717a34c753fSRafael Auler FileNum = 1; 718a34c753fSRafael Auler LastLine = 1; 719a34c753fSRafael Auler Column = 0; 720a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 721a34c753fSRafael Auler Isa = 0; 722a34c753fSRafael Auler Discriminator = 0; 723a34c753fSRafael Auler LastLabel = nullptr; 724a34c753fSRafael Auler continue; 725a34c753fSRafael Auler } 726a34c753fSRafael Auler 727a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 728a34c753fSRafael Auler 729a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 730a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 731a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 732a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 733a34c753fSRafael Auler } 734a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 735a34c753fSRafael Auler Column = LineEntry.getColumn(); 736a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 737a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 738a34c753fSRafael Auler } 739a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 740a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 741a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 742a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 743a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 744a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 745a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 746a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 747a34c753fSRafael Auler } 748a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 749a34c753fSRafael Auler Isa = LineEntry.getIsa(); 750a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 751a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 752a34c753fSRafael Auler } 753a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 754a34c753fSRafael Auler Flags = LineEntry.getFlags(); 755a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 756a34c753fSRafael Auler } 757a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 758a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 759a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 760a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 761a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 762a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 763a34c753fSRafael Auler 764a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 765a34c753fSRafael Auler 766a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 767a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 768a34c753fSRafael Auler // Label and the current Label. 769a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 770a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 771a34c753fSRafael Auler Discriminator = 0; 772a34c753fSRafael Auler LastLine = LineEntry.getLine(); 773a34c753fSRafael Auler LastLabel = Label; 774a34c753fSRafael Auler } 775a34c753fSRafael Auler 776a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 777a34c753fSRafael Auler } 778a34c753fSRafael Auler 779a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 780b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 781b73c87bcSMaksim Panchenko BinaryContext &BC) const { 782a34c753fSRafael Auler if (!RawData.empty()) { 783a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 784a34c753fSRafael Auler InputSequences.empty() && 785a34c753fSRafael Auler "cannot combine raw data with new line entries"); 786a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 787a34c753fSRafael Auler MCOS->emitBytes(RawData); 788a34c753fSRafael Auler 789b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 790b73c87bcSMaksim Panchenko // 791b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 792b73c87bcSMaksim Panchenko // without relocations. 793b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 794b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 795b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 796b73c87bcSMaksim Panchenko 797a34c753fSRafael Auler return; 798a34c753fSRafael Auler } 799a34c753fSRafael Auler 800a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 801a34c753fSRafael Auler 802a34c753fSRafael Auler // Put out the line tables. 803a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 804a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 805a34c753fSRafael Auler 806a34c753fSRafael Auler // Emit line tables for the original code. 807a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 808a34c753fSRafael Auler 809a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 810a34c753fSRafael Auler // of this section (that was used in a previous expression). 811a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 812a34c753fSRafael Auler } 813a34c753fSRafael Auler 814a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 815a34c753fSRafael Auler MCAssembler &Assembler = 816a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 817a34c753fSRafael Auler 818a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 819a34c753fSRafael Auler 820a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 821a34c753fSRafael Auler 822a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 823a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 824a34c753fSRafael Auler if (LineTables.empty()) 825a34c753fSRafael Auler return; 826a34c753fSRafael Auler 827a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 828a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 829a34c753fSRafael Auler if (BC.Ctx->getDwarfVersion() >= 5) 830a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 831a34c753fSRafael Auler 832a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 833a34c753fSRafael Auler Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); 834a34c753fSRafael Auler 835a34c753fSRafael Auler // Handle the rest of the Compile Units. 836a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 837b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 838a34c753fSRafael Auler } 839a34c753fSRafael Auler } 840a34c753fSRafael Auler 841a34c753fSRafael Auler } // namespace bolt 842a34c753fSRafael Auler } // namespace llvm 843