1*2f09f445SMaksim Panchenko //===- bolt/Core/DebugData.cpp - Debugging information handling -----------===// 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 // 9*2f09f445SMaksim Panchenko // This file implements functions and classes for handling debug info. 10*2f09f445SMaksim Panchenko // 11a34c753fSRafael Auler //===----------------------------------------------------------------------===// 12a34c753fSRafael Auler 13a34c753fSRafael Auler #include "bolt/Core/DebugData.h" 14a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h" 15a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h" 16a34c753fSRafael Auler #include "bolt/Utils/Utils.h" 17a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h" 18a34c753fSRafael Auler #include "llvm/MC/MCSymbol.h" 19a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 20a34c753fSRafael Auler #include "llvm/Support/EndianStream.h" 21a34c753fSRafael Auler #include "llvm/Support/LEB128.h" 22a34c753fSRafael Auler #include <algorithm> 23a34c753fSRafael Auler #include <cassert> 24a34c753fSRafael Auler #include <cstdint> 25a34c753fSRafael Auler #include <limits> 26a34c753fSRafael Auler 27a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info" 28a34c753fSRafael Auler 29a34c753fSRafael Auler namespace opts { 30a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity; 31a34c753fSRafael Auler } 32a34c753fSRafael Auler 33a34c753fSRafael Auler namespace llvm { 34a34c753fSRafael Auler namespace bolt { 35a34c753fSRafael Auler 36a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 37a34c753fSRafael Auler 38a34c753fSRafael Auler namespace { 39a34c753fSRafael Auler 40a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size). 41a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of 42a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address). 43a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes. 44a34c753fSRafael Auler // Returns the number of written bytes. 4540c2e0faSMaksim Panchenko uint64_t writeAddressRanges(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 37040c2e0faSMaksim Panchenko void SimpleBinaryPatcher::addUDataPatch(uint32_t Offset, uint64_t Value, 37140c2e0faSMaksim Panchenko uint64_t Size) { 372a34c753fSRafael Auler std::string Buff; 373a34c753fSRafael Auler raw_string_ostream OS(Buff); 374a34c753fSRafael Auler encodeULEB128(Value, OS, Size); 375a34c753fSRafael Auler 376a34c753fSRafael Auler Patches.emplace_back(Offset, OS.str()); 377a34c753fSRafael Auler } 378a34c753fSRafael Auler 379a34c753fSRafael Auler void SimpleBinaryPatcher::addLE64Patch(uint32_t Offset, uint64_t NewValue) { 380a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 381a34c753fSRafael Auler } 382a34c753fSRafael Auler 383a34c753fSRafael Auler void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) { 384a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 385a34c753fSRafael Auler } 386a34c753fSRafael Auler 387a34c753fSRafael Auler void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents, 388a34c753fSRafael Auler uint32_t DWPOffset = 0) { 389a34c753fSRafael Auler for (const auto &Patch : Patches) { 390a34c753fSRafael Auler uint32_t Offset = Patch.first - DWPOffset; 391a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 392a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 393a34c753fSRafael Auler "Applied patch runs over binary size."); 394a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 395a34c753fSRafael Auler BinaryContents[Offset + I] = ByteSequence[I]; 396a34c753fSRafael Auler } 397a34c753fSRafael Auler } 398a34c753fSRafael Auler } 399a34c753fSRafael Auler 400a34c753fSRafael Auler void DebugStrWriter::create() { 401a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 402a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 403a34c753fSRafael Auler } 404a34c753fSRafael Auler 405a34c753fSRafael Auler void DebugStrWriter::initialize() { 406a34c753fSRafael Auler auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); 407a34c753fSRafael Auler (*StrStream) << StrSection; 408a34c753fSRafael Auler } 409a34c753fSRafael Auler 410a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 411a34c753fSRafael Auler if (StrBuffer->empty()) 412a34c753fSRafael Auler initialize(); 413a34c753fSRafael Auler auto Offset = StrBuffer->size(); 414a34c753fSRafael Auler (*StrStream) << Str; 415a34c753fSRafael Auler StrStream->write_zeros(1); 416a34c753fSRafael Auler return Offset; 417a34c753fSRafael Auler } 418a34c753fSRafael Auler 419a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 420a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 421a34c753fSRafael Auler if (!Abbrevs) 422a34c753fSRafael Auler return; 423a34c753fSRafael Auler 424a34c753fSRafael Auler // Multiple units may share the same abbreviations. Only add abbreviations 425a34c753fSRafael Auler // for the first unit and reuse them. 426a34c753fSRafael Auler const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset(); 42745f94abcSMaksim Panchenko if (UnitsAbbrevData.find(AbbrevOffset) != UnitsAbbrevData.end()) 428a34c753fSRafael Auler return; 429a34c753fSRafael Auler 43045f94abcSMaksim Panchenko AbbrevData &UnitData = UnitsAbbrevData[AbbrevOffset]; 431a34c753fSRafael Auler UnitData.Buffer = std::make_unique<DebugBufferVector>(); 432a34c753fSRafael Auler UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 433a34c753fSRafael Auler 43445f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 435a34c753fSRafael Auler 436a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 437a34c753fSRafael Auler 438a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 439a34c753fSRafael Auler // contents. 440a34c753fSRafael Auler if (UnitPatches.empty()) { 441a34c753fSRafael Auler StringRef AbbrevSectionContents = 442a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 443a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 444a34c753fSRafael Auler StringRef AbbrevContents; 445a34c753fSRafael Auler 446a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 447a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 448a34c753fSRafael Auler // Handle DWP section contribution. 449a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 450a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 451a34c753fSRafael Auler if (!DWOEntry) 452a34c753fSRafael Auler return; 453a34c753fSRafael Auler 454a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 455a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 456a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 457a34c753fSRafael Auler DWOContrubution->Length); 45845f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 459a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 46045f94abcSMaksim Panchenko 46145f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 46245f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 46345f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 46445f94abcSMaksim Panchenko // the set boundaries. 46545f94abcSMaksim Panchenko // 46645f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 46745f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 46845f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 46945f94abcSMaksim Panchenko llvm::for_each( 47045f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 47145f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 47245f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 47345f94abcSMaksim Panchenko }); 47445f94abcSMaksim Panchenko llvm::sort(AbbrevSetOffsets); 47545f94abcSMaksim Panchenko } 47645f94abcSMaksim Panchenko auto It = llvm::upper_bound(AbbrevSetOffsets, StartOffset); 47745f94abcSMaksim Panchenko const uint64_t EndOffset = 47845f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 479a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 48045f94abcSMaksim Panchenko } else { 48145f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 48245f94abcSMaksim Panchenko // abbreviations for this unit only. 48345f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 484a34c753fSRafael Auler } 485a34c753fSRafael Auler 486a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 487a34c753fSRafael Auler OS << AbbrevContents; 488a34c753fSRafael Auler 489a34c753fSRafael Auler return; 490a34c753fSRafael Auler } 491a34c753fSRafael Auler 492a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 493a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 494a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 495a34c753fSRafael Auler 496a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 497a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 498a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 499a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 500a34c753fSRafael Auler Abbrev.attributes()) { 501a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 502a34c753fSRafael Auler bool Patched = false; 503a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 504a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 505a34c753fSRafael Auler ++I) { 506a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 507a34c753fSRafael Auler continue; 508a34c753fSRafael Auler 509a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 510a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 511a34c753fSRafael Auler Patched = true; 512a34c753fSRafael Auler break; 513a34c753fSRafael Auler } 514a34c753fSRafael Auler if (Patched) 515a34c753fSRafael Auler continue; 516a34c753fSRafael Auler } 517a34c753fSRafael Auler 518a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 519a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 520a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 521a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 522a34c753fSRafael Auler } 523a34c753fSRafael Auler 524a34c753fSRafael Auler encodeULEB128(0, OS); 525a34c753fSRafael Auler encodeULEB128(0, OS); 526a34c753fSRafael Auler } 527a34c753fSRafael Auler encodeULEB128(0, OS); 528a34c753fSRafael Auler } 529a34c753fSRafael Auler 530a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 53145f94abcSMaksim Panchenko if (DWOId) { 53245f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 53345f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 53445f94abcSMaksim Panchenko // set with the CU. 5351417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 5361417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 53745f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 5381417f607SAlexander Yermolovich if (!IsDWP) { 53945f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 54045f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 54145f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 54245f94abcSMaksim Panchenko "Unable to update debug info.\n"; 54345f94abcSMaksim Panchenko exit(1); 54445f94abcSMaksim Panchenko } 54545f94abcSMaksim Panchenko } 54645f94abcSMaksim Panchenko } 54745f94abcSMaksim Panchenko 54845f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 54945f94abcSMaksim Panchenko addUnitAbbreviations(*Context.getDWOCompileUnitForHash(*DWOId)); 55045f94abcSMaksim Panchenko } else { 55145f94abcSMaksim Panchenko // Add abbreviations from compile and type non-DWO units. 55245f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) 55345f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 55445f94abcSMaksim Panchenko } 55545f94abcSMaksim Panchenko 556a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 557a34c753fSRafael Auler 558a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 559a34c753fSRafael Auler uint64_t Size = 0; 56045f94abcSMaksim Panchenko for (const auto &KV : UnitsAbbrevData) { 561a34c753fSRafael Auler const AbbrevData &UnitData = KV.second; 562a34c753fSRafael Auler Size += UnitData.Buffer->size(); 563a34c753fSRafael Auler } 564a34c753fSRafael Auler ReturnBuffer.reserve(Size); 565a34c753fSRafael Auler 566a34c753fSRafael Auler uint64_t Pos = 0; 56745f94abcSMaksim Panchenko for (auto &KV : UnitsAbbrevData) { 568a34c753fSRafael Auler AbbrevData &UnitData = KV.second; 569a34c753fSRafael Auler ReturnBuffer.append(*UnitData.Buffer); 570a34c753fSRafael Auler UnitData.Offset = Pos; 571a34c753fSRafael Auler Pos += UnitData.Buffer->size(); 572a34c753fSRafael Auler 573a34c753fSRafael Auler UnitData.Buffer.reset(); 574a34c753fSRafael Auler UnitData.Stream.reset(); 575a34c753fSRafael Auler } 576a34c753fSRafael Auler 577a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 578a34c753fSRafael Auler } 579a34c753fSRafael Auler 580a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 581a34c753fSRafael Auler MCDwarfLineTableParams Params, 582a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 583a34c753fSRafael Auler int PointerSize) { 584a34c753fSRafael Auler // emit the sequence to set the address 585a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 586a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 587a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 588a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 589a34c753fSRafael Auler 590a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 591a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 592a34c753fSRafael Auler } 593a34c753fSRafael Auler 594a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 595a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 596a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 597a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 598a34c753fSRafael Auler if (InputSequences.empty()) 599a34c753fSRafael Auler return; 600a34c753fSRafael Auler 601a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 602a34c753fSRafael Auler unsigned FileNum = 1; 603a34c753fSRafael Auler unsigned LastLine = 1; 604a34c753fSRafael Auler unsigned Column = 0; 605a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 606a34c753fSRafael Auler unsigned Isa = 0; 607a34c753fSRafael Auler unsigned Discriminator = 0; 608a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 609a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 610a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 611a34c753fSRafael Auler 612a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 613a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 614a34c753fSRafael Auler FileNum = 1; 615a34c753fSRafael Auler LastLine = 1; 616a34c753fSRafael Auler Column = 0; 617a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 618a34c753fSRafael Auler Isa = 0; 619a34c753fSRafael Auler Discriminator = 0; 620a34c753fSRafael Auler LastAddress = InvalidAddress; 621a34c753fSRafael Auler }; 622a34c753fSRafael Auler 623a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 624a34c753fSRafael Auler const uint64_t SequenceStart = 625a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 626a34c753fSRafael Auler 627a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 628a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 629a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 630a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 631a34c753fSRafael Auler } 632a34c753fSRafael Auler 633a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 634a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 635a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 636a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 637a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 638a34c753fSRafael Auler 639a34c753fSRafael Auler if (FileNum != Row.File) { 640a34c753fSRafael Auler FileNum = Row.File; 641a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 642a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 643a34c753fSRafael Auler } 644a34c753fSRafael Auler if (Column != Row.Column) { 645a34c753fSRafael Auler Column = Row.Column; 646a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 647a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 648a34c753fSRafael Auler } 649a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 650a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 651a34c753fSRafael Auler Discriminator = Row.Discriminator; 652a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 653a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 654a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 655a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 656a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 657a34c753fSRafael Auler } 658a34c753fSRafael Auler if (Isa != Row.Isa) { 659a34c753fSRafael Auler Isa = Row.Isa; 660a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 661a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 662a34c753fSRafael Auler } 663a34c753fSRafael Auler if (Row.IsStmt != Flags) { 664a34c753fSRafael Auler Flags = Row.IsStmt; 665a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 666a34c753fSRafael Auler } 667a34c753fSRafael Auler if (Row.BasicBlock) 668a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 669a34c753fSRafael Auler if (Row.PrologueEnd) 670a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 671a34c753fSRafael Auler if (Row.EpilogueBegin) 672a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 673a34c753fSRafael Auler 674a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 675a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 676a34c753fSRafael Auler if (Row.EndSequence) { 677a34c753fSRafael Auler emitEndOfSequence(Address); 678a34c753fSRafael Auler } else { 679a34c753fSRafael Auler if (LastAddress == InvalidAddress) 680a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 681a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 682a34c753fSRafael Auler else 683a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 684a34c753fSRafael Auler 685a34c753fSRafael Auler LastAddress = Address; 686a34c753fSRafael Auler LastLine = Row.Line; 687a34c753fSRafael Auler } 688a34c753fSRafael Auler 689a34c753fSRafael Auler Discriminator = 0; 690a34c753fSRafael Auler } 691a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 692a34c753fSRafael Auler } 693a34c753fSRafael Auler 694a34c753fSRafael Auler // Finish with the end of the sequence. 695a34c753fSRafael Auler if (LastAddress != InvalidAddress) 696a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 697a34c753fSRafael Auler } 698a34c753fSRafael Auler 699a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 700a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 701a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 702a34c753fSRafael Auler static inline void emitDwarfLineTable( 703a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 704a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 705a34c753fSRafael Auler unsigned FileNum = 1; 706a34c753fSRafael Auler unsigned LastLine = 1; 707a34c753fSRafael Auler unsigned Column = 0; 708a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 709a34c753fSRafael Auler unsigned Isa = 0; 710a34c753fSRafael Auler unsigned Discriminator = 0; 711a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 712a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 713a34c753fSRafael Auler 714a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 715a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 716a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 717a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 718a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 719a34c753fSRafael Auler FileNum = 1; 720a34c753fSRafael Auler LastLine = 1; 721a34c753fSRafael Auler Column = 0; 722a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 723a34c753fSRafael Auler Isa = 0; 724a34c753fSRafael Auler Discriminator = 0; 725a34c753fSRafael Auler LastLabel = nullptr; 726a34c753fSRafael Auler continue; 727a34c753fSRafael Auler } 728a34c753fSRafael Auler 729a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 730a34c753fSRafael Auler 731a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 732a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 733a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 734a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 735a34c753fSRafael Auler } 736a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 737a34c753fSRafael Auler Column = LineEntry.getColumn(); 738a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 739a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 740a34c753fSRafael Auler } 741a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 742a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 743a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 744a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 745a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 746a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 747a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 748a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 749a34c753fSRafael Auler } 750a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 751a34c753fSRafael Auler Isa = LineEntry.getIsa(); 752a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 753a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 754a34c753fSRafael Auler } 755a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 756a34c753fSRafael Auler Flags = LineEntry.getFlags(); 757a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 758a34c753fSRafael Auler } 759a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 760a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 761a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 762a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 763a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 764a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 765a34c753fSRafael Auler 766a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 767a34c753fSRafael Auler 768a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 769a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 770a34c753fSRafael Auler // Label and the current Label. 771a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 772a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 773a34c753fSRafael Auler Discriminator = 0; 774a34c753fSRafael Auler LastLine = LineEntry.getLine(); 775a34c753fSRafael Auler LastLabel = Label; 776a34c753fSRafael Auler } 777a34c753fSRafael Auler 778a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 779a34c753fSRafael Auler } 780a34c753fSRafael Auler 781a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 782b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 783b73c87bcSMaksim Panchenko BinaryContext &BC) const { 784a34c753fSRafael Auler if (!RawData.empty()) { 785a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 786a34c753fSRafael Auler InputSequences.empty() && 787a34c753fSRafael Auler "cannot combine raw data with new line entries"); 788a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 789a34c753fSRafael Auler MCOS->emitBytes(RawData); 790a34c753fSRafael Auler 791b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 792b73c87bcSMaksim Panchenko // 793b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 794b73c87bcSMaksim Panchenko // without relocations. 795b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 796b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 797b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 798b73c87bcSMaksim Panchenko 799a34c753fSRafael Auler return; 800a34c753fSRafael Auler } 801a34c753fSRafael Auler 802a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 803a34c753fSRafael Auler 804a34c753fSRafael Auler // Put out the line tables. 805a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 806a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 807a34c753fSRafael Auler 808a34c753fSRafael Auler // Emit line tables for the original code. 809a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 810a34c753fSRafael Auler 811a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 812a34c753fSRafael Auler // of this section (that was used in a previous expression). 813a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 814a34c753fSRafael Auler } 815a34c753fSRafael Auler 816a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 817a34c753fSRafael Auler MCAssembler &Assembler = 818a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 819a34c753fSRafael Auler 820a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 821a34c753fSRafael Auler 822a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 823a34c753fSRafael Auler 824a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 825a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 826a34c753fSRafael Auler if (LineTables.empty()) 827a34c753fSRafael Auler return; 828a34c753fSRafael Auler 829a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 830a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 831a34c753fSRafael Auler if (BC.Ctx->getDwarfVersion() >= 5) 832a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 833a34c753fSRafael Auler 834a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 835a34c753fSRafael Auler Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); 836a34c753fSRafael Auler 837a34c753fSRafael Auler // Handle the rest of the Compile Units. 838a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 839b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 840a34c753fSRafael Auler } 841a34c753fSRafael Auler } 842a34c753fSRafael Auler 843a34c753fSRafael Auler } // namespace bolt 844a34c753fSRafael Auler } // namespace llvm 845