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" 14f8c7fb49SAmir Ayupov #include "bolt/Core/BinaryContext.h" 15*014cd37fSAlexander Yermolovich #include "bolt/Rewrite/RewriteInstance.h" 16a34c753fSRafael Auler #include "bolt/Utils/Utils.h" 17290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 18290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 19*014cd37fSAlexander Yermolovich #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" 2057f7c7d9Sserge-sans-paille #include "llvm/MC/MCAssembler.h" 21f8c7fb49SAmir Ayupov #include "llvm/MC/MCContext.h" 22a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h" 23a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 24a34c753fSRafael Auler #include "llvm/Support/EndianStream.h" 25a34c753fSRafael Auler #include "llvm/Support/LEB128.h" 269f3f9d19SAlexander Yermolovich #include "llvm/Support/SHA1.h" 27a34c753fSRafael Auler #include <algorithm> 28a34c753fSRafael Auler #include <cassert> 29a34c753fSRafael Auler #include <cstdint> 30a34c753fSRafael Auler #include <limits> 311c2f4bbeSAlexander Yermolovich #include <unordered_map> 32a34c753fSRafael Auler 33a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info" 34a34c753fSRafael Auler 35a34c753fSRafael Auler namespace opts { 36a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity; 371c2f4bbeSAlexander Yermolovich } // namespace opts 38a34c753fSRafael Auler 39a34c753fSRafael Auler namespace llvm { 40f8c7fb49SAmir Ayupov class MCSymbol; 41f8c7fb49SAmir Ayupov 42a34c753fSRafael Auler namespace bolt { 43a34c753fSRafael Auler 44bd1ebe9dSAlexander Yermolovich /// Finds attributes FormValue and Offset. 45bd1ebe9dSAlexander Yermolovich /// 46bd1ebe9dSAlexander Yermolovich /// \param DIE die to look up in. 47bd1ebe9dSAlexander Yermolovich /// \param Index the attribute index to extract. 48bd1ebe9dSAlexander Yermolovich /// \return an optional AttrInfo with DWARFFormValue and Offset. 49bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> 50bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE, 51bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl, 52bd1ebe9dSAlexander Yermolovich uint32_t Index) { 53bd1ebe9dSAlexander Yermolovich const DWARFUnit &U = *DIE.getDwarfUnit(); 54bd1ebe9dSAlexander Yermolovich uint64_t Offset = 55bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U); 56bd1ebe9dSAlexander Yermolovich Optional<DWARFFormValue> Value = 57bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U); 58bd1ebe9dSAlexander Yermolovich if (!Value) 59bd1ebe9dSAlexander Yermolovich return None; 60bd1ebe9dSAlexander Yermolovich // AttributeSpec 61bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal = 62bd1ebe9dSAlexander Yermolovich AbbrevDecl->attributes().begin() + Index; 63bd1ebe9dSAlexander Yermolovich uint32_t ValSize = 0; 64bd1ebe9dSAlexander Yermolovich Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U); 65bd1ebe9dSAlexander Yermolovich if (ValSizeOpt) { 66bd1ebe9dSAlexander Yermolovich ValSize = static_cast<uint32_t>(*ValSizeOpt); 67bd1ebe9dSAlexander Yermolovich } else { 68bd1ebe9dSAlexander Yermolovich DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 69bd1ebe9dSAlexander Yermolovich uint64_t NewOffset = Offset; 70bd1ebe9dSAlexander Yermolovich DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset, 71bd1ebe9dSAlexander Yermolovich U.getFormParams()); 72bd1ebe9dSAlexander Yermolovich // This includes entire size of the entry, which might not be just the 73bd1ebe9dSAlexander Yermolovich // encoding part. For example for DW_AT_loc it will include expression 74bd1ebe9dSAlexander Yermolovich // location. 75bd1ebe9dSAlexander Yermolovich ValSize = NewOffset - Offset; 76bd1ebe9dSAlexander Yermolovich } 77bd1ebe9dSAlexander Yermolovich 78bd1ebe9dSAlexander Yermolovich return AttrInfo{*Value, Offset, ValSize}; 79bd1ebe9dSAlexander Yermolovich } 80bd1ebe9dSAlexander Yermolovich 81a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 82a34c753fSRafael Auler 83a34c753fSRafael Auler namespace { 84a34c753fSRafael Auler 851c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED 861c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) { 871c2f4bbeSAlexander Yermolovich for (uint32_t I = 0, Size = S.size(); I < Size; ++I) { 881c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr(S[I]); 891c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr((int8_t)S[I]); 901c2f4bbeSAlexander Yermolovich } 911c2f4bbeSAlexander Yermolovich errs() << "\n"; 921c2f4bbeSAlexander Yermolovich } 931c2f4bbeSAlexander Yermolovich 94a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size). 95a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of 96a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address). 97a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes. 98a34c753fSRafael Auler // Returns the number of written bytes. 9940c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream, 100a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges, 101a34c753fSRafael Auler const bool WriteRelativeRanges = false) { 102a34c753fSRafael Auler for (const DebugAddressRange &Range : AddressRanges) { 103a34c753fSRafael Auler support::endian::write(Stream, Range.LowPC, support::little); 104a34c753fSRafael Auler support::endian::write( 105a34c753fSRafael Auler Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 106a34c753fSRafael Auler support::little); 107a34c753fSRafael Auler } 108a34c753fSRafael Auler // Finish with 0 entries. 109a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 110a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 111a34c753fSRafael Auler return AddressRanges.size() * 16 + 16; 112a34c753fSRafael Auler } 113a34c753fSRafael Auler 114a34c753fSRafael Auler } // namespace 115a34c753fSRafael Auler 116a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() { 117a34c753fSRafael Auler RangesBuffer = std::make_unique<DebugBufferVector>(); 118a34c753fSRafael Auler RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 119a34c753fSRafael Auler 120a34c753fSRafael Auler // Add an empty range as the first entry; 121a34c753fSRafael Auler SectionOffset += 122a34c753fSRafael Auler writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 123*014cd37fSAlexander Yermolovich Kind = RangesWriterKind::DebugRangesWriter; 124a34c753fSRafael Auler } 125a34c753fSRafael Auler 126a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges( 127a34c753fSRafael Auler DebugAddressRangesVector &&Ranges, 128a34c753fSRafael Auler std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 129a34c753fSRafael Auler if (Ranges.empty()) 130a34c753fSRafael Auler return getEmptyRangesOffset(); 131a34c753fSRafael Auler 132a34c753fSRafael Auler const auto RI = CachedRanges.find(Ranges); 133a34c753fSRafael Auler if (RI != CachedRanges.end()) 134a34c753fSRafael Auler return RI->second; 135a34c753fSRafael Auler 136a34c753fSRafael Auler const uint64_t EntryOffset = addRanges(Ranges); 137a34c753fSRafael Auler CachedRanges.emplace(std::move(Ranges), EntryOffset); 138a34c753fSRafael Auler 139a34c753fSRafael Auler return EntryOffset; 140a34c753fSRafael Auler } 141a34c753fSRafael Auler 142a34c753fSRafael Auler uint64_t 143a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) { 144a34c753fSRafael Auler if (Ranges.empty()) 145a34c753fSRafael Auler return getEmptyRangesOffset(); 146a34c753fSRafael Auler 147a34c753fSRafael Auler // Reading the SectionOffset and updating it should be atomic to guarantee 148a34c753fSRafael Auler // unique and correct offsets in patches. 149a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 150a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 151a34c753fSRafael Auler SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges); 152a34c753fSRafael Auler 153a34c753fSRafael Auler return EntryOffset; 154a34c753fSRafael Auler } 155a34c753fSRafael Auler 156a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() { 157a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 158a34c753fSRafael Auler return SectionOffset; 159a34c753fSRafael Auler } 160a34c753fSRafael Auler 161*014cd37fSAlexander Yermolovich DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr; 162*014cd37fSAlexander Yermolovich 163*014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges( 164*014cd37fSAlexander Yermolovich DebugAddressRangesVector &&Ranges, 165*014cd37fSAlexander Yermolovich std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 166*014cd37fSAlexander Yermolovich return addRanges(Ranges); 167*014cd37fSAlexander Yermolovich } 168*014cd37fSAlexander Yermolovich 169*014cd37fSAlexander Yermolovich struct LocListsRangelistsHeader { 170*014cd37fSAlexander Yermolovich UnitLengthType UnitLength; // Size of loclist entris section, not including 171*014cd37fSAlexander Yermolovich // size of header. 172*014cd37fSAlexander Yermolovich VersionType Version; 173*014cd37fSAlexander Yermolovich AddressSizeType AddressSize; 174*014cd37fSAlexander Yermolovich SegmentSelectorType SegmentSelector; 175*014cd37fSAlexander Yermolovich OffsetEntryCountType OffsetEntryCount; 176*014cd37fSAlexander Yermolovich }; 177*014cd37fSAlexander Yermolovich 178*014cd37fSAlexander Yermolovich static std::unique_ptr<DebugBufferVector> 179*014cd37fSAlexander Yermolovich getDWARF5Header(const LocListsRangelistsHeader &Header) { 180*014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> HeaderBuffer = 181*014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 182*014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> HeaderStream = 183*014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*HeaderBuffer); 184*014cd37fSAlexander Yermolovich 185*014cd37fSAlexander Yermolovich // 7.29 length of the set of entries for this compilation unit, not including 186*014cd37fSAlexander Yermolovich // the length field itself 187*014cd37fSAlexander Yermolovich const uint32_t HeaderSize = 188*014cd37fSAlexander Yermolovich getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType); 189*014cd37fSAlexander Yermolovich 190*014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize, 191*014cd37fSAlexander Yermolovich support::little); 192*014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.Version, support::little); 193*014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.AddressSize, support::little); 194*014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.SegmentSelector, 195*014cd37fSAlexander Yermolovich support::little); 196*014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.OffsetEntryCount, 197*014cd37fSAlexander Yermolovich support::little); 198*014cd37fSAlexander Yermolovich return HeaderBuffer; 199*014cd37fSAlexander Yermolovich } 200*014cd37fSAlexander Yermolovich 201*014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges( 202*014cd37fSAlexander Yermolovich const DebugAddressRangesVector &Ranges) { 203*014cd37fSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 204*014cd37fSAlexander Yermolovich 205*014cd37fSAlexander Yermolovich RangeEntries.push_back(CurrentOffset); 206*014cd37fSAlexander Yermolovich for (const DebugAddressRange &Range : Ranges) { 207*014cd37fSAlexander Yermolovich support::endian::write(*CUBodyStream, 208*014cd37fSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_RLE_startx_length), 209*014cd37fSAlexander Yermolovich support::little); 210*014cd37fSAlexander Yermolovich const uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, CUID); 211*014cd37fSAlexander Yermolovich encodeULEB128(Index, *CUBodyStream); 212*014cd37fSAlexander Yermolovich encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream); 213*014cd37fSAlexander Yermolovich } 214*014cd37fSAlexander Yermolovich support::endian::write(*CUBodyStream, 215*014cd37fSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_RLE_end_of_list), 216*014cd37fSAlexander Yermolovich support::little); 217*014cd37fSAlexander Yermolovich CurrentOffset = CUBodyBuffer->size(); 218*014cd37fSAlexander Yermolovich return RangeEntries.size() - 1; 219*014cd37fSAlexander Yermolovich } 220*014cd37fSAlexander Yermolovich 221*014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::finalizeSection() { 222*014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> CUArrayBuffer = 223*014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 224*014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> CUArrayStream = 225*014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*CUArrayBuffer); 226*014cd37fSAlexander Yermolovich constexpr uint32_t SizeOfArrayEntry = 4; 227*014cd37fSAlexander Yermolovich const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry; 228*014cd37fSAlexander Yermolovich for (uint32_t Offset : RangeEntries) 229*014cd37fSAlexander Yermolovich support::endian::write(*CUArrayStream, Offset + SizeOfArraySection, 230*014cd37fSAlexander Yermolovich support::little); 231*014cd37fSAlexander Yermolovich 232*014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 233*014cd37fSAlexander Yermolovich {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()), 234*014cd37fSAlexander Yermolovich 5, 8, 0, static_cast<uint32_t>(RangeEntries.size())}); 235*014cd37fSAlexander Yermolovich *RangesStream << *Header; 236*014cd37fSAlexander Yermolovich *RangesStream << *CUArrayBuffer; 237*014cd37fSAlexander Yermolovich *RangesStream << *CUBodyBuffer; 238*014cd37fSAlexander Yermolovich SectionOffset = RangesBuffer->size(); 239*014cd37fSAlexander Yermolovich } 240*014cd37fSAlexander Yermolovich 241*014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::initSection(uint64_t CUId_) { 242*014cd37fSAlexander Yermolovich CUBodyBuffer = std::make_unique<DebugBufferVector>(); 243*014cd37fSAlexander Yermolovich CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer); 244*014cd37fSAlexander Yermolovich RangeEntries.clear(); 245*014cd37fSAlexander Yermolovich CurrentOffset = 0; 246*014cd37fSAlexander Yermolovich CUID = CUId_; 247*014cd37fSAlexander Yermolovich } 248*014cd37fSAlexander Yermolovich 249a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 250a34c753fSRafael Auler DebugAddressRangesVector &&Ranges) { 251a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 252a34c753fSRafael Auler CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 253a34c753fSRafael Auler } 254a34c753fSRafael Auler 255a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection( 256612f0f45SAlexander Yermolovich raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const { 257a34c753fSRafael Auler // For reference on the format of the .debug_aranges section, see the DWARF4 258a34c753fSRafael Auler // specification, section 6.1.4 Lookup by Address 259a34c753fSRafael Auler // http://www.dwarfstd.org/doc/DWARF4.pdf 260a34c753fSRafael Auler for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 261a34c753fSRafael Auler const uint64_t Offset = CUOffsetAddressRangesPair.first; 262a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges = 263a34c753fSRafael Auler CUOffsetAddressRangesPair.second; 264a34c753fSRafael Auler 265a34c753fSRafael Auler // Emit header. 266a34c753fSRafael Auler 267a34c753fSRafael Auler // Size of this set: 8 (size of the header) + 4 (padding after header) 268a34c753fSRafael Auler // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 269a34c753fSRafael Auler // pair of uint64_t's for the terminating, zero-length range. 270a34c753fSRafael Auler // Does not include size field itself. 271a34c753fSRafael Auler uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 272a34c753fSRafael Auler 273a34c753fSRafael Auler // Header field #1: set size. 274a34c753fSRafael Auler support::endian::write(RangesStream, Size, support::little); 275a34c753fSRafael Auler 276a34c753fSRafael Auler // Header field #2: version number, 2 as per the specification. 277a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint16_t>(2), 278a34c753fSRafael Auler support::little); 279a34c753fSRafael Auler 2801c2f4bbeSAlexander Yermolovich assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map"); 281a34c753fSRafael Auler // Header field #3: debug info offset of the correspondent compile unit. 282612f0f45SAlexander Yermolovich support::endian::write( 283612f0f45SAlexander Yermolovich RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset), 284a34c753fSRafael Auler support::little); 285a34c753fSRafael Auler 286a34c753fSRafael Auler // Header field #4: address size. 287a34c753fSRafael Auler // 8 since we only write ELF64 binaries for now. 288a34c753fSRafael Auler RangesStream << char(8); 289a34c753fSRafael Auler 290a34c753fSRafael Auler // Header field #5: segment size of target architecture. 291a34c753fSRafael Auler RangesStream << char(0); 292a34c753fSRafael Auler 293a34c753fSRafael Auler // Padding before address table - 4 bytes in the 64-bit-pointer case. 294a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint32_t>(0), 295a34c753fSRafael Auler support::little); 296a34c753fSRafael Auler 297a34c753fSRafael Auler writeAddressRanges(RangesStream, AddressRanges, true); 298a34c753fSRafael Auler } 299a34c753fSRafael Auler } 300a34c753fSRafael Auler 301a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; } 302a34c753fSRafael Auler 303a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() { 304a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 305a34c753fSRafael Auler indexToAdddessEnd()); 306a34c753fSRafael Auler // Sorting address in increasing order of indices. 307a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 308a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 309a34c753fSRafael Auler return A.first < B.first; 310a34c753fSRafael Auler }); 311a34c753fSRafael Auler for (auto &Pair : SortedMap) 312a34c753fSRafael Auler dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 313a34c753fSRafael Auler } 314*014cd37fSAlexander Yermolovich uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, uint64_t CUID) { 315e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 316*014cd37fSAlexander Yermolovich if (!AddressMaps.count(CUID)) 317*014cd37fSAlexander Yermolovich AddressMaps[CUID] = AddressForDWOCU(); 318a34c753fSRafael Auler 319*014cd37fSAlexander Yermolovich AddressForDWOCU &Map = AddressMaps[CUID]; 320a34c753fSRafael Auler auto Entry = Map.find(Address); 321a34c753fSRafael Auler if (Entry == Map.end()) { 322a34c753fSRafael Auler auto Index = Map.getNextIndex(); 323a34c753fSRafael Auler Entry = Map.insert(Address, Index).first; 324a34c753fSRafael Auler } 325a34c753fSRafael Auler return Entry->second; 326a34c753fSRafael Auler } 327a34c753fSRafael Auler 328a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 329a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update 330a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 331a34c753fSRafael Auler // update AddressToIndex and IndexToAddress 332a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 333*014cd37fSAlexander Yermolovich uint64_t CUID) { 334e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 335*014cd37fSAlexander Yermolovich AddressForDWOCU &Map = AddressMaps[CUID]; 336a34c753fSRafael Auler auto Entry = Map.find(Address); 337a34c753fSRafael Auler if (Entry != Map.end()) { 338a34c753fSRafael Auler if (Entry->second > Index) 339a34c753fSRafael Auler Map.updateAddressToIndex(Address, Index); 340a34c753fSRafael Auler Map.updateIndexToAddrss(Address, Index); 3413652483cSRafael Auler } else { 342a34c753fSRafael Auler Map.insert(Address, Index); 343a34c753fSRafael Auler } 3443652483cSRafael Auler } 345a34c753fSRafael Auler 346a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() { 347a34c753fSRafael Auler // Need to layout all sections within .debug_addr 348a34c753fSRafael Auler // Within each section sort Address by index. 349a34c753fSRafael Auler AddressSectionBuffer Buffer; 350a34c753fSRafael Auler raw_svector_ostream AddressStream(Buffer); 351a34c753fSRafael Auler for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 352a34c753fSRafael Auler Optional<uint64_t> DWOId = CU->getDWOId(); 353a34c753fSRafael Auler // Handling the case wehre debug information is a mix of Debug fission and 354a34c753fSRafael Auler // monolitic. 355a34c753fSRafael Auler if (!DWOId) 356a34c753fSRafael Auler continue; 357a34c753fSRafael Auler auto AM = AddressMaps.find(*DWOId); 358*014cd37fSAlexander Yermolovich assert(AM != AddressMaps.end() && "Address Map not found."); 359a34c753fSRafael Auler // Adding to map even if it did not contribute to .debug_addr. 360a34c753fSRafael Auler // The Skeleton CU will still have DW_AT_GNU_addr_base. 361a34c753fSRafael Auler DWOIdToOffsetMap[*DWOId] = Buffer.size(); 362a34c753fSRafael Auler // If does not exist this CUs DWO section didn't contribute to .debug_addr. 363a34c753fSRafael Auler if (AM == AddressMaps.end()) 364a34c753fSRafael Auler continue; 365a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 366a34c753fSRafael Auler AM->second.indexToAdddessEnd()); 367a34c753fSRafael Auler // Sorting address in increasing order of indices. 368a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 369a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 370a34c753fSRafael Auler return A.first < B.first; 371a34c753fSRafael Auler }); 372a34c753fSRafael Auler 373a34c753fSRafael Auler uint8_t AddrSize = CU->getAddressByteSize(); 374a34c753fSRafael Auler uint32_t Counter = 0; 375a34c753fSRafael Auler auto WriteAddress = [&](uint64_t Address) -> void { 376a34c753fSRafael Auler ++Counter; 377a34c753fSRafael Auler switch (AddrSize) { 378a34c753fSRafael Auler default: 379a34c753fSRafael Auler assert(false && "Address Size is invalid."); 380a34c753fSRafael Auler break; 381a34c753fSRafael Auler case 4: 382a34c753fSRafael Auler support::endian::write(AddressStream, static_cast<uint32_t>(Address), 383a34c753fSRafael Auler support::little); 384a34c753fSRafael Auler break; 385a34c753fSRafael Auler case 8: 386a34c753fSRafael Auler support::endian::write(AddressStream, Address, support::little); 387a34c753fSRafael Auler break; 388a34c753fSRafael Auler } 389a34c753fSRafael Auler }; 390a34c753fSRafael Auler 391a34c753fSRafael Auler for (const IndexAddressPair &Val : SortedMap) { 392a34c753fSRafael Auler while (Val.first > Counter) 393a34c753fSRafael Auler WriteAddress(0); 394a34c753fSRafael Auler WriteAddress(Val.second); 395a34c753fSRafael Auler } 396a34c753fSRafael Auler } 397a34c753fSRafael Auler 398a34c753fSRafael Auler return Buffer; 399a34c753fSRafael Auler } 400*014cd37fSAlexander Yermolovich AddressSectionBuffer DebugAddrWriterDwarf5::finalize() { 401*014cd37fSAlexander Yermolovich // Need to layout all sections within .debug_addr 402*014cd37fSAlexander Yermolovich // Within each section sort Address by index. 403*014cd37fSAlexander Yermolovich AddressSectionBuffer Buffer; 404*014cd37fSAlexander Yermolovich raw_svector_ostream AddressStream(Buffer); 405*014cd37fSAlexander Yermolovich const endianness Endian = 406*014cd37fSAlexander Yermolovich BC->DwCtx->isLittleEndian() ? support::little : support::big; 407*014cd37fSAlexander Yermolovich const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection(); 408*014cd37fSAlexander Yermolovich DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0); 409*014cd37fSAlexander Yermolovich DWARFDebugAddrTable AddrTable; 410*014cd37fSAlexander Yermolovich DIDumpOptions DumpOpts; 411*014cd37fSAlexander Yermolovich constexpr uint32_t HeaderSize = 8; 412*014cd37fSAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 413*014cd37fSAlexander Yermolovich const uint64_t CUID = CU->getOffset(); 414*014cd37fSAlexander Yermolovich const uint8_t AddrSize = CU->getAddressByteSize(); 415*014cd37fSAlexander Yermolovich auto Iter = AddressMaps.find(CUID); 416*014cd37fSAlexander Yermolovich // A case where CU has entry in .debug_addr, but we don't modify addresses 417*014cd37fSAlexander Yermolovich // for it. 418*014cd37fSAlexander Yermolovich if (Iter == AddressMaps.end()) { 419*014cd37fSAlexander Yermolovich Iter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; 420*014cd37fSAlexander Yermolovich Optional<uint64_t> BaseOffset = CU->getAddrOffsetSectionBase(); 421*014cd37fSAlexander Yermolovich if (!BaseOffset) 422*014cd37fSAlexander Yermolovich continue; 423*014cd37fSAlexander Yermolovich // Address base offset is to the first entry. 424*014cd37fSAlexander Yermolovich // The size of header is 8 bytes. 425*014cd37fSAlexander Yermolovich uint64_t Offset = *BaseOffset - HeaderSize; 426*014cd37fSAlexander Yermolovich if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize, 427*014cd37fSAlexander Yermolovich DumpOpts.WarningHandler)) { 428*014cd37fSAlexander Yermolovich DumpOpts.RecoverableErrorHandler(std::move(Err)); 429*014cd37fSAlexander Yermolovich continue; 430*014cd37fSAlexander Yermolovich } 431*014cd37fSAlexander Yermolovich uint32_t Index = 0; 432*014cd37fSAlexander Yermolovich for (uint64_t Addr : AddrTable.getAddressEntries()) 433*014cd37fSAlexander Yermolovich Iter->second.insert(Addr, Index++); 434*014cd37fSAlexander Yermolovich } 435a34c753fSRafael Auler 436*014cd37fSAlexander Yermolovich DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize; 437*014cd37fSAlexander Yermolovich 438*014cd37fSAlexander Yermolovich std::vector<IndexAddressPair> SortedMap(Iter->second.indexToAddressBegin(), 439*014cd37fSAlexander Yermolovich Iter->second.indexToAdddessEnd()); 440*014cd37fSAlexander Yermolovich // Sorting address in increasing order of indices. 441*014cd37fSAlexander Yermolovich std::sort(SortedMap.begin(), SortedMap.end(), 442*014cd37fSAlexander Yermolovich [](const IndexAddressPair &A, const IndexAddressPair &B) { 443*014cd37fSAlexander Yermolovich return A.first < B.first; 444*014cd37fSAlexander Yermolovich }); 445*014cd37fSAlexander Yermolovich // Writing out Header 446*014cd37fSAlexander Yermolovich const uint32_t Length = SortedMap.size() * AddrSize + 4; 447*014cd37fSAlexander Yermolovich support::endian::write(AddressStream, Length, Endian); 448*014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian); 449*014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize), 450*014cd37fSAlexander Yermolovich Endian); 451*014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian); 452*014cd37fSAlexander Yermolovich 453*014cd37fSAlexander Yermolovich uint32_t Counter = 0; 454*014cd37fSAlexander Yermolovich auto writeAddress = [&](uint64_t Address) -> void { 455*014cd37fSAlexander Yermolovich ++Counter; 456*014cd37fSAlexander Yermolovich switch (AddrSize) { 457*014cd37fSAlexander Yermolovich default: 458*014cd37fSAlexander Yermolovich llvm_unreachable("Address Size is invalid."); 459*014cd37fSAlexander Yermolovich break; 460*014cd37fSAlexander Yermolovich case 4: 461*014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint32_t>(Address), 462*014cd37fSAlexander Yermolovich Endian); 463*014cd37fSAlexander Yermolovich break; 464*014cd37fSAlexander Yermolovich case 8: 465*014cd37fSAlexander Yermolovich support::endian::write(AddressStream, Address, Endian); 466*014cd37fSAlexander Yermolovich break; 467*014cd37fSAlexander Yermolovich } 468*014cd37fSAlexander Yermolovich }; 469*014cd37fSAlexander Yermolovich 470*014cd37fSAlexander Yermolovich for (const IndexAddressPair &Val : SortedMap) { 471*014cd37fSAlexander Yermolovich while (Val.first > Counter) 472*014cd37fSAlexander Yermolovich writeAddress(0); 473*014cd37fSAlexander Yermolovich writeAddress(Val.second); 474*014cd37fSAlexander Yermolovich } 475*014cd37fSAlexander Yermolovich } 476*014cd37fSAlexander Yermolovich 477*014cd37fSAlexander Yermolovich return Buffer; 478*014cd37fSAlexander Yermolovich } 479*014cd37fSAlexander Yermolovich 480*014cd37fSAlexander Yermolovich uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) { 481*014cd37fSAlexander Yermolovich Optional<uint64_t> DWOId = Unit.getDWOId(); 482*014cd37fSAlexander Yermolovich assert(DWOId && "Can't get offset, not a skeleton CU."); 483*014cd37fSAlexander Yermolovich auto Iter = DWOIdToOffsetMap.find(*DWOId); 484*014cd37fSAlexander Yermolovich assert(Iter != DWOIdToOffsetMap.end() && 485*014cd37fSAlexander Yermolovich "Offset in to.debug_addr was not found for DWO ID."); 486*014cd37fSAlexander Yermolovich return Iter->second; 487*014cd37fSAlexander Yermolovich } 488*014cd37fSAlexander Yermolovich 489*014cd37fSAlexander Yermolovich uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) { 490*014cd37fSAlexander Yermolovich auto Iter = DWOIdToOffsetMap.find(Unit.getOffset()); 491a34c753fSRafael Auler assert(Iter != DWOIdToOffsetMap.end() && 492a34c753fSRafael Auler "Offset in to.debug_addr was not found for DWO ID."); 493a34c753fSRafael Auler return Iter->second; 494a34c753fSRafael Auler } 495a34c753fSRafael Auler 496a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) { 497a34c753fSRafael Auler LocBuffer = std::make_unique<DebugBufferVector>(); 498a34c753fSRafael Auler LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 499a34c753fSRafael Auler } 500a34c753fSRafael Auler 501*014cd37fSAlexander Yermolovich void DebugLocWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex, 502a34c753fSRafael Auler DebugLocationsVector &&LocList) { 503a34c753fSRafael Auler if (LocList.empty()) { 504a34c753fSRafael Auler EmptyAttrLists.push_back(AttrOffset); 505a34c753fSRafael Auler return; 506a34c753fSRafael Auler } 507a34c753fSRafael Auler // Since there is a separate DebugLocWriter for each thread, 508a34c753fSRafael Auler // we don't need a lock to read the SectionOffset and update it. 509a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 510a34c753fSRafael Auler 511a34c753fSRafael Auler for (const DebugLocationEntry &Entry : LocList) { 512a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 513a34c753fSRafael Auler support::little); 514a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 515a34c753fSRafael Auler support::little); 516a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 517a34c753fSRafael Auler support::little); 518a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 519a34c753fSRafael Auler Entry.Expr.size()); 520a34c753fSRafael Auler SectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 521a34c753fSRafael Auler } 522a34c753fSRafael Auler LocStream->write_zeros(16); 523a34c753fSRafael Auler SectionOffset += 16; 524a34c753fSRafael Auler LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 525a34c753fSRafael Auler } 526a34c753fSRafael Auler 527*014cd37fSAlexander Yermolovich void DebugLoclistWriter::addList(uint64_t AttrOffset, uint32_t LocListIndex, 528a34c753fSRafael Auler DebugLocationsVector &&LocList) { 529*014cd37fSAlexander Yermolovich Patches.push_back({AttrOffset, LocListIndex, std::move(LocList)}); 530a34c753fSRafael Auler } 531a34c753fSRafael Auler 532a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 533a34c753fSRafael Auler return std::move(LocBuffer); 534a34c753fSRafael Auler } 535a34c753fSRafael Auler 536a34c753fSRafael Auler // DWARF 4: 2.6.2 537a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset, 538a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 539a34c753fSRafael Auler for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) { 540a34c753fSRafael Auler uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset; 541a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset, 542a34c753fSRafael Auler Offset); 543a34c753fSRafael Auler } 544a34c753fSRafael Auler 545a34c753fSRafael Auler for (uint64_t DebugInfoAttrOffset : EmptyAttrLists) 546a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset, 547a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 548a34c753fSRafael Auler } 549a34c753fSRafael Auler 550*014cd37fSAlexander Yermolovich static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { 551*014cd37fSAlexander Yermolovich support::endian::write(Stream, static_cast<uint32_t>(4), support::little); 552*014cd37fSAlexander Yermolovich support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end), 553*014cd37fSAlexander Yermolovich support::little); 554*014cd37fSAlexander Yermolovich 555*014cd37fSAlexander Yermolovich const char Zeroes[16] = {0}; 556*014cd37fSAlexander Yermolovich Stream << StringRef(Zeroes, 16); 557*014cd37fSAlexander Yermolovich encodeULEB128(0, Stream); 558*014cd37fSAlexander Yermolovich support::endian::write( 559*014cd37fSAlexander Yermolovich Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little); 560*014cd37fSAlexander Yermolovich } 561*014cd37fSAlexander Yermolovich 562*014cd37fSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARF5(uint64_t SectionOffset, 563a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 564*014cd37fSAlexander Yermolovich 565*014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> LocArrayBuffer = 566*014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 567*014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> LocArrayStream = 568*014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*LocArrayBuffer); 569*014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> LocBodyBuffer = 570*014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 571*014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> LocBodyStream = 572*014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*LocBodyBuffer); 573*014cd37fSAlexander Yermolovich 574*014cd37fSAlexander Yermolovich const uint32_t SizeOfArraySection = Patches.size() * sizeof(uint32_t); 575*014cd37fSAlexander Yermolovich std::sort(Patches.begin(), Patches.end(), 576*014cd37fSAlexander Yermolovich [](const LocPatch &P1, const LocPatch &P2) -> bool { 577*014cd37fSAlexander Yermolovich return P1.Index < P2.Index; 578*014cd37fSAlexander Yermolovich }); 579*014cd37fSAlexander Yermolovich 580*014cd37fSAlexander Yermolovich if (LocListsBaseAttrOffset != InvalidLocListsBaseAttrOffset) 581*014cd37fSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(LocListsBaseAttrOffset, 582*014cd37fSAlexander Yermolovich SectionOffset + 583*014cd37fSAlexander Yermolovich getDWARF5RngListLocListHeaderSize()); 584*014cd37fSAlexander Yermolovich 585*014cd37fSAlexander Yermolovich uint32_t Index{0}; 586*014cd37fSAlexander Yermolovich for (LocPatch &Patch : Patches) { 587*014cd37fSAlexander Yermolovich const uint32_t EntryOffset = LocBodyBuffer->size(); 588*014cd37fSAlexander Yermolovich if (Patch.LocList.empty()) { 589*014cd37fSAlexander Yermolovich if (Patch.Index == DebugLoclistWriter::InvalidIndex) 590*014cd37fSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); 591*014cd37fSAlexander Yermolovich 592*014cd37fSAlexander Yermolovich writeEmptyListDwarf5(*LocBodyStream); 593*014cd37fSAlexander Yermolovich continue; 594*014cd37fSAlexander Yermolovich } 595*014cd37fSAlexander Yermolovich 596*014cd37fSAlexander Yermolovich assert(Patch.Index == DebugLoclistWriter::InvalidIndex || 597*014cd37fSAlexander Yermolovich Patch.Index == Index++ && "Gap in LocList Index Array."); 598*014cd37fSAlexander Yermolovich 599*014cd37fSAlexander Yermolovich std::vector<uint64_t> OffsetsArray; 600*014cd37fSAlexander Yermolovich for (const DebugLocationEntry &Entry : Patch.LocList) { 601*014cd37fSAlexander Yermolovich support::endian::write(*LocBodyStream, 602*014cd37fSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 603*014cd37fSAlexander Yermolovich support::little); 604*014cd37fSAlexander Yermolovich const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUID); 605*014cd37fSAlexander Yermolovich encodeULEB128(Index, *LocBodyStream); 606*014cd37fSAlexander Yermolovich encodeULEB128(Entry.HighPC - Entry.LowPC, *LocBodyStream); 607*014cd37fSAlexander Yermolovich encodeULEB128(Entry.Expr.size(), *LocBodyStream); 608*014cd37fSAlexander Yermolovich *LocBodyStream << StringRef( 609*014cd37fSAlexander Yermolovich reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size()); 610*014cd37fSAlexander Yermolovich } 611*014cd37fSAlexander Yermolovich support::endian::write(*LocBodyStream, 612*014cd37fSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 613*014cd37fSAlexander Yermolovich support::little); 614*014cd37fSAlexander Yermolovich 615*014cd37fSAlexander Yermolovich // Write out IndexArray 616*014cd37fSAlexander Yermolovich support::endian::write( 617*014cd37fSAlexander Yermolovich *LocArrayStream, 618*014cd37fSAlexander Yermolovich static_cast<uint32_t>(SizeOfArraySection + EntryOffset), 619*014cd37fSAlexander Yermolovich support::little); 620*014cd37fSAlexander Yermolovich // Don't need to patch Index since we are re-using them. 621*014cd37fSAlexander Yermolovich if (Patch.Index == DebugLoclistWriter::InvalidIndex) 622*014cd37fSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); 623*014cd37fSAlexander Yermolovich clearList(Patch.LocList); 624*014cd37fSAlexander Yermolovich } 625*014cd37fSAlexander Yermolovich if (!Patches.empty()) { 626*014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> Header = 627*014cd37fSAlexander Yermolovich getDWARF5Header({static_cast<uint32_t>(SizeOfArraySection + 628*014cd37fSAlexander Yermolovich LocBodyBuffer.get()->size()), 629*014cd37fSAlexander Yermolovich 5, 8, 0, static_cast<uint32_t>(Patches.size())}); 630*014cd37fSAlexander Yermolovich *LocStream << *Header; 631*014cd37fSAlexander Yermolovich *LocStream << *LocArrayBuffer; 632*014cd37fSAlexander Yermolovich *LocStream << *LocBodyBuffer; 633*014cd37fSAlexander Yermolovich } 634*014cd37fSAlexander Yermolovich clearList(Patches); 635*014cd37fSAlexander Yermolovich } 636*014cd37fSAlexander Yermolovich 637*014cd37fSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARFLegacy( 638*014cd37fSAlexander Yermolovich uint64_t SectionOffset, SimpleBinaryPatcher &DebugInfoPatcher) { 639a34c753fSRafael Auler for (LocPatch &Patch : Patches) { 640a34c753fSRafael Auler if (Patch.LocList.empty()) { 641a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, 642a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 643a34c753fSRafael Auler continue; 644a34c753fSRafael Auler } 645a34c753fSRafael Auler const uint32_t EntryOffset = LocBuffer->size(); 646a34c753fSRafael Auler for (const DebugLocationEntry &Entry : Patch.LocList) { 647a34c753fSRafael Auler support::endian::write(*LocStream, 648a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 649a34c753fSRafael Auler support::little); 650*014cd37fSAlexander Yermolovich const uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, CUID); 651a34c753fSRafael Auler encodeULEB128(Index, *LocStream); 652a34c753fSRafael Auler 653a34c753fSRafael Auler // TODO: Support DWARF5 654a34c753fSRafael Auler support::endian::write(*LocStream, 655a34c753fSRafael Auler static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 656a34c753fSRafael Auler support::little); 657a34c753fSRafael Auler support::endian::write(*LocStream, 658a34c753fSRafael Auler static_cast<uint16_t>(Entry.Expr.size()), 659a34c753fSRafael Auler support::little); 660a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 661a34c753fSRafael Auler Entry.Expr.size()); 662a34c753fSRafael Auler } 663a34c753fSRafael Auler support::endian::write(*LocStream, 664a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 665a34c753fSRafael Auler support::little); 666a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); 667a34c753fSRafael Auler clearList(Patch.LocList); 668a34c753fSRafael Auler } 669a34c753fSRafael Auler clearList(Patches); 670a34c753fSRafael Auler } 671a34c753fSRafael Auler 672*014cd37fSAlexander Yermolovich void DebugLoclistWriter::finalize(uint64_t SectionOffset, 673*014cd37fSAlexander Yermolovich SimpleBinaryPatcher &DebugInfoPatcher) { 674*014cd37fSAlexander Yermolovich if (DwarfVersion < 5) 675*014cd37fSAlexander Yermolovich finalizeDWARFLegacy(SectionOffset, DebugInfoPatcher); 676*014cd37fSAlexander Yermolovich else 677*014cd37fSAlexander Yermolovich finalizeDWARF5(SectionOffset, DebugInfoPatcher); 678*014cd37fSAlexander Yermolovich } 679*014cd37fSAlexander Yermolovich 680a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 681a34c753fSRafael Auler 6821c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 6831c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 6841c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 685ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 686a34c753fSRafael Auler } 687a34c753fSRafael Auler 6881c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 6891c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 6901c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 6911c2f4bbeSAlexander Yermolovich auto RetVal = DestinationLabels.insert(Offset); 6921c2f4bbeSAlexander Yermolovich if (!RetVal.second) 6931c2f4bbeSAlexander Yermolovich return; 6941c2f4bbeSAlexander Yermolovich 695ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 696a34c753fSRafael Auler } 697a34c753fSRafael Auler 698bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 699bd1ebe9dSAlexander Yermolovich std::string LE64(ByteSize, 0); 700bd1ebe9dSAlexander Yermolovich for (size_t I = 0; I < ByteSize; ++I) { 701bd1ebe9dSAlexander Yermolovich LE64[I] = NewValue & 0xff; 702bd1ebe9dSAlexander Yermolovich NewValue >>= 8; 703bd1ebe9dSAlexander Yermolovich } 704bd1ebe9dSAlexander Yermolovich return LE64; 705bd1ebe9dSAlexander Yermolovich } 706bd1ebe9dSAlexander Yermolovich 707bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 708bd1ebe9dSAlexander Yermolovich uint32_t Value) { 709bd1ebe9dSAlexander Yermolovich std::string StrValue = encodeLE(4, Value); 710bd1ebe9dSAlexander Yermolovich insertNewEntry(DIE, std::move(StrValue)); 711bd1ebe9dSAlexander Yermolovich } 712bd1ebe9dSAlexander Yermolovich 713bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 714bd1ebe9dSAlexander Yermolovich std::string &&Value) { 715bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl = 716bd1ebe9dSAlexander Yermolovich DIE.getAbbreviationDeclarationPtr(); 717bd1ebe9dSAlexander Yermolovich 718bd1ebe9dSAlexander Yermolovich // In case this DIE has no attributes. 719bd1ebe9dSAlexander Yermolovich uint32_t Offset = DIE.getOffset() + 1; 720bd1ebe9dSAlexander Yermolovich size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 721bd1ebe9dSAlexander Yermolovich if (NumOfAttributes) { 722bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> Val = 723bd1ebe9dSAlexander Yermolovich findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 724bd1ebe9dSAlexander Yermolovich assert(Val && "Invalid Value."); 725bd1ebe9dSAlexander Yermolovich 726bd1ebe9dSAlexander Yermolovich Offset = Val->Offset + Val->Size - DWPUnitOffset; 727bd1ebe9dSAlexander Yermolovich } 728bd1ebe9dSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 729bd1ebe9dSAlexander Yermolovich DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 730bd1ebe9dSAlexander Yermolovich } 731bd1ebe9dSAlexander Yermolovich 7321c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 7331c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset, 7341c2f4bbeSAlexander Yermolovich uint32_t OldValueSize, 7351c2f4bbeSAlexander Yermolovich dwarf::Form Form) { 7361c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7371c2f4bbeSAlexander Yermolovich DestinationOffset -= DWPUnitOffset; 7381c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 739ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back( 740ea6c8b01SAlexander Yermolovich new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 7411c2f4bbeSAlexander Yermolovich } 7421c2f4bbeSAlexander Yermolovich 7431c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 7441c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7451c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7461c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7471c2f4bbeSAlexander Yermolovich DebugPatches.emplace_back( 748ea6c8b01SAlexander Yermolovich new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 7491c2f4bbeSAlexander Yermolovich } 7501c2f4bbeSAlexander Yermolovich 7511c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 7521c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7531c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 754ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 7551c2f4bbeSAlexander Yermolovich } 7561c2f4bbeSAlexander Yermolovich 7571c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 7581c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7591c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7601c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7611c2f4bbeSAlexander Yermolovich if (OldValueSize == 4) 762ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 763a44fe319SAlexander Yermolovich else if (OldValueSize == 8) 764ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 765a44fe319SAlexander Yermolovich else 766a44fe319SAlexander Yermolovich DebugPatches.emplace_back( 767a44fe319SAlexander Yermolovich new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); 7681c2f4bbeSAlexander Yermolovich } 7691c2f4bbeSAlexander Yermolovich 7701c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 7711c2f4bbeSAlexander Yermolovich std::string &&NewValue, 7721c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7731c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(NewValue)); 7741c2f4bbeSAlexander Yermolovich } 7751c2f4bbeSAlexander Yermolovich 7761c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 7771c2f4bbeSAlexander Yermolovich auto Str = std::string(1, Value); 7781c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Str)); 7791c2f4bbeSAlexander Yermolovich } 7801c2f4bbeSAlexander Yermolovich 7811c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 7821c2f4bbeSAlexander Yermolovich size_t ByteSize) { 7831c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 7841c2f4bbeSAlexander Yermolovich } 7851c2f4bbeSAlexander Yermolovich 7861c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 7871c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 788a34c753fSRafael Auler std::string Buff; 789a34c753fSRafael Auler raw_string_ostream OS(Buff); 7901c2f4bbeSAlexander Yermolovich encodeULEB128(Value, OS, OldValueSize); 791a34c753fSRafael Auler 7921c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Buff)); 793a34c753fSRafael Auler } 794a34c753fSRafael Auler 7951c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 796a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 797a34c753fSRafael Auler } 798a34c753fSRafael Auler 7991c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 8001c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 801a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 802a34c753fSRafael Auler } 803a34c753fSRafael Auler 8041c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 8051c2f4bbeSAlexander Yermolovich std::string BinaryContentsStr = std::string(BinaryContents); 806a34c753fSRafael Auler for (const auto &Patch : Patches) { 8071c2f4bbeSAlexander Yermolovich uint32_t Offset = Patch.first; 808a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 809a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 810a34c753fSRafael Auler "Applied patch runs over binary size."); 811a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 8121c2f4bbeSAlexander Yermolovich BinaryContentsStr[Offset + I] = ByteSequence[I]; 813a34c753fSRafael Auler } 814a34c753fSRafael Auler } 8151c2f4bbeSAlexander Yermolovich return BinaryContentsStr; 8161c2f4bbeSAlexander Yermolovich } 8171c2f4bbeSAlexander Yermolovich 818612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 819612f0f45SAlexander Yermolovich bool IsDWOContext) { 820612f0f45SAlexander Yermolovich CUOffsetMap CUMap; 821ea6c8b01SAlexander Yermolovich std::sort(DebugPatches.begin(), DebugPatches.end(), 822ea6c8b01SAlexander Yermolovich [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) { 823bd1ebe9dSAlexander Yermolovich if (V1.get()->Offset == V2.get()->Offset) { 824bd1ebe9dSAlexander Yermolovich if (V1->Kind == DebugPatchKind::NewDebugEntry && 825bd1ebe9dSAlexander Yermolovich V2->Kind == DebugPatchKind::NewDebugEntry) 826bd1ebe9dSAlexander Yermolovich return reinterpret_cast<const NewDebugEntry *>(V1.get()) 827bd1ebe9dSAlexander Yermolovich ->CurrentOrder < 828bd1ebe9dSAlexander Yermolovich reinterpret_cast<const NewDebugEntry *>(V2.get()) 829bd1ebe9dSAlexander Yermolovich ->CurrentOrder; 830bd1ebe9dSAlexander Yermolovich 831bd1ebe9dSAlexander Yermolovich // This is a case where we are modifying first entry of next 832bd1ebe9dSAlexander Yermolovich // DIE, and adding a new one. 833bd1ebe9dSAlexander Yermolovich return V1->Kind == DebugPatchKind::NewDebugEntry; 834bd1ebe9dSAlexander Yermolovich } 8351c2f4bbeSAlexander Yermolovich return V1.get()->Offset < V2.get()->Offset; 8361c2f4bbeSAlexander Yermolovich }); 8371c2f4bbeSAlexander Yermolovich 838612f0f45SAlexander Yermolovich DWARFUnitVector::compile_unit_range CompileUnits = 839612f0f45SAlexander Yermolovich IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 840612f0f45SAlexander Yermolovich 841612f0f45SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 842612f0f45SAlexander Yermolovich CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 843612f0f45SAlexander Yermolovich static_cast<uint32_t>(CU->getLength())}; 844612f0f45SAlexander Yermolovich 8451c2f4bbeSAlexander Yermolovich // Calculating changes in .debug_info size from Patches to build a map of old 8461c2f4bbeSAlexander Yermolovich // to updated reference destination offsets. 847612f0f45SAlexander Yermolovich uint32_t PreviousOffset = 0; 848612f0f45SAlexander Yermolovich int32_t PreviousChangeInSize = 0; 849ea6c8b01SAlexander Yermolovich for (UniquePatchPtrType &PatchBase : DebugPatches) { 8501c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 8511c2f4bbeSAlexander Yermolovich switch (P->Kind) { 8521c2f4bbeSAlexander Yermolovich default: 8531c2f4bbeSAlexander Yermolovich continue; 8541c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 855612f0f45SAlexander Yermolovich PreviousChangeInSize -= 4; 8561c2f4bbeSAlexander Yermolovich break; 8571c2f4bbeSAlexander Yermolovich } 858a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 859a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 860a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 861a44fe319SAlexander Yermolovich PreviousChangeInSize += 4 - DPVS->OldValueSize; 862a44fe319SAlexander Yermolovich break; 863a44fe319SAlexander Yermolovich } 8641c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 8651c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *DPV = 8661c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 8671c2f4bbeSAlexander Yermolovich std::string Temp; 8681c2f4bbeSAlexander Yermolovich raw_string_ostream OS(Temp); 8691c2f4bbeSAlexander Yermolovich encodeULEB128(DPV->Value, OS); 870612f0f45SAlexander Yermolovich PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 8711c2f4bbeSAlexander Yermolovich break; 8721c2f4bbeSAlexander Yermolovich } 8731c2f4bbeSAlexander Yermolovich case DebugPatchKind::DestinationReferenceLabel: { 8741c2f4bbeSAlexander Yermolovich DestinationReferenceLabel *DRL = 8751c2f4bbeSAlexander Yermolovich reinterpret_cast<DestinationReferenceLabel *>(P); 876612f0f45SAlexander Yermolovich OldToNewOffset[DRL->Offset] = 877612f0f45SAlexander Yermolovich DRL->Offset + ChangeInSize + PreviousChangeInSize; 8781c2f4bbeSAlexander Yermolovich break; 8791c2f4bbeSAlexander Yermolovich } 8801c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 8811c2f4bbeSAlexander Yermolovich // This doesn't look to be a common case, so will always encode as 4 bytes 8821c2f4bbeSAlexander Yermolovich // to reduce algorithmic complexity. 8831c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 8841c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.IndirectRelative) { 885612f0f45SAlexander Yermolovich PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 8861c2f4bbeSAlexander Yermolovich assert(RDP->PatchInfo.OldValueSize <= 4 && 8871c2f4bbeSAlexander Yermolovich "Variable encoding reference greater than 4 bytes."); 8881c2f4bbeSAlexander Yermolovich } 8891c2f4bbeSAlexander Yermolovich break; 8901c2f4bbeSAlexander Yermolovich } 8911c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 8921c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 8931c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 8941c2f4bbeSAlexander Yermolovich uint32_t CUOffset = BaseLabel->Offset; 895612f0f45SAlexander Yermolovich ChangeInSize += PreviousChangeInSize; 8961c2f4bbeSAlexander Yermolovich uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 897612f0f45SAlexander Yermolovich CUMap[CUOffset].Offset = CUOffsetUpdate; 898612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 899612f0f45SAlexander Yermolovich PreviousChangeInSize = 0; 900612f0f45SAlexander Yermolovich PreviousOffset = CUOffset; 901bd1ebe9dSAlexander Yermolovich break; 902bd1ebe9dSAlexander Yermolovich } 903bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 904bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 905bd1ebe9dSAlexander Yermolovich PreviousChangeInSize += NDE->Value.size(); 906bd1ebe9dSAlexander Yermolovich break; 9071c2f4bbeSAlexander Yermolovich } 9081c2f4bbeSAlexander Yermolovich } 9091c2f4bbeSAlexander Yermolovich } 910612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 9111c2f4bbeSAlexander Yermolovich return CUMap; 9121c2f4bbeSAlexander Yermolovich } 913bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 9141c2f4bbeSAlexander Yermolovich 9151c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 9161c2f4bbeSAlexander Yermolovich std::string NewBinaryContents; 9171c2f4bbeSAlexander Yermolovich NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 9181c2f4bbeSAlexander Yermolovich uint32_t StartOffset = 0; 9191c2f4bbeSAlexander Yermolovich uint32_t DwarfUnitBaseOffset = 0; 9201c2f4bbeSAlexander Yermolovich uint32_t OldValueSize = 0; 9211c2f4bbeSAlexander Yermolovich uint32_t Offset = 0; 9221c2f4bbeSAlexander Yermolovich std::string ByteSequence; 9231c2f4bbeSAlexander Yermolovich std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 9241c2f4bbeSAlexander Yermolovich // Wasting one entry to avoid checks for first. 9251c2f4bbeSAlexander Yermolovich LengthPatches.push_back({0, 0}); 9261c2f4bbeSAlexander Yermolovich 9271c2f4bbeSAlexander Yermolovich // Applying all the patches replacing current entry. 9281c2f4bbeSAlexander Yermolovich // This might change the size of .debug_info section. 929ea6c8b01SAlexander Yermolovich for (const UniquePatchPtrType &PatchBase : DebugPatches) { 9301c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 9311c2f4bbeSAlexander Yermolovich switch (P->Kind) { 9321c2f4bbeSAlexander Yermolovich default: 9331c2f4bbeSAlexander Yermolovich continue; 9341c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 9351c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 9361c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset = RDP->DestinationOffset; 9371c2f4bbeSAlexander Yermolovich assert(OldToNewOffset.count(DestinationOffset) && 9381c2f4bbeSAlexander Yermolovich "Destination Offset for reference not updated."); 9391c2f4bbeSAlexander Yermolovich uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 9401c2f4bbeSAlexander Yermolovich Offset = RDP->Offset; 9411c2f4bbeSAlexander Yermolovich OldValueSize = RDP->PatchInfo.OldValueSize; 9421c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.DirectRelative) { 9431c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 9441c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 9451c2f4bbeSAlexander Yermolovich // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 9461c2f4bbeSAlexander Yermolovich // and overflow if later debug information grows. 9471c2f4bbeSAlexander Yermolovich if (ByteSequence.size() > OldValueSize) 9481c2f4bbeSAlexander Yermolovich errs() << "BOLT-ERROR: Relative reference of size " 9491c2f4bbeSAlexander Yermolovich << Twine::utohexstr(OldValueSize) 9501c2f4bbeSAlexander Yermolovich << " overflows with the new encoding.\n"; 9511c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.DirectAbsolute) { 9521c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 9531c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.IndirectRelative) { 9541c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 9551c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 9561c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 9571c2f4bbeSAlexander Yermolovich encodeULEB128(UpdatedOffset, OS, 4); 9581c2f4bbeSAlexander Yermolovich } else { 9591c2f4bbeSAlexander Yermolovich llvm_unreachable("Invalid Reference form."); 9601c2f4bbeSAlexander Yermolovich } 9611c2f4bbeSAlexander Yermolovich break; 9621c2f4bbeSAlexander Yermolovich } 9631c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue32: { 9641c2f4bbeSAlexander Yermolovich DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 9651c2f4bbeSAlexander Yermolovich Offset = P32->Offset; 9661c2f4bbeSAlexander Yermolovich OldValueSize = 4; 9671c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P32->Value); 9681c2f4bbeSAlexander Yermolovich break; 9691c2f4bbeSAlexander Yermolovich } 9701c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 9711c2f4bbeSAlexander Yermolovich DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 9721c2f4bbeSAlexander Yermolovich Offset = P64to32->Offset; 9731c2f4bbeSAlexander Yermolovich OldValueSize = 8; 9741c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P64to32->Value); 9751c2f4bbeSAlexander Yermolovich break; 9761c2f4bbeSAlexander Yermolovich } 977a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 978a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 979a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 980a44fe319SAlexander Yermolovich Offset = DPVS->Offset; 981a44fe319SAlexander Yermolovich OldValueSize = DPVS->OldValueSize; 982a44fe319SAlexander Yermolovich ByteSequence = encodeLE(4, DPVS->Value); 983a44fe319SAlexander Yermolovich break; 984a44fe319SAlexander Yermolovich } 9851c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 9861c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *PV = 9871c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 9881c2f4bbeSAlexander Yermolovich Offset = PV->Offset; 9891c2f4bbeSAlexander Yermolovich OldValueSize = PV->OldValueSize; 9901c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 9911c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 9921c2f4bbeSAlexander Yermolovich encodeULEB128(PV->Value, OS); 9931c2f4bbeSAlexander Yermolovich break; 9941c2f4bbeSAlexander Yermolovich } 9951c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64: { 9961c2f4bbeSAlexander Yermolovich DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 9971c2f4bbeSAlexander Yermolovich Offset = P64->Offset; 9981c2f4bbeSAlexander Yermolovich OldValueSize = 8; 9991c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(8, P64->Value); 10001c2f4bbeSAlexander Yermolovich break; 10011c2f4bbeSAlexander Yermolovich } 10021c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 10031c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 10041c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 10051c2f4bbeSAlexander Yermolovich Offset = BaseLabel->Offset; 10061c2f4bbeSAlexander Yermolovich OldValueSize = 0; 10071c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 10081c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 10091c2f4bbeSAlexander Yermolovich // Length to copy between last patch entry and next compile unit. 10101c2f4bbeSAlexander Yermolovich uint32_t RemainingLength = Offset - StartOffset; 10111c2f4bbeSAlexander Yermolovich uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 10121c2f4bbeSAlexander Yermolovich DwarfUnitBaseOffset = NewCUOffset; 10131c2f4bbeSAlexander Yermolovich // Length of previous CU = This CU Offset - sizeof(length) - last CU 10141c2f4bbeSAlexander Yermolovich // Offset. 10151c2f4bbeSAlexander Yermolovich Patch.second = NewCUOffset - 4 - Patch.first; 10161c2f4bbeSAlexander Yermolovich LengthPatches.push_back({NewCUOffset, 0}); 10171c2f4bbeSAlexander Yermolovich break; 10181c2f4bbeSAlexander Yermolovich } 1019bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 1020bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1021bd1ebe9dSAlexander Yermolovich Offset = NDE->Offset; 1022bd1ebe9dSAlexander Yermolovich OldValueSize = 0; 1023bd1ebe9dSAlexander Yermolovich ByteSequence = NDE->Value; 1024bd1ebe9dSAlexander Yermolovich break; 1025bd1ebe9dSAlexander Yermolovich } 10261c2f4bbeSAlexander Yermolovich } 10271c2f4bbeSAlexander Yermolovich 1028bd1ebe9dSAlexander Yermolovich assert((P->Kind == DebugPatchKind::NewDebugEntry || 1029bd1ebe9dSAlexander Yermolovich Offset + ByteSequence.size() <= BinaryContents.size()) && 10301c2f4bbeSAlexander Yermolovich "Applied patch runs over binary size."); 10311c2f4bbeSAlexander Yermolovich uint32_t Length = Offset - StartOffset; 10321c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 10331c2f4bbeSAlexander Yermolovich Length); 10341c2f4bbeSAlexander Yermolovich NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 10351c2f4bbeSAlexander Yermolovich StartOffset = Offset + OldValueSize; 10361c2f4bbeSAlexander Yermolovich } 10371c2f4bbeSAlexander Yermolovich uint32_t Length = BinaryContents.size() - StartOffset; 10381c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 10391c2f4bbeSAlexander Yermolovich Length); 10401c2f4bbeSAlexander Yermolovich DebugPatches.clear(); 10411c2f4bbeSAlexander Yermolovich 10421c2f4bbeSAlexander Yermolovich // Patching lengths of CUs 10431c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 10441c2f4bbeSAlexander Yermolovich Patch.second = NewBinaryContents.size() - 4 - Patch.first; 10451c2f4bbeSAlexander Yermolovich for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 10461c2f4bbeSAlexander Yermolovich const auto &Patch = LengthPatches[J]; 10471c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, Patch.second); 10481c2f4bbeSAlexander Yermolovich Offset = Patch.first; 10491c2f4bbeSAlexander Yermolovich for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 10501c2f4bbeSAlexander Yermolovich NewBinaryContents[Offset + I] = ByteSequence[I]; 10511c2f4bbeSAlexander Yermolovich } 10521c2f4bbeSAlexander Yermolovich 10531c2f4bbeSAlexander Yermolovich return NewBinaryContents; 1054a34c753fSRafael Auler } 1055a34c753fSRafael Auler 1056a34c753fSRafael Auler void DebugStrWriter::create() { 1057a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 1058a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 1059a34c753fSRafael Auler } 1060a34c753fSRafael Auler 1061a34c753fSRafael Auler void DebugStrWriter::initialize() { 1062a34c753fSRafael Auler auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); 1063a34c753fSRafael Auler (*StrStream) << StrSection; 1064a34c753fSRafael Auler } 1065a34c753fSRafael Auler 1066a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 1067e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 1068a34c753fSRafael Auler if (StrBuffer->empty()) 1069a34c753fSRafael Auler initialize(); 1070a34c753fSRafael Auler auto Offset = StrBuffer->size(); 1071a34c753fSRafael Auler (*StrStream) << Str; 1072a34c753fSRafael Auler StrStream->write_zeros(1); 1073a34c753fSRafael Auler return Offset; 1074a34c753fSRafael Auler } 1075a34c753fSRafael Auler 1076a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 1077a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 1078a34c753fSRafael Auler if (!Abbrevs) 1079a34c753fSRafael Auler return; 1080a34c753fSRafael Auler 108145f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 1082bd1ebe9dSAlexander Yermolovich const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 1083a34c753fSRafael Auler 10849f3f9d19SAlexander Yermolovich // We are duplicating abbrev sections, to handle the case where for one CU we 10859f3f9d19SAlexander Yermolovich // modify it, but for another we don't. 10869f3f9d19SAlexander Yermolovich auto UnitDataPtr = std::make_unique<AbbrevData>(); 10879f3f9d19SAlexander Yermolovich AbbrevData &UnitData = *UnitDataPtr.get(); 10889f3f9d19SAlexander Yermolovich UnitData.Buffer = std::make_unique<DebugBufferVector>(); 10899f3f9d19SAlexander Yermolovich UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 1090bd1ebe9dSAlexander Yermolovich 1091a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 1092a34c753fSRafael Auler 10939f3f9d19SAlexander Yermolovich // Returns true if AbbrevData is re-used, false otherwise. 10949f3f9d19SAlexander Yermolovich auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 10959f3f9d19SAlexander Yermolovich llvm::SHA1 Hasher; 10969f3f9d19SAlexander Yermolovich Hasher.update(AbbrevData); 1097330268baSArgyrios Kyrtzidis std::array<uint8_t, 20> Hash = Hasher.final(); 1098330268baSArgyrios Kyrtzidis StringRef Key((const char *)Hash.data(), Hash.size()); 10999f3f9d19SAlexander Yermolovich auto Iter = AbbrevDataCache.find(Key); 11009f3f9d19SAlexander Yermolovich if (Iter != AbbrevDataCache.end()) { 11019f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = Iter->second.get(); 11029f3f9d19SAlexander Yermolovich return true; 11039f3f9d19SAlexander Yermolovich } 11049f3f9d19SAlexander Yermolovich AbbrevDataCache[Key] = std::move(UnitDataPtr); 11059f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = &UnitData; 11069f3f9d19SAlexander Yermolovich return false; 11079f3f9d19SAlexander Yermolovich }; 1108a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 1109a34c753fSRafael Auler // contents. 1110bd1ebe9dSAlexander Yermolovich if (UnitPatches.empty() && AbbrevEntries.empty()) { 1111a34c753fSRafael Auler StringRef AbbrevSectionContents = 1112a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 1113a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 1114a34c753fSRafael Auler StringRef AbbrevContents; 1115a34c753fSRafael Auler 1116a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 1117a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 1118a34c753fSRafael Auler // Handle DWP section contribution. 1119a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 1120a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 1121a34c753fSRafael Auler if (!DWOEntry) 1122a34c753fSRafael Auler return; 1123a34c753fSRafael Auler 1124a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 1125a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 1126a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 1127a34c753fSRafael Auler DWOContrubution->Length); 112845f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 1129a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 113045f94abcSMaksim Panchenko 113145f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 113245f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 113345f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 113445f94abcSMaksim Panchenko // the set boundaries. 113545f94abcSMaksim Panchenko // 113645f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 113745f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 113845f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 11391c2f4bbeSAlexander Yermolovich for_each( 114045f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 114145f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 114245f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 114345f94abcSMaksim Panchenko }); 11441c2f4bbeSAlexander Yermolovich sort(AbbrevSetOffsets); 114545f94abcSMaksim Panchenko } 11461c2f4bbeSAlexander Yermolovich auto It = upper_bound(AbbrevSetOffsets, StartOffset); 114745f94abcSMaksim Panchenko const uint64_t EndOffset = 114845f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 1149a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 115045f94abcSMaksim Panchenko } else { 115145f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 115245f94abcSMaksim Panchenko // abbreviations for this unit only. 115345f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 1154a34c753fSRafael Auler } 1155a34c753fSRafael Auler 11569f3f9d19SAlexander Yermolovich if (!hashAndAddAbbrev(AbbrevContents)) { 1157a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 1158a34c753fSRafael Auler OS << AbbrevContents; 11599f3f9d19SAlexander Yermolovich } 1160a34c753fSRafael Auler return; 1161a34c753fSRafael Auler } 1162a34c753fSRafael Auler 1163a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 1164a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 1165a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 1166a34c753fSRafael Auler 1167a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 1168a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 1169a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 1170a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 1171a34c753fSRafael Auler Abbrev.attributes()) { 1172a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 1173a34c753fSRafael Auler bool Patched = false; 1174a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 1175a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 1176a34c753fSRafael Auler ++I) { 1177a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 1178a34c753fSRafael Auler continue; 1179a34c753fSRafael Auler 1180a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 1181a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 1182a34c753fSRafael Auler Patched = true; 1183a34c753fSRafael Auler break; 1184a34c753fSRafael Auler } 1185a34c753fSRafael Auler if (Patched) 1186a34c753fSRafael Auler continue; 1187a34c753fSRafael Auler } 1188a34c753fSRafael Auler 1189a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 1190a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 1191a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 1192a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 1193a34c753fSRafael Auler } 1194bd1ebe9dSAlexander Yermolovich const auto Entries = AbbrevEntries.find(&Abbrev); 1195bd1ebe9dSAlexander Yermolovich // Adding new Abbrevs for inserted entries. 1196bd1ebe9dSAlexander Yermolovich if (Entries != AbbrevEntries.end()) { 1197bd1ebe9dSAlexander Yermolovich for (const AbbrevEntry &Entry : Entries->second) { 1198bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Attr, OS); 1199bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Form, OS); 1200bd1ebe9dSAlexander Yermolovich } 1201bd1ebe9dSAlexander Yermolovich } 1202a34c753fSRafael Auler encodeULEB128(0, OS); 1203a34c753fSRafael Auler encodeULEB128(0, OS); 1204a34c753fSRafael Auler } 1205a34c753fSRafael Auler encodeULEB128(0, OS); 12069f3f9d19SAlexander Yermolovich 12079f3f9d19SAlexander Yermolovich hashAndAddAbbrev(OS.str()); 1208a34c753fSRafael Auler } 1209a34c753fSRafael Auler 1210a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 12119f3f9d19SAlexander Yermolovich // Used to create determinism for writing out abbrevs. 12129f3f9d19SAlexander Yermolovich std::vector<AbbrevData *> Abbrevs; 121345f94abcSMaksim Panchenko if (DWOId) { 121445f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 121545f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 121645f94abcSMaksim Panchenko // set with the CU. 12171417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 12181417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 121945f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 12201417f607SAlexander Yermolovich if (!IsDWP) { 122145f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 122245f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 122345f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 122445f94abcSMaksim Panchenko "Unable to update debug info.\n"; 122545f94abcSMaksim Panchenko exit(1); 122645f94abcSMaksim Panchenko } 122745f94abcSMaksim Panchenko } 122845f94abcSMaksim Panchenko } 122945f94abcSMaksim Panchenko 12309f3f9d19SAlexander Yermolovich DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 123145f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 123245f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 12339f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 12349f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 12359f3f9d19SAlexander Yermolovich } else { 12369f3f9d19SAlexander Yermolovich Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 12379f3f9d19SAlexander Yermolovich std::unordered_set<AbbrevData *> ProcessedAbbrevs; 12389f3f9d19SAlexander Yermolovich // Add abbreviations from compile and type non-DWO units. 12399f3f9d19SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 12409f3f9d19SAlexander Yermolovich addUnitAbbreviations(*Unit); 12419f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 12429f3f9d19SAlexander Yermolovich if (!ProcessedAbbrevs.insert(Abbrev).second) 12439f3f9d19SAlexander Yermolovich continue; 12449f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 12459f3f9d19SAlexander Yermolovich } 124645f94abcSMaksim Panchenko } 124745f94abcSMaksim Panchenko 1248a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 1249a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 1250a34c753fSRafael Auler uint64_t Size = 0; 12519f3f9d19SAlexander Yermolovich for (const AbbrevData *UnitData : Abbrevs) 12529f3f9d19SAlexander Yermolovich Size += UnitData->Buffer->size(); 12539f3f9d19SAlexander Yermolovich 1254a34c753fSRafael Auler ReturnBuffer.reserve(Size); 1255a34c753fSRafael Auler 1256a34c753fSRafael Auler uint64_t Pos = 0; 12579f3f9d19SAlexander Yermolovich for (AbbrevData *UnitData : Abbrevs) { 12589f3f9d19SAlexander Yermolovich ReturnBuffer.append(*UnitData->Buffer); 12599f3f9d19SAlexander Yermolovich UnitData->Offset = Pos; 12609f3f9d19SAlexander Yermolovich Pos += UnitData->Buffer->size(); 1261a34c753fSRafael Auler 12629f3f9d19SAlexander Yermolovich UnitData->Buffer.reset(); 12639f3f9d19SAlexander Yermolovich UnitData->Stream.reset(); 1264a34c753fSRafael Auler } 1265a34c753fSRafael Auler 1266a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 1267a34c753fSRafael Auler } 1268a34c753fSRafael Auler 1269a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 1270a34c753fSRafael Auler MCDwarfLineTableParams Params, 1271a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 1272a34c753fSRafael Auler int PointerSize) { 1273a34c753fSRafael Auler // emit the sequence to set the address 1274a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 1275a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 1276a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 1277a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 1278a34c753fSRafael Auler 1279a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 1280a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 1281a34c753fSRafael Auler } 1282a34c753fSRafael Auler 1283a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 1284a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 1285a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 1286a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 1287a34c753fSRafael Auler if (InputSequences.empty()) 1288a34c753fSRafael Auler return; 1289a34c753fSRafael Auler 1290a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 1291a34c753fSRafael Auler unsigned FileNum = 1; 1292a34c753fSRafael Auler unsigned LastLine = 1; 1293a34c753fSRafael Auler unsigned Column = 0; 1294a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1295a34c753fSRafael Auler unsigned Isa = 0; 1296a34c753fSRafael Auler unsigned Discriminator = 0; 1297a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 1298a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 1299a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1300a34c753fSRafael Auler 1301a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 1302a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1303a34c753fSRafael Auler FileNum = 1; 1304a34c753fSRafael Auler LastLine = 1; 1305a34c753fSRafael Auler Column = 0; 1306a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1307a34c753fSRafael Auler Isa = 0; 1308a34c753fSRafael Auler Discriminator = 0; 1309a34c753fSRafael Auler LastAddress = InvalidAddress; 1310a34c753fSRafael Auler }; 1311a34c753fSRafael Auler 1312a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1313a34c753fSRafael Auler const uint64_t SequenceStart = 1314a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 1315a34c753fSRafael Auler 1316a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 1317a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1318a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 1319a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1320a34c753fSRafael Auler } 1321a34c753fSRafael Auler 1322a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 1323a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 1324a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1325a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1326a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 1327a34c753fSRafael Auler 1328a34c753fSRafael Auler if (FileNum != Row.File) { 1329a34c753fSRafael Auler FileNum = Row.File; 1330a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1331a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1332a34c753fSRafael Auler } 1333a34c753fSRafael Auler if (Column != Row.Column) { 1334a34c753fSRafael Auler Column = Row.Column; 1335a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1336a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1337a34c753fSRafael Auler } 1338a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 1339a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1340a34c753fSRafael Auler Discriminator = Row.Discriminator; 1341a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1342a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1343a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1344a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1345a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1346a34c753fSRafael Auler } 1347a34c753fSRafael Auler if (Isa != Row.Isa) { 1348a34c753fSRafael Auler Isa = Row.Isa; 1349a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1350a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1351a34c753fSRafael Auler } 1352a34c753fSRafael Auler if (Row.IsStmt != Flags) { 1353a34c753fSRafael Auler Flags = Row.IsStmt; 1354a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1355a34c753fSRafael Auler } 1356a34c753fSRafael Auler if (Row.BasicBlock) 1357a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1358a34c753fSRafael Auler if (Row.PrologueEnd) 1359a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1360a34c753fSRafael Auler if (Row.EpilogueBegin) 1361a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1362a34c753fSRafael Auler 1363a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 1364a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 1365a34c753fSRafael Auler if (Row.EndSequence) { 1366a34c753fSRafael Auler emitEndOfSequence(Address); 1367a34c753fSRafael Auler } else { 1368a34c753fSRafael Auler if (LastAddress == InvalidAddress) 1369a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1370a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1371a34c753fSRafael Auler else 1372a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1373a34c753fSRafael Auler 1374a34c753fSRafael Auler LastAddress = Address; 1375a34c753fSRafael Auler LastLine = Row.Line; 1376a34c753fSRafael Auler } 1377a34c753fSRafael Auler 1378a34c753fSRafael Auler Discriminator = 0; 1379a34c753fSRafael Auler } 1380a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 1381a34c753fSRafael Auler } 1382a34c753fSRafael Auler 1383a34c753fSRafael Auler // Finish with the end of the sequence. 1384a34c753fSRafael Auler if (LastAddress != InvalidAddress) 1385a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1386a34c753fSRafael Auler } 1387a34c753fSRafael Auler 1388a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 1389a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 1390a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 1391a34c753fSRafael Auler static inline void emitDwarfLineTable( 1392a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 1393a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1394a34c753fSRafael Auler unsigned FileNum = 1; 1395a34c753fSRafael Auler unsigned LastLine = 1; 1396a34c753fSRafael Auler unsigned Column = 0; 1397a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1398a34c753fSRafael Auler unsigned Isa = 0; 1399a34c753fSRafael Auler unsigned Discriminator = 0; 1400a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 1401a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1402a34c753fSRafael Auler 1403a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1404a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1405a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1406a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1407a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1408a34c753fSRafael Auler FileNum = 1; 1409a34c753fSRafael Auler LastLine = 1; 1410a34c753fSRafael Auler Column = 0; 1411a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1412a34c753fSRafael Auler Isa = 0; 1413a34c753fSRafael Auler Discriminator = 0; 1414a34c753fSRafael Auler LastLabel = nullptr; 1415a34c753fSRafael Auler continue; 1416a34c753fSRafael Auler } 1417a34c753fSRafael Auler 1418a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1419a34c753fSRafael Auler 1420a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 1421a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 1422a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1423a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1424a34c753fSRafael Auler } 1425a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 1426a34c753fSRafael Auler Column = LineEntry.getColumn(); 1427a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1428a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1429a34c753fSRafael Auler } 1430a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 1431*014cd37fSAlexander Yermolovich MCOS->getContext().getDwarfVersion() >= 2) { 1432a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 1433a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1434a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1435a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1436a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1437a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1438a34c753fSRafael Auler } 1439a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 1440a34c753fSRafael Auler Isa = LineEntry.getIsa(); 1441a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1442a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1443a34c753fSRafael Auler } 1444a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1445a34c753fSRafael Auler Flags = LineEntry.getFlags(); 1446a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1447a34c753fSRafael Auler } 1448a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1449a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1450a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1451a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1452a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1453a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1454a34c753fSRafael Auler 1455a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 1456a34c753fSRafael Auler 1457a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 1458a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 1459a34c753fSRafael Auler // Label and the current Label. 1460a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1461a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1462a34c753fSRafael Auler Discriminator = 0; 1463a34c753fSRafael Auler LastLine = LineEntry.getLine(); 1464a34c753fSRafael Auler LastLabel = Label; 1465a34c753fSRafael Auler } 1466a34c753fSRafael Auler 1467a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 1468a34c753fSRafael Auler } 1469a34c753fSRafael Auler 1470a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1471b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 1472b73c87bcSMaksim Panchenko BinaryContext &BC) const { 1473a34c753fSRafael Auler if (!RawData.empty()) { 1474a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 1475a34c753fSRafael Auler InputSequences.empty() && 1476a34c753fSRafael Auler "cannot combine raw data with new line entries"); 1477a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 1478a34c753fSRafael Auler MCOS->emitBytes(RawData); 1479a34c753fSRafael Auler 1480b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 1481b73c87bcSMaksim Panchenko // 1482b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1483b73c87bcSMaksim Panchenko // without relocations. 1484b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 1485b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1486b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1487b73c87bcSMaksim Panchenko 1488a34c753fSRafael Auler return; 1489a34c753fSRafael Auler } 1490a34c753fSRafael Auler 1491a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1492a34c753fSRafael Auler 1493a34c753fSRafael Auler // Put out the line tables. 1494a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1495a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1496a34c753fSRafael Auler 1497a34c753fSRafael Auler // Emit line tables for the original code. 1498a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1499a34c753fSRafael Auler 1500a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 1501a34c753fSRafael Auler // of this section (that was used in a previous expression). 1502a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 1503a34c753fSRafael Auler } 1504a34c753fSRafael Auler 1505*014cd37fSAlexander Yermolovich // Helper function to parse .debug_line_str, and populate one we are using. 1506*014cd37fSAlexander Yermolovich // For functions that we do not modify we output them as raw data. 1507*014cd37fSAlexander Yermolovich // Re-constructing .debug_line_str so that offsets are correct for those 1508*014cd37fSAlexander Yermolovich // debut line tables. 1509*014cd37fSAlexander Yermolovich // Bonus is that when we output a final binary we can re-use .debug_line_str 1510*014cd37fSAlexander Yermolovich // section. So we don't have to do the SHF_ALLOC trick we did with 1511*014cd37fSAlexander Yermolovich // .debug_line. 1512*014cd37fSAlexander Yermolovich static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, 1513*014cd37fSAlexander Yermolovich MCDwarfLineStr &LineStr, 1514*014cd37fSAlexander Yermolovich BinaryContext &BC, 1515*014cd37fSAlexander Yermolovich MCStreamer &Streamer) { 1516*014cd37fSAlexander Yermolovich DataExtractor StrData(LineStrSection.getContents(), 1517*014cd37fSAlexander Yermolovich BC.DwCtx->isLittleEndian(), 0); 1518*014cd37fSAlexander Yermolovich uint64_t Offset = 0; 1519*014cd37fSAlexander Yermolovich while (StrData.isValidOffset(Offset)) { 1520*014cd37fSAlexander Yermolovich Error Err = Error::success(); 1521*014cd37fSAlexander Yermolovich const char *CStr = StrData.getCStr(&Offset, &Err); 1522*014cd37fSAlexander Yermolovich if (Err) { 1523*014cd37fSAlexander Yermolovich errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; 1524*014cd37fSAlexander Yermolovich continue; 1525*014cd37fSAlexander Yermolovich } 1526*014cd37fSAlexander Yermolovich LineStr.emitRef(&Streamer, CStr); 1527*014cd37fSAlexander Yermolovich } 1528*014cd37fSAlexander Yermolovich } 1529*014cd37fSAlexander Yermolovich 1530a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1531a34c753fSRafael Auler MCAssembler &Assembler = 1532a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1533a34c753fSRafael Auler 1534a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1535a34c753fSRafael Auler 1536a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 1537a34c753fSRafael Auler 1538a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 1539a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 1540a34c753fSRafael Auler if (LineTables.empty()) 1541a34c753fSRafael Auler return; 1542a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 1543a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 1544*014cd37fSAlexander Yermolovich ErrorOr<BinarySection &> LineStrSection = 1545*014cd37fSAlexander Yermolovich BC.getUniqueSectionByName(".debug_line_str"); 1546*014cd37fSAlexander Yermolovich // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower 1547*014cd37fSAlexander Yermolovich // .debug_line 1548*014cd37fSAlexander Yermolovich if (LineStrSection) { 1549a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 1550*014cd37fSAlexander Yermolovich parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer); 1551*014cd37fSAlexander Yermolovich } 1552a34c753fSRafael Auler 1553a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 1554a34c753fSRafael Auler Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); 1555a34c753fSRafael Auler 1556*014cd37fSAlexander Yermolovich const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); 1557a34c753fSRafael Auler // Handle the rest of the Compile Units. 1558a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 1559*014cd37fSAlexander Yermolovich Streamer.getContext().setDwarfVersion( 1560*014cd37fSAlexander Yermolovich CUIDTablePair.second.getDwarfVersion()); 1561b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1562a34c753fSRafael Auler } 1563*014cd37fSAlexander Yermolovich 1564*014cd37fSAlexander Yermolovich // Resetting DWARF version for rest of the flow. 1565*014cd37fSAlexander Yermolovich BC.Ctx->setDwarfVersion(DwarfVersion); 1566*014cd37fSAlexander Yermolovich 1567*014cd37fSAlexander Yermolovich // Still need to write the section out for the ExecutionEngine, and temp in 1568*014cd37fSAlexander Yermolovich // memory object we are constructing. 1569*014cd37fSAlexander Yermolovich if (LineStr) { 1570*014cd37fSAlexander Yermolovich LineStr->emitSection(&Streamer); 1571*014cd37fSAlexander Yermolovich SmallString<0> Data = LineStr->getFinalizedData(); 1572*014cd37fSAlexander Yermolovich BC.registerOrUpdateNoteSection(".debug_line_str", copyByteArray(Data.str()), 1573*014cd37fSAlexander Yermolovich Data.size()); 1574*014cd37fSAlexander Yermolovich } 1575a34c753fSRafael Auler } 1576a34c753fSRafael Auler 1577a34c753fSRafael Auler } // namespace bolt 1578a34c753fSRafael Auler } // namespace llvm 1579