12f09f445SMaksim 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 // 92f09f445SMaksim Panchenko // This file implements functions and classes for handling debug info. 102f09f445SMaksim 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> 261c2f4bbeSAlexander Yermolovich #include <unordered_map> 27a34c753fSRafael Auler 28a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info" 29a34c753fSRafael Auler 30a34c753fSRafael Auler namespace opts { 31a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity; 321c2f4bbeSAlexander Yermolovich } // namespace opts 33a34c753fSRafael Auler 34a34c753fSRafael Auler namespace llvm { 35a34c753fSRafael Auler namespace bolt { 36a34c753fSRafael Auler 37a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 38a34c753fSRafael Auler 39a34c753fSRafael Auler namespace { 40a34c753fSRafael Auler 411c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED 421c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) { 431c2f4bbeSAlexander Yermolovich for (uint32_t I = 0, Size = S.size(); I < Size; ++I) { 441c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr(S[I]); 451c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr((int8_t)S[I]); 461c2f4bbeSAlexander Yermolovich } 471c2f4bbeSAlexander Yermolovich errs() << "\n"; 481c2f4bbeSAlexander Yermolovich } 491c2f4bbeSAlexander Yermolovich 50a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size). 51a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of 52a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address). 53a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes. 54a34c753fSRafael Auler // Returns the number of written bytes. 5540c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream, 56a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges, 57a34c753fSRafael Auler const bool WriteRelativeRanges = false) { 58a34c753fSRafael Auler for (const DebugAddressRange &Range : AddressRanges) { 59a34c753fSRafael Auler support::endian::write(Stream, Range.LowPC, support::little); 60a34c753fSRafael Auler support::endian::write( 61a34c753fSRafael Auler Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 62a34c753fSRafael Auler support::little); 63a34c753fSRafael Auler } 64a34c753fSRafael Auler // Finish with 0 entries. 65a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 66a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 67a34c753fSRafael Auler return AddressRanges.size() * 16 + 16; 68a34c753fSRafael Auler } 69a34c753fSRafael Auler 70a34c753fSRafael Auler } // namespace 71a34c753fSRafael Auler 72a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() { 73a34c753fSRafael Auler RangesBuffer = std::make_unique<DebugBufferVector>(); 74a34c753fSRafael Auler RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 75a34c753fSRafael Auler 76a34c753fSRafael Auler // Add an empty range as the first entry; 77a34c753fSRafael Auler SectionOffset += 78a34c753fSRafael Auler writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 79a34c753fSRafael Auler } 80a34c753fSRafael Auler 81a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges( 82a34c753fSRafael Auler DebugAddressRangesVector &&Ranges, 83a34c753fSRafael Auler std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 84a34c753fSRafael Auler if (Ranges.empty()) 85a34c753fSRafael Auler return getEmptyRangesOffset(); 86a34c753fSRafael Auler 87a34c753fSRafael Auler const auto RI = CachedRanges.find(Ranges); 88a34c753fSRafael Auler if (RI != CachedRanges.end()) 89a34c753fSRafael Auler return RI->second; 90a34c753fSRafael Auler 91a34c753fSRafael Auler const uint64_t EntryOffset = addRanges(Ranges); 92a34c753fSRafael Auler CachedRanges.emplace(std::move(Ranges), EntryOffset); 93a34c753fSRafael Auler 94a34c753fSRafael Auler return EntryOffset; 95a34c753fSRafael Auler } 96a34c753fSRafael Auler 97a34c753fSRafael Auler uint64_t 98a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) { 99a34c753fSRafael Auler if (Ranges.empty()) 100a34c753fSRafael Auler return getEmptyRangesOffset(); 101a34c753fSRafael Auler 102a34c753fSRafael Auler // Reading the SectionOffset and updating it should be atomic to guarantee 103a34c753fSRafael Auler // unique and correct offsets in patches. 104a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 105a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 106a34c753fSRafael Auler SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges); 107a34c753fSRafael Auler 108a34c753fSRafael Auler return EntryOffset; 109a34c753fSRafael Auler } 110a34c753fSRafael Auler 111a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() { 112a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 113a34c753fSRafael Auler return SectionOffset; 114a34c753fSRafael Auler } 115a34c753fSRafael Auler 116a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 117a34c753fSRafael Auler DebugAddressRangesVector &&Ranges) { 118a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 119a34c753fSRafael Auler CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 120a34c753fSRafael Auler } 121a34c753fSRafael Auler 122a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection( 1231c2f4bbeSAlexander Yermolovich raw_svector_ostream &RangesStream, 1241c2f4bbeSAlexander Yermolovich const std::unordered_map<uint32_t, uint32_t> CUMap) const { 125a34c753fSRafael Auler // For reference on the format of the .debug_aranges section, see the DWARF4 126a34c753fSRafael Auler // specification, section 6.1.4 Lookup by Address 127a34c753fSRafael Auler // http://www.dwarfstd.org/doc/DWARF4.pdf 128a34c753fSRafael Auler for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 129a34c753fSRafael Auler const uint64_t Offset = CUOffsetAddressRangesPair.first; 130a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges = 131a34c753fSRafael Auler CUOffsetAddressRangesPair.second; 132a34c753fSRafael Auler 133a34c753fSRafael Auler // Emit header. 134a34c753fSRafael Auler 135a34c753fSRafael Auler // Size of this set: 8 (size of the header) + 4 (padding after header) 136a34c753fSRafael Auler // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 137a34c753fSRafael Auler // pair of uint64_t's for the terminating, zero-length range. 138a34c753fSRafael Auler // Does not include size field itself. 139a34c753fSRafael Auler uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 140a34c753fSRafael Auler 141a34c753fSRafael Auler // Header field #1: set size. 142a34c753fSRafael Auler support::endian::write(RangesStream, Size, support::little); 143a34c753fSRafael Auler 144a34c753fSRafael Auler // Header field #2: version number, 2 as per the specification. 145a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint16_t>(2), 146a34c753fSRafael Auler support::little); 147a34c753fSRafael Auler 1481c2f4bbeSAlexander Yermolovich assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map"); 149a34c753fSRafael Auler // Header field #3: debug info offset of the correspondent compile unit. 1501c2f4bbeSAlexander Yermolovich support::endian::write(RangesStream, 1511c2f4bbeSAlexander Yermolovich static_cast<uint32_t>(CUMap.find(Offset)->second), 152a34c753fSRafael Auler support::little); 153a34c753fSRafael Auler 154a34c753fSRafael Auler // Header field #4: address size. 155a34c753fSRafael Auler // 8 since we only write ELF64 binaries for now. 156a34c753fSRafael Auler RangesStream << char(8); 157a34c753fSRafael Auler 158a34c753fSRafael Auler // Header field #5: segment size of target architecture. 159a34c753fSRafael Auler RangesStream << char(0); 160a34c753fSRafael Auler 161a34c753fSRafael Auler // Padding before address table - 4 bytes in the 64-bit-pointer case. 162a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint32_t>(0), 163a34c753fSRafael Auler support::little); 164a34c753fSRafael Auler 165a34c753fSRafael Auler writeAddressRanges(RangesStream, AddressRanges, true); 166a34c753fSRafael Auler } 167a34c753fSRafael Auler } 168a34c753fSRafael Auler 169a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; } 170a34c753fSRafael Auler 171a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() { 172a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 173a34c753fSRafael Auler indexToAdddessEnd()); 174a34c753fSRafael Auler // Sorting address in increasing order of indices. 175a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 176a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 177a34c753fSRafael Auler return A.first < B.first; 178a34c753fSRafael Auler }); 179a34c753fSRafael Auler for (auto &Pair : SortedMap) 180a34c753fSRafael Auler dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 181a34c753fSRafael Auler } 182a34c753fSRafael Auler uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, 183a34c753fSRafael Auler uint64_t DWOId) { 184e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 185a34c753fSRafael Auler if (!AddressMaps.count(DWOId)) 186a34c753fSRafael Auler AddressMaps[DWOId] = AddressForDWOCU(); 187a34c753fSRafael Auler 188a34c753fSRafael Auler AddressForDWOCU &Map = AddressMaps[DWOId]; 189a34c753fSRafael Auler auto Entry = Map.find(Address); 190a34c753fSRafael Auler if (Entry == Map.end()) { 191a34c753fSRafael Auler auto Index = Map.getNextIndex(); 192a34c753fSRafael Auler Entry = Map.insert(Address, Index).first; 193a34c753fSRafael Auler } 194a34c753fSRafael Auler return Entry->second; 195a34c753fSRafael Auler } 196a34c753fSRafael Auler 197a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 198a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update 199a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 200a34c753fSRafael Auler // update AddressToIndex and IndexToAddress 201a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 202a34c753fSRafael Auler uint64_t DWOId) { 203e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 204a34c753fSRafael Auler AddressForDWOCU &Map = AddressMaps[DWOId]; 205a34c753fSRafael Auler auto Entry = Map.find(Address); 206a34c753fSRafael Auler if (Entry != Map.end()) { 207a34c753fSRafael Auler if (Entry->second > Index) 208a34c753fSRafael Auler Map.updateAddressToIndex(Address, Index); 209a34c753fSRafael Auler Map.updateIndexToAddrss(Address, Index); 2103652483cSRafael Auler } else { 211a34c753fSRafael Auler Map.insert(Address, Index); 212a34c753fSRafael Auler } 2133652483cSRafael Auler } 214a34c753fSRafael Auler 215a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() { 216a34c753fSRafael Auler // Need to layout all sections within .debug_addr 217a34c753fSRafael Auler // Within each section sort Address by index. 218a34c753fSRafael Auler AddressSectionBuffer Buffer; 219a34c753fSRafael Auler raw_svector_ostream AddressStream(Buffer); 220a34c753fSRafael Auler for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 221a34c753fSRafael Auler Optional<uint64_t> DWOId = CU->getDWOId(); 222a34c753fSRafael Auler // Handling the case wehre debug information is a mix of Debug fission and 223a34c753fSRafael Auler // monolitic. 224a34c753fSRafael Auler if (!DWOId) 225a34c753fSRafael Auler continue; 226a34c753fSRafael Auler auto AM = AddressMaps.find(*DWOId); 227a34c753fSRafael Auler // Adding to map even if it did not contribute to .debug_addr. 228a34c753fSRafael Auler // The Skeleton CU will still have DW_AT_GNU_addr_base. 229a34c753fSRafael Auler DWOIdToOffsetMap[*DWOId] = Buffer.size(); 230a34c753fSRafael Auler // If does not exist this CUs DWO section didn't contribute to .debug_addr. 231a34c753fSRafael Auler if (AM == AddressMaps.end()) 232a34c753fSRafael Auler continue; 233a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 234a34c753fSRafael Auler AM->second.indexToAdddessEnd()); 235a34c753fSRafael Auler // Sorting address in increasing order of indices. 236a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 237a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 238a34c753fSRafael Auler return A.first < B.first; 239a34c753fSRafael Auler }); 240a34c753fSRafael Auler 241a34c753fSRafael Auler uint8_t AddrSize = CU->getAddressByteSize(); 242a34c753fSRafael Auler uint32_t Counter = 0; 243a34c753fSRafael Auler auto WriteAddress = [&](uint64_t Address) -> void { 244a34c753fSRafael Auler ++Counter; 245a34c753fSRafael Auler switch (AddrSize) { 246a34c753fSRafael Auler default: 247a34c753fSRafael Auler assert(false && "Address Size is invalid."); 248a34c753fSRafael Auler break; 249a34c753fSRafael Auler case 4: 250a34c753fSRafael Auler support::endian::write(AddressStream, static_cast<uint32_t>(Address), 251a34c753fSRafael Auler support::little); 252a34c753fSRafael Auler break; 253a34c753fSRafael Auler case 8: 254a34c753fSRafael Auler support::endian::write(AddressStream, Address, support::little); 255a34c753fSRafael Auler break; 256a34c753fSRafael Auler } 257a34c753fSRafael Auler }; 258a34c753fSRafael Auler 259a34c753fSRafael Auler for (const IndexAddressPair &Val : SortedMap) { 260a34c753fSRafael Auler while (Val.first > Counter) 261a34c753fSRafael Auler WriteAddress(0); 262a34c753fSRafael Auler WriteAddress(Val.second); 263a34c753fSRafael Auler } 264a34c753fSRafael Auler } 265a34c753fSRafael Auler 266a34c753fSRafael Auler return Buffer; 267a34c753fSRafael Auler } 268a34c753fSRafael Auler 269a34c753fSRafael Auler uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) { 270a34c753fSRafael Auler auto Iter = DWOIdToOffsetMap.find(DWOId); 271a34c753fSRafael Auler assert(Iter != DWOIdToOffsetMap.end() && 272a34c753fSRafael Auler "Offset in to.debug_addr was not found for DWO ID."); 273a34c753fSRafael Auler return Iter->second; 274a34c753fSRafael Auler } 275a34c753fSRafael Auler 276a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) { 277a34c753fSRafael Auler LocBuffer = std::make_unique<DebugBufferVector>(); 278a34c753fSRafael Auler LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 279a34c753fSRafael Auler } 280a34c753fSRafael Auler 281a34c753fSRafael Auler void DebugLocWriter::addList(uint64_t AttrOffset, 282a34c753fSRafael Auler DebugLocationsVector &&LocList) { 283a34c753fSRafael Auler if (LocList.empty()) { 284a34c753fSRafael Auler EmptyAttrLists.push_back(AttrOffset); 285a34c753fSRafael Auler return; 286a34c753fSRafael Auler } 287a34c753fSRafael Auler // Since there is a separate DebugLocWriter for each thread, 288a34c753fSRafael Auler // we don't need a lock to read the SectionOffset and update it. 289a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 290a34c753fSRafael Auler 291a34c753fSRafael Auler for (const DebugLocationEntry &Entry : LocList) { 292a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 293a34c753fSRafael Auler support::little); 294a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 295a34c753fSRafael Auler support::little); 296a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 297a34c753fSRafael Auler support::little); 298a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 299a34c753fSRafael Auler Entry.Expr.size()); 300a34c753fSRafael Auler SectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 301a34c753fSRafael Auler } 302a34c753fSRafael Auler LocStream->write_zeros(16); 303a34c753fSRafael Auler SectionOffset += 16; 304a34c753fSRafael Auler LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 305a34c753fSRafael Auler } 306a34c753fSRafael Auler 307a34c753fSRafael Auler void DebugLoclistWriter::addList(uint64_t AttrOffset, 308a34c753fSRafael Auler DebugLocationsVector &&LocList) { 309a34c753fSRafael Auler Patches.push_back({AttrOffset, std::move(LocList)}); 310a34c753fSRafael Auler } 311a34c753fSRafael Auler 312a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 313a34c753fSRafael Auler return std::move(LocBuffer); 314a34c753fSRafael Auler } 315a34c753fSRafael Auler 316a34c753fSRafael Auler // DWARF 4: 2.6.2 317a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset, 318a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 319a34c753fSRafael Auler for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) { 320a34c753fSRafael Auler uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset; 321a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset, 322a34c753fSRafael Auler Offset); 323a34c753fSRafael Auler } 324a34c753fSRafael Auler 325a34c753fSRafael Auler for (uint64_t DebugInfoAttrOffset : EmptyAttrLists) 326a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset, 327a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 328a34c753fSRafael Auler } 329a34c753fSRafael Auler 330a34c753fSRafael Auler void DebugLoclistWriter::finalize(uint64_t SectionOffset, 331a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 332a34c753fSRafael Auler for (LocPatch &Patch : Patches) { 333a34c753fSRafael Auler if (Patch.LocList.empty()) { 334a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, 335a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 336a34c753fSRafael Auler continue; 337a34c753fSRafael Auler } 338a34c753fSRafael Auler const uint32_t EntryOffset = LocBuffer->size(); 339a34c753fSRafael Auler for (const DebugLocationEntry &Entry : Patch.LocList) { 340a34c753fSRafael Auler support::endian::write(*LocStream, 341a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 342a34c753fSRafael Auler support::little); 343a34c753fSRafael Auler uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId); 344a34c753fSRafael Auler encodeULEB128(Index, *LocStream); 345a34c753fSRafael Auler 346a34c753fSRafael Auler // TODO: Support DWARF5 347a34c753fSRafael Auler support::endian::write(*LocStream, 348a34c753fSRafael Auler static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 349a34c753fSRafael Auler support::little); 350a34c753fSRafael Auler support::endian::write(*LocStream, 351a34c753fSRafael Auler static_cast<uint16_t>(Entry.Expr.size()), 352a34c753fSRafael Auler support::little); 353a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 354a34c753fSRafael Auler Entry.Expr.size()); 355a34c753fSRafael Auler } 356a34c753fSRafael Auler support::endian::write(*LocStream, 357a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 358a34c753fSRafael Auler support::little); 359a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); 360a34c753fSRafael Auler clearList(Patch.LocList); 361a34c753fSRafael Auler } 362a34c753fSRafael Auler clearList(Patches); 363a34c753fSRafael Auler } 364a34c753fSRafael Auler 365a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 366a34c753fSRafael Auler 3671c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 3681c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 3691c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 370*ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 371a34c753fSRafael Auler } 372a34c753fSRafael Auler 3731c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 3741c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 3751c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 3761c2f4bbeSAlexander Yermolovich auto RetVal = DestinationLabels.insert(Offset); 3771c2f4bbeSAlexander Yermolovich if (!RetVal.second) 3781c2f4bbeSAlexander Yermolovich return; 3791c2f4bbeSAlexander Yermolovich 380*ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 381a34c753fSRafael Auler } 382a34c753fSRafael Auler 3831c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 3841c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset, 3851c2f4bbeSAlexander Yermolovich uint32_t OldValueSize, 3861c2f4bbeSAlexander Yermolovich dwarf::Form Form) { 3871c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 3881c2f4bbeSAlexander Yermolovich DestinationOffset -= DWPUnitOffset; 3891c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 390*ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back( 391*ea6c8b01SAlexander Yermolovich new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 3921c2f4bbeSAlexander Yermolovich } 3931c2f4bbeSAlexander Yermolovich 3941c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 3951c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 3961c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 3971c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 3981c2f4bbeSAlexander Yermolovich DebugPatches.emplace_back( 399*ea6c8b01SAlexander Yermolovich new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 4001c2f4bbeSAlexander Yermolovich } 4011c2f4bbeSAlexander Yermolovich 4021c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 4031c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4041c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 405*ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 4061c2f4bbeSAlexander Yermolovich } 4071c2f4bbeSAlexander Yermolovich 4081c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 4091c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 4101c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4111c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 4121c2f4bbeSAlexander Yermolovich if (OldValueSize == 4) 413*ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 4141c2f4bbeSAlexander Yermolovich else 415*ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 4161c2f4bbeSAlexander Yermolovich } 4171c2f4bbeSAlexander Yermolovich 4181c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 4191c2f4bbeSAlexander Yermolovich std::string &&NewValue, 4201c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 4211c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(NewValue)); 4221c2f4bbeSAlexander Yermolovich } 4231c2f4bbeSAlexander Yermolovich 4241c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 4251c2f4bbeSAlexander Yermolovich auto Str = std::string(1, Value); 4261c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Str)); 4271c2f4bbeSAlexander Yermolovich } 4281c2f4bbeSAlexander Yermolovich 4291c2f4bbeSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 430a34c753fSRafael Auler std::string LE64(ByteSize, 0); 431a34c753fSRafael Auler for (size_t I = 0; I < ByteSize; ++I) { 432a34c753fSRafael Auler LE64[I] = NewValue & 0xff; 433a34c753fSRafael Auler NewValue >>= 8; 434a34c753fSRafael Auler } 4351c2f4bbeSAlexander Yermolovich return LE64; 436a34c753fSRafael Auler } 437a34c753fSRafael Auler 4381c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 4391c2f4bbeSAlexander Yermolovich size_t ByteSize) { 4401c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 4411c2f4bbeSAlexander Yermolovich } 4421c2f4bbeSAlexander Yermolovich 4431c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 4441c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 445a34c753fSRafael Auler std::string Buff; 446a34c753fSRafael Auler raw_string_ostream OS(Buff); 4471c2f4bbeSAlexander Yermolovich encodeULEB128(Value, OS, OldValueSize); 448a34c753fSRafael Auler 4491c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Buff)); 450a34c753fSRafael Auler } 451a34c753fSRafael Auler 4521c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 453a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 454a34c753fSRafael Auler } 455a34c753fSRafael Auler 4561c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 4571c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 458a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 459a34c753fSRafael Auler } 460a34c753fSRafael Auler 4611c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 4621c2f4bbeSAlexander Yermolovich std::string BinaryContentsStr = std::string(BinaryContents); 463a34c753fSRafael Auler for (const auto &Patch : Patches) { 4641c2f4bbeSAlexander Yermolovich uint32_t Offset = Patch.first; 465a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 466a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 467a34c753fSRafael Auler "Applied patch runs over binary size."); 468a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 4691c2f4bbeSAlexander Yermolovich BinaryContentsStr[Offset + I] = ByteSequence[I]; 470a34c753fSRafael Auler } 471a34c753fSRafael Auler } 4721c2f4bbeSAlexander Yermolovich return BinaryContentsStr; 4731c2f4bbeSAlexander Yermolovich } 4741c2f4bbeSAlexander Yermolovich 4751c2f4bbeSAlexander Yermolovich std::unordered_map<uint32_t, uint32_t> 4761c2f4bbeSAlexander Yermolovich DebugInfoBinaryPatcher::computeNewOffsets() { 4771c2f4bbeSAlexander Yermolovich std::unordered_map<uint32_t, uint32_t> CUMap; 478*ea6c8b01SAlexander Yermolovich std::sort(DebugPatches.begin(), DebugPatches.end(), 479*ea6c8b01SAlexander Yermolovich [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) { 4801c2f4bbeSAlexander Yermolovich return V1.get()->Offset < V2.get()->Offset; 4811c2f4bbeSAlexander Yermolovich }); 4821c2f4bbeSAlexander Yermolovich 4831c2f4bbeSAlexander Yermolovich // Calculating changes in .debug_info size from Patches to build a map of old 4841c2f4bbeSAlexander Yermolovich // to updated reference destination offsets. 485*ea6c8b01SAlexander Yermolovich for (UniquePatchPtrType &PatchBase : DebugPatches) { 4861c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 4871c2f4bbeSAlexander Yermolovich switch (P->Kind) { 4881c2f4bbeSAlexander Yermolovich default: 4891c2f4bbeSAlexander Yermolovich continue; 4901c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 4911c2f4bbeSAlexander Yermolovich ChangeInSize -= 4; 4921c2f4bbeSAlexander Yermolovich break; 4931c2f4bbeSAlexander Yermolovich } 4941c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 4951c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *DPV = 4961c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 4971c2f4bbeSAlexander Yermolovich std::string Temp; 4981c2f4bbeSAlexander Yermolovich raw_string_ostream OS(Temp); 4991c2f4bbeSAlexander Yermolovich encodeULEB128(DPV->Value, OS); 5001c2f4bbeSAlexander Yermolovich ChangeInSize += Temp.size() - DPV->OldValueSize; 5011c2f4bbeSAlexander Yermolovich break; 5021c2f4bbeSAlexander Yermolovich } 5031c2f4bbeSAlexander Yermolovich case DebugPatchKind::DestinationReferenceLabel: { 5041c2f4bbeSAlexander Yermolovich DestinationReferenceLabel *DRL = 5051c2f4bbeSAlexander Yermolovich reinterpret_cast<DestinationReferenceLabel *>(P); 5061c2f4bbeSAlexander Yermolovich OldToNewOffset[DRL->Offset] = DRL->Offset + ChangeInSize; 5071c2f4bbeSAlexander Yermolovich break; 5081c2f4bbeSAlexander Yermolovich } 5091c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 5101c2f4bbeSAlexander Yermolovich // This doesn't look to be a common case, so will always encode as 4 bytes 5111c2f4bbeSAlexander Yermolovich // to reduce algorithmic complexity. 5121c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 5131c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.IndirectRelative) { 5141c2f4bbeSAlexander Yermolovich ChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 5151c2f4bbeSAlexander Yermolovich assert(RDP->PatchInfo.OldValueSize <= 4 && 5161c2f4bbeSAlexander Yermolovich "Variable encoding reference greater than 4 bytes."); 5171c2f4bbeSAlexander Yermolovich } 5181c2f4bbeSAlexander Yermolovich break; 5191c2f4bbeSAlexander Yermolovich } 5201c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 5211c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 5221c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 5231c2f4bbeSAlexander Yermolovich uint32_t CUOffset = BaseLabel->Offset; 5241c2f4bbeSAlexander Yermolovich uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 5251c2f4bbeSAlexander Yermolovich CUMap[CUOffset] = CUOffsetUpdate; 5261c2f4bbeSAlexander Yermolovich } 5271c2f4bbeSAlexander Yermolovich } 5281c2f4bbeSAlexander Yermolovich } 5291c2f4bbeSAlexander Yermolovich return CUMap; 5301c2f4bbeSAlexander Yermolovich } 5311c2f4bbeSAlexander Yermolovich 5321c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 5331c2f4bbeSAlexander Yermolovich std::string NewBinaryContents; 5341c2f4bbeSAlexander Yermolovich NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 5351c2f4bbeSAlexander Yermolovich uint32_t StartOffset = 0; 5361c2f4bbeSAlexander Yermolovich uint32_t DwarfUnitBaseOffset = 0; 5371c2f4bbeSAlexander Yermolovich uint32_t OldValueSize = 0; 5381c2f4bbeSAlexander Yermolovich uint32_t Offset = 0; 5391c2f4bbeSAlexander Yermolovich std::string ByteSequence; 5401c2f4bbeSAlexander Yermolovich std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 5411c2f4bbeSAlexander Yermolovich // Wasting one entry to avoid checks for first. 5421c2f4bbeSAlexander Yermolovich LengthPatches.push_back({0, 0}); 5431c2f4bbeSAlexander Yermolovich 5441c2f4bbeSAlexander Yermolovich // Applying all the patches replacing current entry. 5451c2f4bbeSAlexander Yermolovich // This might change the size of .debug_info section. 546*ea6c8b01SAlexander Yermolovich for (const UniquePatchPtrType &PatchBase : DebugPatches) { 5471c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 5481c2f4bbeSAlexander Yermolovich switch (P->Kind) { 5491c2f4bbeSAlexander Yermolovich default: 5501c2f4bbeSAlexander Yermolovich continue; 5511c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 5521c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 5531c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset = RDP->DestinationOffset; 5541c2f4bbeSAlexander Yermolovich assert(OldToNewOffset.count(DestinationOffset) && 5551c2f4bbeSAlexander Yermolovich "Destination Offset for reference not updated."); 5561c2f4bbeSAlexander Yermolovich uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 5571c2f4bbeSAlexander Yermolovich Offset = RDP->Offset; 5581c2f4bbeSAlexander Yermolovich OldValueSize = RDP->PatchInfo.OldValueSize; 5591c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.DirectRelative) { 5601c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 5611c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 5621c2f4bbeSAlexander Yermolovich // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 5631c2f4bbeSAlexander Yermolovich // and overflow if later debug information grows. 5641c2f4bbeSAlexander Yermolovich if (ByteSequence.size() > OldValueSize) 5651c2f4bbeSAlexander Yermolovich errs() << "BOLT-ERROR: Relative reference of size " 5661c2f4bbeSAlexander Yermolovich << Twine::utohexstr(OldValueSize) 5671c2f4bbeSAlexander Yermolovich << " overflows with the new encoding.\n"; 5681c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.DirectAbsolute) { 5691c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 5701c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.IndirectRelative) { 5711c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 5721c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 5731c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 5741c2f4bbeSAlexander Yermolovich encodeULEB128(UpdatedOffset, OS, 4); 5751c2f4bbeSAlexander Yermolovich } else { 5761c2f4bbeSAlexander Yermolovich llvm_unreachable("Invalid Reference form."); 5771c2f4bbeSAlexander Yermolovich } 5781c2f4bbeSAlexander Yermolovich break; 5791c2f4bbeSAlexander Yermolovich } 5801c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue32: { 5811c2f4bbeSAlexander Yermolovich DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 5821c2f4bbeSAlexander Yermolovich Offset = P32->Offset; 5831c2f4bbeSAlexander Yermolovich OldValueSize = 4; 5841c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P32->Value); 5851c2f4bbeSAlexander Yermolovich break; 5861c2f4bbeSAlexander Yermolovich } 5871c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 5881c2f4bbeSAlexander Yermolovich DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 5891c2f4bbeSAlexander Yermolovich Offset = P64to32->Offset; 5901c2f4bbeSAlexander Yermolovich OldValueSize = 8; 5911c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P64to32->Value); 5921c2f4bbeSAlexander Yermolovich break; 5931c2f4bbeSAlexander Yermolovich } 5941c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 5951c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *PV = 5961c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 5971c2f4bbeSAlexander Yermolovich Offset = PV->Offset; 5981c2f4bbeSAlexander Yermolovich OldValueSize = PV->OldValueSize; 5991c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 6001c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 6011c2f4bbeSAlexander Yermolovich encodeULEB128(PV->Value, OS); 6021c2f4bbeSAlexander Yermolovich break; 6031c2f4bbeSAlexander Yermolovich } 6041c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64: { 6051c2f4bbeSAlexander Yermolovich DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 6061c2f4bbeSAlexander Yermolovich Offset = P64->Offset; 6071c2f4bbeSAlexander Yermolovich OldValueSize = 8; 6081c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(8, P64->Value); 6091c2f4bbeSAlexander Yermolovich break; 6101c2f4bbeSAlexander Yermolovich } 6111c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 6121c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 6131c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 6141c2f4bbeSAlexander Yermolovich Offset = BaseLabel->Offset; 6151c2f4bbeSAlexander Yermolovich OldValueSize = 0; 6161c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 6171c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 6181c2f4bbeSAlexander Yermolovich // Length to copy between last patch entry and next compile unit. 6191c2f4bbeSAlexander Yermolovich uint32_t RemainingLength = Offset - StartOffset; 6201c2f4bbeSAlexander Yermolovich uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 6211c2f4bbeSAlexander Yermolovich DwarfUnitBaseOffset = NewCUOffset; 6221c2f4bbeSAlexander Yermolovich // Length of previous CU = This CU Offset - sizeof(length) - last CU 6231c2f4bbeSAlexander Yermolovich // Offset. 6241c2f4bbeSAlexander Yermolovich Patch.second = NewCUOffset - 4 - Patch.first; 6251c2f4bbeSAlexander Yermolovich LengthPatches.push_back({NewCUOffset, 0}); 6261c2f4bbeSAlexander Yermolovich break; 6271c2f4bbeSAlexander Yermolovich } 6281c2f4bbeSAlexander Yermolovich } 6291c2f4bbeSAlexander Yermolovich 6301c2f4bbeSAlexander Yermolovich assert(Offset + ByteSequence.size() <= BinaryContents.size() && 6311c2f4bbeSAlexander Yermolovich "Applied patch runs over binary size."); 6321c2f4bbeSAlexander Yermolovich uint32_t Length = Offset - StartOffset; 6331c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 6341c2f4bbeSAlexander Yermolovich Length); 6351c2f4bbeSAlexander Yermolovich NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 6361c2f4bbeSAlexander Yermolovich StartOffset = Offset + OldValueSize; 6371c2f4bbeSAlexander Yermolovich } 6381c2f4bbeSAlexander Yermolovich uint32_t Length = BinaryContents.size() - StartOffset; 6391c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 6401c2f4bbeSAlexander Yermolovich Length); 6411c2f4bbeSAlexander Yermolovich DebugPatches.clear(); 6421c2f4bbeSAlexander Yermolovich 6431c2f4bbeSAlexander Yermolovich // Patching lengths of CUs 6441c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 6451c2f4bbeSAlexander Yermolovich Patch.second = NewBinaryContents.size() - 4 - Patch.first; 6461c2f4bbeSAlexander Yermolovich for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 6471c2f4bbeSAlexander Yermolovich const auto &Patch = LengthPatches[J]; 6481c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, Patch.second); 6491c2f4bbeSAlexander Yermolovich Offset = Patch.first; 6501c2f4bbeSAlexander Yermolovich for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 6511c2f4bbeSAlexander Yermolovich NewBinaryContents[Offset + I] = ByteSequence[I]; 6521c2f4bbeSAlexander Yermolovich } 6531c2f4bbeSAlexander Yermolovich 6541c2f4bbeSAlexander Yermolovich return NewBinaryContents; 655a34c753fSRafael Auler } 656a34c753fSRafael Auler 657a34c753fSRafael Auler void DebugStrWriter::create() { 658a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 659a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 660a34c753fSRafael Auler } 661a34c753fSRafael Auler 662a34c753fSRafael Auler void DebugStrWriter::initialize() { 663a34c753fSRafael Auler auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); 664a34c753fSRafael Auler (*StrStream) << StrSection; 665a34c753fSRafael Auler } 666a34c753fSRafael Auler 667a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 668e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 669a34c753fSRafael Auler if (StrBuffer->empty()) 670a34c753fSRafael Auler initialize(); 671a34c753fSRafael Auler auto Offset = StrBuffer->size(); 672a34c753fSRafael Auler (*StrStream) << Str; 673a34c753fSRafael Auler StrStream->write_zeros(1); 674a34c753fSRafael Auler return Offset; 675a34c753fSRafael Auler } 676a34c753fSRafael Auler 677a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 678a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 679a34c753fSRafael Auler if (!Abbrevs) 680a34c753fSRafael Auler return; 681a34c753fSRafael Auler 682a34c753fSRafael Auler // Multiple units may share the same abbreviations. Only add abbreviations 683a34c753fSRafael Auler // for the first unit and reuse them. 684a34c753fSRafael Auler const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset(); 68545f94abcSMaksim Panchenko if (UnitsAbbrevData.find(AbbrevOffset) != UnitsAbbrevData.end()) 686a34c753fSRafael Auler return; 687a34c753fSRafael Auler 68845f94abcSMaksim Panchenko AbbrevData &UnitData = UnitsAbbrevData[AbbrevOffset]; 689a34c753fSRafael Auler UnitData.Buffer = std::make_unique<DebugBufferVector>(); 690a34c753fSRafael Auler UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 691a34c753fSRafael Auler 69245f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 693a34c753fSRafael Auler 694a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 695a34c753fSRafael Auler 696a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 697a34c753fSRafael Auler // contents. 698a34c753fSRafael Auler if (UnitPatches.empty()) { 699a34c753fSRafael Auler StringRef AbbrevSectionContents = 700a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 701a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 702a34c753fSRafael Auler StringRef AbbrevContents; 703a34c753fSRafael Auler 704a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 705a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 706a34c753fSRafael Auler // Handle DWP section contribution. 707a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 708a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 709a34c753fSRafael Auler if (!DWOEntry) 710a34c753fSRafael Auler return; 711a34c753fSRafael Auler 712a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 713a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 714a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 715a34c753fSRafael Auler DWOContrubution->Length); 71645f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 717a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 71845f94abcSMaksim Panchenko 71945f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 72045f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 72145f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 72245f94abcSMaksim Panchenko // the set boundaries. 72345f94abcSMaksim Panchenko // 72445f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 72545f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 72645f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 7271c2f4bbeSAlexander Yermolovich for_each( 72845f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 72945f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 73045f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 73145f94abcSMaksim Panchenko }); 7321c2f4bbeSAlexander Yermolovich sort(AbbrevSetOffsets); 73345f94abcSMaksim Panchenko } 7341c2f4bbeSAlexander Yermolovich auto It = upper_bound(AbbrevSetOffsets, StartOffset); 73545f94abcSMaksim Panchenko const uint64_t EndOffset = 73645f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 737a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 73845f94abcSMaksim Panchenko } else { 73945f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 74045f94abcSMaksim Panchenko // abbreviations for this unit only. 74145f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 742a34c753fSRafael Auler } 743a34c753fSRafael Auler 744a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 745a34c753fSRafael Auler OS << AbbrevContents; 746a34c753fSRafael Auler 747a34c753fSRafael Auler return; 748a34c753fSRafael Auler } 749a34c753fSRafael Auler 750a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 751a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 752a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 753a34c753fSRafael Auler 754a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 755a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 756a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 757a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 758a34c753fSRafael Auler Abbrev.attributes()) { 759a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 760a34c753fSRafael Auler bool Patched = false; 761a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 762a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 763a34c753fSRafael Auler ++I) { 764a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 765a34c753fSRafael Auler continue; 766a34c753fSRafael Auler 767a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 768a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 769a34c753fSRafael Auler Patched = true; 770a34c753fSRafael Auler break; 771a34c753fSRafael Auler } 772a34c753fSRafael Auler if (Patched) 773a34c753fSRafael Auler continue; 774a34c753fSRafael Auler } 775a34c753fSRafael Auler 776a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 777a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 778a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 779a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 780a34c753fSRafael Auler } 781a34c753fSRafael Auler 782a34c753fSRafael Auler encodeULEB128(0, OS); 783a34c753fSRafael Auler encodeULEB128(0, OS); 784a34c753fSRafael Auler } 785a34c753fSRafael Auler encodeULEB128(0, OS); 786a34c753fSRafael Auler } 787a34c753fSRafael Auler 788a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 78945f94abcSMaksim Panchenko if (DWOId) { 79045f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 79145f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 79245f94abcSMaksim Panchenko // set with the CU. 7931417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 7941417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 79545f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 7961417f607SAlexander Yermolovich if (!IsDWP) { 79745f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 79845f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 79945f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 80045f94abcSMaksim Panchenko "Unable to update debug info.\n"; 80145f94abcSMaksim Panchenko exit(1); 80245f94abcSMaksim Panchenko } 80345f94abcSMaksim Panchenko } 80445f94abcSMaksim Panchenko } 80545f94abcSMaksim Panchenko 80645f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 80745f94abcSMaksim Panchenko addUnitAbbreviations(*Context.getDWOCompileUnitForHash(*DWOId)); 80845f94abcSMaksim Panchenko } else { 80945f94abcSMaksim Panchenko // Add abbreviations from compile and type non-DWO units. 81045f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) 81145f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 81245f94abcSMaksim Panchenko } 81345f94abcSMaksim Panchenko 814a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 815a34c753fSRafael Auler 816a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 817a34c753fSRafael Auler uint64_t Size = 0; 81845f94abcSMaksim Panchenko for (const auto &KV : UnitsAbbrevData) { 819a34c753fSRafael Auler const AbbrevData &UnitData = KV.second; 820a34c753fSRafael Auler Size += UnitData.Buffer->size(); 821a34c753fSRafael Auler } 822a34c753fSRafael Auler ReturnBuffer.reserve(Size); 823a34c753fSRafael Auler 824a34c753fSRafael Auler uint64_t Pos = 0; 82545f94abcSMaksim Panchenko for (auto &KV : UnitsAbbrevData) { 826a34c753fSRafael Auler AbbrevData &UnitData = KV.second; 827a34c753fSRafael Auler ReturnBuffer.append(*UnitData.Buffer); 828a34c753fSRafael Auler UnitData.Offset = Pos; 829a34c753fSRafael Auler Pos += UnitData.Buffer->size(); 830a34c753fSRafael Auler 831a34c753fSRafael Auler UnitData.Buffer.reset(); 832a34c753fSRafael Auler UnitData.Stream.reset(); 833a34c753fSRafael Auler } 834a34c753fSRafael Auler 835a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 836a34c753fSRafael Auler } 837a34c753fSRafael Auler 838a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 839a34c753fSRafael Auler MCDwarfLineTableParams Params, 840a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 841a34c753fSRafael Auler int PointerSize) { 842a34c753fSRafael Auler // emit the sequence to set the address 843a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 844a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 845a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 846a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 847a34c753fSRafael Auler 848a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 849a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 850a34c753fSRafael Auler } 851a34c753fSRafael Auler 852a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 853a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 854a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 855a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 856a34c753fSRafael Auler if (InputSequences.empty()) 857a34c753fSRafael Auler return; 858a34c753fSRafael Auler 859a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 860a34c753fSRafael Auler unsigned FileNum = 1; 861a34c753fSRafael Auler unsigned LastLine = 1; 862a34c753fSRafael Auler unsigned Column = 0; 863a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 864a34c753fSRafael Auler unsigned Isa = 0; 865a34c753fSRafael Auler unsigned Discriminator = 0; 866a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 867a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 868a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 869a34c753fSRafael Auler 870a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 871a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 872a34c753fSRafael Auler FileNum = 1; 873a34c753fSRafael Auler LastLine = 1; 874a34c753fSRafael Auler Column = 0; 875a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 876a34c753fSRafael Auler Isa = 0; 877a34c753fSRafael Auler Discriminator = 0; 878a34c753fSRafael Auler LastAddress = InvalidAddress; 879a34c753fSRafael Auler }; 880a34c753fSRafael Auler 881a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 882a34c753fSRafael Auler const uint64_t SequenceStart = 883a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 884a34c753fSRafael Auler 885a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 886a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 887a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 888a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 889a34c753fSRafael Auler } 890a34c753fSRafael Auler 891a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 892a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 893a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 894a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 895a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 896a34c753fSRafael Auler 897a34c753fSRafael Auler if (FileNum != Row.File) { 898a34c753fSRafael Auler FileNum = Row.File; 899a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 900a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 901a34c753fSRafael Auler } 902a34c753fSRafael Auler if (Column != Row.Column) { 903a34c753fSRafael Auler Column = Row.Column; 904a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 905a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 906a34c753fSRafael Auler } 907a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 908a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 909a34c753fSRafael Auler Discriminator = Row.Discriminator; 910a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 911a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 912a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 913a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 914a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 915a34c753fSRafael Auler } 916a34c753fSRafael Auler if (Isa != Row.Isa) { 917a34c753fSRafael Auler Isa = Row.Isa; 918a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 919a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 920a34c753fSRafael Auler } 921a34c753fSRafael Auler if (Row.IsStmt != Flags) { 922a34c753fSRafael Auler Flags = Row.IsStmt; 923a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 924a34c753fSRafael Auler } 925a34c753fSRafael Auler if (Row.BasicBlock) 926a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 927a34c753fSRafael Auler if (Row.PrologueEnd) 928a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 929a34c753fSRafael Auler if (Row.EpilogueBegin) 930a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 931a34c753fSRafael Auler 932a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 933a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 934a34c753fSRafael Auler if (Row.EndSequence) { 935a34c753fSRafael Auler emitEndOfSequence(Address); 936a34c753fSRafael Auler } else { 937a34c753fSRafael Auler if (LastAddress == InvalidAddress) 938a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 939a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 940a34c753fSRafael Auler else 941a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 942a34c753fSRafael Auler 943a34c753fSRafael Auler LastAddress = Address; 944a34c753fSRafael Auler LastLine = Row.Line; 945a34c753fSRafael Auler } 946a34c753fSRafael Auler 947a34c753fSRafael Auler Discriminator = 0; 948a34c753fSRafael Auler } 949a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 950a34c753fSRafael Auler } 951a34c753fSRafael Auler 952a34c753fSRafael Auler // Finish with the end of the sequence. 953a34c753fSRafael Auler if (LastAddress != InvalidAddress) 954a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 955a34c753fSRafael Auler } 956a34c753fSRafael Auler 957a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 958a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 959a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 960a34c753fSRafael Auler static inline void emitDwarfLineTable( 961a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 962a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 963a34c753fSRafael Auler unsigned FileNum = 1; 964a34c753fSRafael Auler unsigned LastLine = 1; 965a34c753fSRafael Auler unsigned Column = 0; 966a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 967a34c753fSRafael Auler unsigned Isa = 0; 968a34c753fSRafael Auler unsigned Discriminator = 0; 969a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 970a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 971a34c753fSRafael Auler 972a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 973a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 974a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 975a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 976a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 977a34c753fSRafael Auler FileNum = 1; 978a34c753fSRafael Auler LastLine = 1; 979a34c753fSRafael Auler Column = 0; 980a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 981a34c753fSRafael Auler Isa = 0; 982a34c753fSRafael Auler Discriminator = 0; 983a34c753fSRafael Auler LastLabel = nullptr; 984a34c753fSRafael Auler continue; 985a34c753fSRafael Auler } 986a34c753fSRafael Auler 987a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 988a34c753fSRafael Auler 989a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 990a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 991a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 992a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 993a34c753fSRafael Auler } 994a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 995a34c753fSRafael Auler Column = LineEntry.getColumn(); 996a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 997a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 998a34c753fSRafael Auler } 999a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 1000a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1001a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 1002a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1003a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1004a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1005a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1006a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1007a34c753fSRafael Auler } 1008a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 1009a34c753fSRafael Auler Isa = LineEntry.getIsa(); 1010a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1011a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1012a34c753fSRafael Auler } 1013a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1014a34c753fSRafael Auler Flags = LineEntry.getFlags(); 1015a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1016a34c753fSRafael Auler } 1017a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1018a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1019a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1020a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1021a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1022a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1023a34c753fSRafael Auler 1024a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 1025a34c753fSRafael Auler 1026a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 1027a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 1028a34c753fSRafael Auler // Label and the current Label. 1029a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1030a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1031a34c753fSRafael Auler Discriminator = 0; 1032a34c753fSRafael Auler LastLine = LineEntry.getLine(); 1033a34c753fSRafael Auler LastLabel = Label; 1034a34c753fSRafael Auler } 1035a34c753fSRafael Auler 1036a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 1037a34c753fSRafael Auler } 1038a34c753fSRafael Auler 1039a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1040b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 1041b73c87bcSMaksim Panchenko BinaryContext &BC) const { 1042a34c753fSRafael Auler if (!RawData.empty()) { 1043a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 1044a34c753fSRafael Auler InputSequences.empty() && 1045a34c753fSRafael Auler "cannot combine raw data with new line entries"); 1046a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 1047a34c753fSRafael Auler MCOS->emitBytes(RawData); 1048a34c753fSRafael Auler 1049b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 1050b73c87bcSMaksim Panchenko // 1051b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1052b73c87bcSMaksim Panchenko // without relocations. 1053b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 1054b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1055b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1056b73c87bcSMaksim Panchenko 1057a34c753fSRafael Auler return; 1058a34c753fSRafael Auler } 1059a34c753fSRafael Auler 1060a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1061a34c753fSRafael Auler 1062a34c753fSRafael Auler // Put out the line tables. 1063a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1064a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1065a34c753fSRafael Auler 1066a34c753fSRafael Auler // Emit line tables for the original code. 1067a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1068a34c753fSRafael Auler 1069a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 1070a34c753fSRafael Auler // of this section (that was used in a previous expression). 1071a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 1072a34c753fSRafael Auler } 1073a34c753fSRafael Auler 1074a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1075a34c753fSRafael Auler MCAssembler &Assembler = 1076a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1077a34c753fSRafael Auler 1078a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1079a34c753fSRafael Auler 1080a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 1081a34c753fSRafael Auler 1082a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 1083a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 1084a34c753fSRafael Auler if (LineTables.empty()) 1085a34c753fSRafael Auler return; 1086a34c753fSRafael Auler 1087a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 1088a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 1089a34c753fSRafael Auler if (BC.Ctx->getDwarfVersion() >= 5) 1090a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 1091a34c753fSRafael Auler 1092a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 1093a34c753fSRafael Auler Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); 1094a34c753fSRafael Auler 1095a34c753fSRafael Auler // Handle the rest of the Compile Units. 1096a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 1097b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1098a34c753fSRafael Auler } 1099a34c753fSRafael Auler } 1100a34c753fSRafael Auler 1101a34c753fSRafael Auler } // namespace bolt 1102a34c753fSRafael Auler } // namespace llvm 1103