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