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