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" 15014cd37fSAlexander 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" 19014cd37fSAlexander 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> 32ba1ac98cSAlexander Yermolovich #include <vector> 33a34c753fSRafael Auler 34a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info" 35a34c753fSRafael Auler 36a34c753fSRafael Auler namespace opts { 37a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity; 381c2f4bbeSAlexander Yermolovich } // namespace opts 39a34c753fSRafael Auler 40a34c753fSRafael Auler namespace llvm { 41f8c7fb49SAmir Ayupov class MCSymbol; 42f8c7fb49SAmir Ayupov 43a34c753fSRafael Auler namespace bolt { 44a34c753fSRafael Auler 45bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> 46bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE, 47bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl, 48bd1ebe9dSAlexander Yermolovich uint32_t Index) { 49bd1ebe9dSAlexander Yermolovich const DWARFUnit &U = *DIE.getDwarfUnit(); 50bd1ebe9dSAlexander Yermolovich uint64_t Offset = 51bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U); 52bd1ebe9dSAlexander Yermolovich Optional<DWARFFormValue> Value = 53bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U); 54bd1ebe9dSAlexander Yermolovich if (!Value) 55bd1ebe9dSAlexander Yermolovich return None; 56bd1ebe9dSAlexander Yermolovich // AttributeSpec 57bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal = 58bd1ebe9dSAlexander Yermolovich AbbrevDecl->attributes().begin() + Index; 59bd1ebe9dSAlexander Yermolovich uint32_t ValSize = 0; 60bd1ebe9dSAlexander Yermolovich Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U); 61bd1ebe9dSAlexander Yermolovich if (ValSizeOpt) { 62bd1ebe9dSAlexander Yermolovich ValSize = static_cast<uint32_t>(*ValSizeOpt); 63bd1ebe9dSAlexander Yermolovich } else { 64bd1ebe9dSAlexander Yermolovich DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 65bd1ebe9dSAlexander Yermolovich uint64_t NewOffset = Offset; 66bd1ebe9dSAlexander Yermolovich DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset, 67bd1ebe9dSAlexander Yermolovich U.getFormParams()); 68bd1ebe9dSAlexander Yermolovich // This includes entire size of the entry, which might not be just the 69bd1ebe9dSAlexander Yermolovich // encoding part. For example for DW_AT_loc it will include expression 70bd1ebe9dSAlexander Yermolovich // location. 71bd1ebe9dSAlexander Yermolovich ValSize = NewOffset - Offset; 72bd1ebe9dSAlexander Yermolovich } 731c6dc43dSAlexander Yermolovich return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize}; 741c6dc43dSAlexander Yermolovich } 75bd1ebe9dSAlexander Yermolovich 761c6dc43dSAlexander Yermolovich Optional<AttrInfo> findAttributeInfo(const DWARFDie DIE, 771c6dc43dSAlexander Yermolovich dwarf::Attribute Attr) { 781c6dc43dSAlexander Yermolovich if (!DIE.isValid()) 791c6dc43dSAlexander Yermolovich return None; 801c6dc43dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl = 811c6dc43dSAlexander Yermolovich DIE.getAbbreviationDeclarationPtr(); 821c6dc43dSAlexander Yermolovich if (!AbbrevDecl) 831c6dc43dSAlexander Yermolovich return None; 841c6dc43dSAlexander Yermolovich Optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr); 851c6dc43dSAlexander Yermolovich if (!Index) 861c6dc43dSAlexander Yermolovich return None; 871c6dc43dSAlexander Yermolovich return findAttributeInfo(DIE, AbbrevDecl, *Index); 88bd1ebe9dSAlexander Yermolovich } 89bd1ebe9dSAlexander Yermolovich 90a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 91a34c753fSRafael Auler 92a34c753fSRafael Auler namespace { 93a34c753fSRafael Auler 941c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED 951c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) { 961c2f4bbeSAlexander Yermolovich for (uint32_t I = 0, Size = S.size(); I < Size; ++I) { 971c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr(S[I]); 981c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr((int8_t)S[I]); 991c2f4bbeSAlexander Yermolovich } 1001c2f4bbeSAlexander Yermolovich errs() << "\n"; 1011c2f4bbeSAlexander Yermolovich } 1021c2f4bbeSAlexander Yermolovich 103a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size). 104a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of 105a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address). 106a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes. 107a34c753fSRafael Auler // Returns the number of written bytes. 10840c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream, 109a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges, 110a34c753fSRafael Auler const bool WriteRelativeRanges = false) { 111a34c753fSRafael Auler for (const DebugAddressRange &Range : AddressRanges) { 112a34c753fSRafael Auler support::endian::write(Stream, Range.LowPC, support::little); 113a34c753fSRafael Auler support::endian::write( 114a34c753fSRafael Auler Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 115a34c753fSRafael Auler support::little); 116a34c753fSRafael Auler } 117a34c753fSRafael Auler // Finish with 0 entries. 118a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 119a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 120a34c753fSRafael Auler return AddressRanges.size() * 16 + 16; 121a34c753fSRafael Auler } 122a34c753fSRafael Auler 123a34c753fSRafael Auler } // namespace 124a34c753fSRafael Auler 125a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() { 126a34c753fSRafael Auler RangesBuffer = std::make_unique<DebugBufferVector>(); 127a34c753fSRafael Auler RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 128a34c753fSRafael Auler 129a34c753fSRafael Auler // Add an empty range as the first entry; 130a34c753fSRafael Auler SectionOffset += 131a34c753fSRafael Auler writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 132014cd37fSAlexander Yermolovich Kind = RangesWriterKind::DebugRangesWriter; 133a34c753fSRafael Auler } 134a34c753fSRafael Auler 135a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges( 136a34c753fSRafael Auler DebugAddressRangesVector &&Ranges, 137a34c753fSRafael Auler std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 138a34c753fSRafael Auler if (Ranges.empty()) 139a34c753fSRafael Auler return getEmptyRangesOffset(); 140a34c753fSRafael Auler 141a34c753fSRafael Auler const auto RI = CachedRanges.find(Ranges); 142a34c753fSRafael Auler if (RI != CachedRanges.end()) 143a34c753fSRafael Auler return RI->second; 144a34c753fSRafael Auler 145a34c753fSRafael Auler const uint64_t EntryOffset = addRanges(Ranges); 146a34c753fSRafael Auler CachedRanges.emplace(std::move(Ranges), EntryOffset); 147a34c753fSRafael Auler 148a34c753fSRafael Auler return EntryOffset; 149a34c753fSRafael Auler } 150a34c753fSRafael Auler 151a34c753fSRafael Auler uint64_t 152a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) { 153a34c753fSRafael Auler if (Ranges.empty()) 154a34c753fSRafael Auler return getEmptyRangesOffset(); 155a34c753fSRafael Auler 156a34c753fSRafael Auler // Reading the SectionOffset and updating it should be atomic to guarantee 157a34c753fSRafael Auler // unique and correct offsets in patches. 158a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 159a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 160a34c753fSRafael Auler SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges); 161a34c753fSRafael Auler 162a34c753fSRafael Auler return EntryOffset; 163a34c753fSRafael Auler } 164a34c753fSRafael Auler 165a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() { 166a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 167a34c753fSRafael Auler return SectionOffset; 168a34c753fSRafael Auler } 169a34c753fSRafael Auler 170014cd37fSAlexander Yermolovich DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr; 171014cd37fSAlexander Yermolovich 172014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges( 173014cd37fSAlexander Yermolovich DebugAddressRangesVector &&Ranges, 174014cd37fSAlexander Yermolovich std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 175014cd37fSAlexander Yermolovich return addRanges(Ranges); 176014cd37fSAlexander Yermolovich } 177014cd37fSAlexander Yermolovich 178014cd37fSAlexander Yermolovich struct LocListsRangelistsHeader { 179014cd37fSAlexander Yermolovich UnitLengthType UnitLength; // Size of loclist entris section, not including 180014cd37fSAlexander Yermolovich // size of header. 181014cd37fSAlexander Yermolovich VersionType Version; 182014cd37fSAlexander Yermolovich AddressSizeType AddressSize; 183014cd37fSAlexander Yermolovich SegmentSelectorType SegmentSelector; 184014cd37fSAlexander Yermolovich OffsetEntryCountType OffsetEntryCount; 185014cd37fSAlexander Yermolovich }; 186014cd37fSAlexander Yermolovich 187014cd37fSAlexander Yermolovich static std::unique_ptr<DebugBufferVector> 188014cd37fSAlexander Yermolovich getDWARF5Header(const LocListsRangelistsHeader &Header) { 189014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> HeaderBuffer = 190014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 191014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> HeaderStream = 192014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*HeaderBuffer); 193014cd37fSAlexander Yermolovich 194014cd37fSAlexander Yermolovich // 7.29 length of the set of entries for this compilation unit, not including 195014cd37fSAlexander Yermolovich // the length field itself 196014cd37fSAlexander Yermolovich const uint32_t HeaderSize = 197014cd37fSAlexander Yermolovich getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType); 198014cd37fSAlexander Yermolovich 199014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize, 200014cd37fSAlexander Yermolovich support::little); 201014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.Version, support::little); 202014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.AddressSize, support::little); 203014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.SegmentSelector, 204014cd37fSAlexander Yermolovich support::little); 205014cd37fSAlexander Yermolovich support::endian::write(*HeaderStream, Header.OffsetEntryCount, 206014cd37fSAlexander Yermolovich support::little); 207014cd37fSAlexander Yermolovich return HeaderBuffer; 208014cd37fSAlexander Yermolovich } 209014cd37fSAlexander Yermolovich 210014cd37fSAlexander Yermolovich uint64_t DebugRangeListsSectionWriter::addRanges( 211014cd37fSAlexander Yermolovich const DebugAddressRangesVector &Ranges) { 212014cd37fSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 213014cd37fSAlexander Yermolovich 214014cd37fSAlexander Yermolovich RangeEntries.push_back(CurrentOffset); 215014cd37fSAlexander Yermolovich for (const DebugAddressRange &Range : Ranges) { 216014cd37fSAlexander Yermolovich support::endian::write(*CUBodyStream, 217014cd37fSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_RLE_startx_length), 218014cd37fSAlexander Yermolovich support::little); 219ba1ac98cSAlexander Yermolovich uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU); 220014cd37fSAlexander Yermolovich encodeULEB128(Index, *CUBodyStream); 221014cd37fSAlexander Yermolovich encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream); 222014cd37fSAlexander Yermolovich } 223014cd37fSAlexander Yermolovich support::endian::write(*CUBodyStream, 224014cd37fSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_RLE_end_of_list), 225014cd37fSAlexander Yermolovich support::little); 226014cd37fSAlexander Yermolovich CurrentOffset = CUBodyBuffer->size(); 227014cd37fSAlexander Yermolovich return RangeEntries.size() - 1; 228014cd37fSAlexander Yermolovich } 229014cd37fSAlexander Yermolovich 230014cd37fSAlexander Yermolovich void DebugRangeListsSectionWriter::finalizeSection() { 231014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> CUArrayBuffer = 232014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 233014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> CUArrayStream = 234014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*CUArrayBuffer); 235014cd37fSAlexander Yermolovich constexpr uint32_t SizeOfArrayEntry = 4; 236014cd37fSAlexander Yermolovich const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry; 237014cd37fSAlexander Yermolovich for (uint32_t Offset : RangeEntries) 238014cd37fSAlexander Yermolovich support::endian::write(*CUArrayStream, Offset + SizeOfArraySection, 239014cd37fSAlexander Yermolovich support::little); 240014cd37fSAlexander Yermolovich 241014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 242014cd37fSAlexander Yermolovich {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()), 243014cd37fSAlexander Yermolovich 5, 8, 0, static_cast<uint32_t>(RangeEntries.size())}); 244014cd37fSAlexander Yermolovich *RangesStream << *Header; 245014cd37fSAlexander Yermolovich *RangesStream << *CUArrayBuffer; 246014cd37fSAlexander Yermolovich *RangesStream << *CUBodyBuffer; 247014cd37fSAlexander Yermolovich SectionOffset = RangesBuffer->size(); 248014cd37fSAlexander Yermolovich } 249014cd37fSAlexander Yermolovich 250ba1ac98cSAlexander Yermolovich void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) { 251014cd37fSAlexander Yermolovich CUBodyBuffer = std::make_unique<DebugBufferVector>(); 252014cd37fSAlexander Yermolovich CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer); 253014cd37fSAlexander Yermolovich RangeEntries.clear(); 254014cd37fSAlexander Yermolovich CurrentOffset = 0; 255ba1ac98cSAlexander Yermolovich CU = &Unit; 256014cd37fSAlexander Yermolovich } 257014cd37fSAlexander Yermolovich 258a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 259a34c753fSRafael Auler DebugAddressRangesVector &&Ranges) { 260a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 261a34c753fSRafael Auler CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 262a34c753fSRafael Auler } 263a34c753fSRafael Auler 264a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection( 265612f0f45SAlexander Yermolovich raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const { 266a34c753fSRafael Auler // For reference on the format of the .debug_aranges section, see the DWARF4 267a34c753fSRafael Auler // specification, section 6.1.4 Lookup by Address 268a34c753fSRafael Auler // http://www.dwarfstd.org/doc/DWARF4.pdf 269a34c753fSRafael Auler for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 270a34c753fSRafael Auler const uint64_t Offset = CUOffsetAddressRangesPair.first; 271a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges = 272a34c753fSRafael Auler CUOffsetAddressRangesPair.second; 273a34c753fSRafael Auler 274a34c753fSRafael Auler // Emit header. 275a34c753fSRafael Auler 276a34c753fSRafael Auler // Size of this set: 8 (size of the header) + 4 (padding after header) 277a34c753fSRafael Auler // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 278a34c753fSRafael Auler // pair of uint64_t's for the terminating, zero-length range. 279a34c753fSRafael Auler // Does not include size field itself. 280a34c753fSRafael Auler uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 281a34c753fSRafael Auler 282a34c753fSRafael Auler // Header field #1: set size. 283a34c753fSRafael Auler support::endian::write(RangesStream, Size, support::little); 284a34c753fSRafael Auler 285a34c753fSRafael Auler // Header field #2: version number, 2 as per the specification. 286a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint16_t>(2), 287a34c753fSRafael Auler support::little); 288a34c753fSRafael Auler 2891c2f4bbeSAlexander Yermolovich assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map"); 290a34c753fSRafael Auler // Header field #3: debug info offset of the correspondent compile unit. 291612f0f45SAlexander Yermolovich support::endian::write( 292612f0f45SAlexander Yermolovich RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset), 293a34c753fSRafael Auler support::little); 294a34c753fSRafael Auler 295a34c753fSRafael Auler // Header field #4: address size. 296a34c753fSRafael Auler // 8 since we only write ELF64 binaries for now. 297a34c753fSRafael Auler RangesStream << char(8); 298a34c753fSRafael Auler 299a34c753fSRafael Auler // Header field #5: segment size of target architecture. 300a34c753fSRafael Auler RangesStream << char(0); 301a34c753fSRafael Auler 302a34c753fSRafael Auler // Padding before address table - 4 bytes in the 64-bit-pointer case. 303a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint32_t>(0), 304a34c753fSRafael Auler support::little); 305a34c753fSRafael Auler 306a34c753fSRafael Auler writeAddressRanges(RangesStream, AddressRanges, true); 307a34c753fSRafael Auler } 308a34c753fSRafael Auler } 309a34c753fSRafael Auler 310a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; } 311a34c753fSRafael Auler 312a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() { 313a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 314a34c753fSRafael Auler indexToAdddessEnd()); 315a34c753fSRafael Auler // Sorting address in increasing order of indices. 316a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 317a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 318a34c753fSRafael Auler return A.first < B.first; 319a34c753fSRafael Auler }); 320a34c753fSRafael Auler for (auto &Pair : SortedMap) 321a34c753fSRafael Auler dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 322a34c753fSRafael Auler } 323ba1ac98cSAlexander Yermolovich uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { 324e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 325ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(CU); 326014cd37fSAlexander Yermolovich if (!AddressMaps.count(CUID)) 327014cd37fSAlexander Yermolovich AddressMaps[CUID] = AddressForDWOCU(); 328a34c753fSRafael Auler 329014cd37fSAlexander Yermolovich AddressForDWOCU &Map = AddressMaps[CUID]; 330a34c753fSRafael Auler auto Entry = Map.find(Address); 331a34c753fSRafael Auler if (Entry == Map.end()) { 332a34c753fSRafael Auler auto Index = Map.getNextIndex(); 333a34c753fSRafael Auler Entry = Map.insert(Address, Index).first; 334a34c753fSRafael Auler } 335a34c753fSRafael Auler return Entry->second; 336a34c753fSRafael Auler } 337a34c753fSRafael Auler 338a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 339a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update 340a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 341a34c753fSRafael Auler // update AddressToIndex and IndexToAddress 342a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 343ba1ac98cSAlexander Yermolovich DWARFUnit &CU) { 344e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 345ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(CU); 346014cd37fSAlexander Yermolovich AddressForDWOCU &Map = AddressMaps[CUID]; 347a34c753fSRafael Auler auto Entry = Map.find(Address); 348a34c753fSRafael Auler if (Entry != Map.end()) { 349a34c753fSRafael Auler if (Entry->second > Index) 350a34c753fSRafael Auler Map.updateAddressToIndex(Address, Index); 351a34c753fSRafael Auler Map.updateIndexToAddrss(Address, Index); 3523652483cSRafael Auler } else { 353a34c753fSRafael Auler Map.insert(Address, Index); 354a34c753fSRafael Auler } 3553652483cSRafael Auler } 356a34c753fSRafael Auler 357a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() { 358a34c753fSRafael Auler // Need to layout all sections within .debug_addr 359a34c753fSRafael Auler // Within each section sort Address by index. 360a34c753fSRafael Auler AddressSectionBuffer Buffer; 361a34c753fSRafael Auler raw_svector_ostream AddressStream(Buffer); 362a34c753fSRafael Auler for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 363a34c753fSRafael Auler // Handling the case wehre debug information is a mix of Debug fission and 364a34c753fSRafael Auler // monolitic. 365ba1ac98cSAlexander Yermolovich if (!CU->getDWOId()) 366a34c753fSRafael Auler continue; 367ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(*CU.get()); 368ba1ac98cSAlexander Yermolovich auto AM = AddressMaps.find(CUID); 369a34c753fSRafael Auler // Adding to map even if it did not contribute to .debug_addr. 3703abb68a6SAlexander Yermolovich // The Skeleton CU might still have DW_AT_GNU_addr_base. 371ba1ac98cSAlexander Yermolovich DWOIdToOffsetMap[CUID] = Buffer.size(); 372a34c753fSRafael Auler // If does not exist this CUs DWO section didn't contribute to .debug_addr. 373a34c753fSRafael Auler if (AM == AddressMaps.end()) 374a34c753fSRafael Auler continue; 375a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 376a34c753fSRafael Auler AM->second.indexToAdddessEnd()); 377a34c753fSRafael Auler // Sorting address in increasing order of indices. 378a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 379a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 380a34c753fSRafael Auler return A.first < B.first; 381a34c753fSRafael Auler }); 382a34c753fSRafael Auler 383a34c753fSRafael Auler uint8_t AddrSize = CU->getAddressByteSize(); 384a34c753fSRafael Auler uint32_t Counter = 0; 385a34c753fSRafael Auler auto WriteAddress = [&](uint64_t Address) -> void { 386a34c753fSRafael Auler ++Counter; 387a34c753fSRafael Auler switch (AddrSize) { 388a34c753fSRafael Auler default: 389a34c753fSRafael Auler assert(false && "Address Size is invalid."); 390a34c753fSRafael Auler break; 391a34c753fSRafael Auler case 4: 392a34c753fSRafael Auler support::endian::write(AddressStream, static_cast<uint32_t>(Address), 393a34c753fSRafael Auler support::little); 394a34c753fSRafael Auler break; 395a34c753fSRafael Auler case 8: 396a34c753fSRafael Auler support::endian::write(AddressStream, Address, support::little); 397a34c753fSRafael Auler break; 398a34c753fSRafael Auler } 399a34c753fSRafael Auler }; 400a34c753fSRafael Auler 401a34c753fSRafael Auler for (const IndexAddressPair &Val : SortedMap) { 402a34c753fSRafael Auler while (Val.first > Counter) 403a34c753fSRafael Auler WriteAddress(0); 404a34c753fSRafael Auler WriteAddress(Val.second); 405a34c753fSRafael Auler } 406a34c753fSRafael Auler } 407a34c753fSRafael Auler 408a34c753fSRafael Auler return Buffer; 409a34c753fSRafael Auler } 410014cd37fSAlexander Yermolovich AddressSectionBuffer DebugAddrWriterDwarf5::finalize() { 411014cd37fSAlexander Yermolovich // Need to layout all sections within .debug_addr 412014cd37fSAlexander Yermolovich // Within each section sort Address by index. 413014cd37fSAlexander Yermolovich AddressSectionBuffer Buffer; 414014cd37fSAlexander Yermolovich raw_svector_ostream AddressStream(Buffer); 415014cd37fSAlexander Yermolovich const endianness Endian = 416014cd37fSAlexander Yermolovich BC->DwCtx->isLittleEndian() ? support::little : support::big; 417014cd37fSAlexander Yermolovich const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection(); 418014cd37fSAlexander Yermolovich DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0); 419014cd37fSAlexander Yermolovich DWARFDebugAddrTable AddrTable; 420014cd37fSAlexander Yermolovich DIDumpOptions DumpOpts; 421014cd37fSAlexander Yermolovich constexpr uint32_t HeaderSize = 8; 422014cd37fSAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 423ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(*CU.get()); 424014cd37fSAlexander Yermolovich const uint8_t AddrSize = CU->getAddressByteSize(); 425ba1ac98cSAlexander Yermolovich auto AMIter = AddressMaps.find(CUID); 426014cd37fSAlexander Yermolovich // A case where CU has entry in .debug_addr, but we don't modify addresses 427014cd37fSAlexander Yermolovich // for it. 428ba1ac98cSAlexander Yermolovich if (AMIter == AddressMaps.end()) { 429ba1ac98cSAlexander Yermolovich AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; 430014cd37fSAlexander Yermolovich Optional<uint64_t> BaseOffset = CU->getAddrOffsetSectionBase(); 431014cd37fSAlexander Yermolovich if (!BaseOffset) 432014cd37fSAlexander Yermolovich continue; 433014cd37fSAlexander Yermolovich // Address base offset is to the first entry. 434014cd37fSAlexander Yermolovich // The size of header is 8 bytes. 435014cd37fSAlexander Yermolovich uint64_t Offset = *BaseOffset - HeaderSize; 436014cd37fSAlexander Yermolovich if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize, 437014cd37fSAlexander Yermolovich DumpOpts.WarningHandler)) { 438014cd37fSAlexander Yermolovich DumpOpts.RecoverableErrorHandler(std::move(Err)); 439014cd37fSAlexander Yermolovich continue; 440014cd37fSAlexander Yermolovich } 441014cd37fSAlexander Yermolovich uint32_t Index = 0; 442014cd37fSAlexander Yermolovich for (uint64_t Addr : AddrTable.getAddressEntries()) 443ba1ac98cSAlexander Yermolovich AMIter->second.insert(Addr, Index++); 444014cd37fSAlexander Yermolovich } 445a34c753fSRafael Auler 446014cd37fSAlexander Yermolovich DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize; 447014cd37fSAlexander Yermolovich 448ba1ac98cSAlexander Yermolovich std::vector<IndexAddressPair> SortedMap( 449ba1ac98cSAlexander Yermolovich AMIter->second.indexToAddressBegin(), 450ba1ac98cSAlexander Yermolovich AMIter->second.indexToAdddessEnd()); 451014cd37fSAlexander Yermolovich // Sorting address in increasing order of indices. 452014cd37fSAlexander Yermolovich std::sort(SortedMap.begin(), SortedMap.end(), 453014cd37fSAlexander Yermolovich [](const IndexAddressPair &A, const IndexAddressPair &B) { 454014cd37fSAlexander Yermolovich return A.first < B.first; 455014cd37fSAlexander Yermolovich }); 456014cd37fSAlexander Yermolovich // Writing out Header 457014cd37fSAlexander Yermolovich const uint32_t Length = SortedMap.size() * AddrSize + 4; 458014cd37fSAlexander Yermolovich support::endian::write(AddressStream, Length, Endian); 459014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian); 460014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize), 461014cd37fSAlexander Yermolovich Endian); 462014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian); 463014cd37fSAlexander Yermolovich 464014cd37fSAlexander Yermolovich uint32_t Counter = 0; 465014cd37fSAlexander Yermolovich auto writeAddress = [&](uint64_t Address) -> void { 466014cd37fSAlexander Yermolovich ++Counter; 467014cd37fSAlexander Yermolovich switch (AddrSize) { 468014cd37fSAlexander Yermolovich default: 469014cd37fSAlexander Yermolovich llvm_unreachable("Address Size is invalid."); 470014cd37fSAlexander Yermolovich break; 471014cd37fSAlexander Yermolovich case 4: 472014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint32_t>(Address), 473014cd37fSAlexander Yermolovich Endian); 474014cd37fSAlexander Yermolovich break; 475014cd37fSAlexander Yermolovich case 8: 476014cd37fSAlexander Yermolovich support::endian::write(AddressStream, Address, Endian); 477014cd37fSAlexander Yermolovich break; 478014cd37fSAlexander Yermolovich } 479014cd37fSAlexander Yermolovich }; 480014cd37fSAlexander Yermolovich 481014cd37fSAlexander Yermolovich for (const IndexAddressPair &Val : SortedMap) { 482014cd37fSAlexander Yermolovich while (Val.first > Counter) 483014cd37fSAlexander Yermolovich writeAddress(0); 484014cd37fSAlexander Yermolovich writeAddress(Val.second); 485014cd37fSAlexander Yermolovich } 486014cd37fSAlexander Yermolovich } 487014cd37fSAlexander Yermolovich 488014cd37fSAlexander Yermolovich return Buffer; 489014cd37fSAlexander Yermolovich } 490014cd37fSAlexander Yermolovich 491014cd37fSAlexander Yermolovich uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) { 492ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(Unit); 493ba1ac98cSAlexander Yermolovich assert(CUID && "Can't get offset, not a skeleton CU."); 494ba1ac98cSAlexander Yermolovich auto Iter = DWOIdToOffsetMap.find(CUID); 495014cd37fSAlexander Yermolovich assert(Iter != DWOIdToOffsetMap.end() && 496014cd37fSAlexander Yermolovich "Offset in to.debug_addr was not found for DWO ID."); 497014cd37fSAlexander Yermolovich return Iter->second; 498014cd37fSAlexander Yermolovich } 499014cd37fSAlexander Yermolovich 500014cd37fSAlexander Yermolovich uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) { 501ba1ac98cSAlexander Yermolovich auto Iter = DWOIdToOffsetMap.find(getCUID(Unit)); 502a34c753fSRafael Auler assert(Iter != DWOIdToOffsetMap.end() && 5033abb68a6SAlexander Yermolovich "Offset in to.debug_addr was not found for CU ID."); 504a34c753fSRafael Auler return Iter->second; 505a34c753fSRafael Auler } 506a34c753fSRafael Auler 5071c6dc43dSAlexander Yermolovich void DebugLocWriter::init() { 508a34c753fSRafael Auler LocBuffer = std::make_unique<DebugBufferVector>(); 509a34c753fSRafael Auler LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 5101c6dc43dSAlexander Yermolovich // Writing out empty location list to which all references to empty location 5111c6dc43dSAlexander Yermolovich // lists will point. 5121c6dc43dSAlexander Yermolovich if (!LocSectionOffset && DwarfVersion < 5) { 5131c6dc43dSAlexander Yermolovich const char Zeroes[16] = {0}; 5141c6dc43dSAlexander Yermolovich *LocStream << StringRef(Zeroes, 16); 5151c6dc43dSAlexander Yermolovich LocSectionOffset += 16; 5161c6dc43dSAlexander Yermolovich } 517a34c753fSRafael Auler } 518a34c753fSRafael Auler 5191c6dc43dSAlexander Yermolovich uint32_t DebugLocWriter::LocSectionOffset = 0; 5201c6dc43dSAlexander Yermolovich void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList, 5211c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, 5221c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) { 5231c6dc43dSAlexander Yermolovich const uint64_t AttrOffset = AttrVal.Offset; 524a34c753fSRafael Auler if (LocList.empty()) { 5251c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); 526a34c753fSRafael Auler return; 527a34c753fSRafael Auler } 528a34c753fSRafael Auler // Since there is a separate DebugLocWriter for each thread, 529a34c753fSRafael Auler // we don't need a lock to read the SectionOffset and update it. 5301c6dc43dSAlexander Yermolovich const uint32_t EntryOffset = LocSectionOffset; 531a34c753fSRafael Auler 532a34c753fSRafael Auler for (const DebugLocationEntry &Entry : LocList) { 533a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 534a34c753fSRafael Auler support::little); 535a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 536a34c753fSRafael Auler support::little); 537a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 538a34c753fSRafael Auler support::little); 539a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 540a34c753fSRafael Auler Entry.Expr.size()); 5411c6dc43dSAlexander Yermolovich LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 542a34c753fSRafael Auler } 543a34c753fSRafael Auler LocStream->write_zeros(16); 5441c6dc43dSAlexander Yermolovich LocSectionOffset += 16; 545a34c753fSRafael Auler LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 5461c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); 547a34c753fSRafael Auler } 548a34c753fSRafael Auler 549a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 550a34c753fSRafael Auler return std::move(LocBuffer); 551a34c753fSRafael Auler } 552a34c753fSRafael Auler 553a34c753fSRafael Auler // DWARF 4: 2.6.2 5541c6dc43dSAlexander Yermolovich void DebugLocWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 5551c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) {} 556a34c753fSRafael Auler 557014cd37fSAlexander Yermolovich static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { 558014cd37fSAlexander Yermolovich support::endian::write(Stream, static_cast<uint32_t>(4), support::little); 559014cd37fSAlexander Yermolovich support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end), 560014cd37fSAlexander Yermolovich support::little); 561014cd37fSAlexander Yermolovich 562014cd37fSAlexander Yermolovich const char Zeroes[16] = {0}; 563014cd37fSAlexander Yermolovich Stream << StringRef(Zeroes, 16); 564014cd37fSAlexander Yermolovich encodeULEB128(0, Stream); 565014cd37fSAlexander Yermolovich support::endian::write( 566014cd37fSAlexander Yermolovich Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little); 567014cd37fSAlexander Yermolovich } 568014cd37fSAlexander Yermolovich 5691c6dc43dSAlexander Yermolovich static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList, 5701c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, 5711c6dc43dSAlexander Yermolovich DebugAddrWriter &AddrWriter, 5721c6dc43dSAlexander Yermolovich DebugBufferVector &LocBuffer, DWARFUnit &CU, 5731c6dc43dSAlexander Yermolovich raw_svector_ostream &LocStream) { 5741c6dc43dSAlexander Yermolovich const uint64_t AttrOffset = AttrVal.Offset; 5751c6dc43dSAlexander Yermolovich if (LocList.empty()) { 5761c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); 5771c6dc43dSAlexander Yermolovich return; 5781c6dc43dSAlexander Yermolovich } 5791c6dc43dSAlexander Yermolovich 5801c6dc43dSAlexander Yermolovich const uint32_t EntryOffset = LocBuffer.size(); 5811c6dc43dSAlexander Yermolovich for (const DebugLocationEntry &Entry : LocList) { 5821c6dc43dSAlexander Yermolovich support::endian::write(LocStream, 5831c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 5841c6dc43dSAlexander Yermolovich support::little); 5851c6dc43dSAlexander Yermolovich const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 5861c6dc43dSAlexander Yermolovich encodeULEB128(Index, LocStream); 5871c6dc43dSAlexander Yermolovich 5881c6dc43dSAlexander Yermolovich support::endian::write(LocStream, 5891c6dc43dSAlexander Yermolovich static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 5901c6dc43dSAlexander Yermolovich support::little); 5911c6dc43dSAlexander Yermolovich support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()), 5921c6dc43dSAlexander Yermolovich support::little); 5931c6dc43dSAlexander Yermolovich LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 5941c6dc43dSAlexander Yermolovich Entry.Expr.size()); 5951c6dc43dSAlexander Yermolovich } 5961c6dc43dSAlexander Yermolovich support::endian::write(LocStream, 5971c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 5981c6dc43dSAlexander Yermolovich support::little); 5991c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); 6001c6dc43dSAlexander Yermolovich } 6011c6dc43dSAlexander Yermolovich 6021c6dc43dSAlexander Yermolovich static void writeDWARF5LocList( 6031c6dc43dSAlexander Yermolovich uint32_t &NumberOfEntries, AttrInfo &AttrVal, DebugLocationsVector &LocList, 6041c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter, 6051c6dc43dSAlexander Yermolovich DebugAddrWriter &AddrWriter, DebugBufferVector &LocBodyBuffer, 6061c6dc43dSAlexander Yermolovich std::vector<uint32_t> &RelativeLocListOffsets, DWARFUnit &CU, 6071c6dc43dSAlexander Yermolovich raw_svector_ostream &LocBodyStream) { 6081c6dc43dSAlexander Yermolovich if (AttrVal.V.getForm() != dwarf::DW_FORM_loclistx) { 6091c6dc43dSAlexander Yermolovich AbbrevWriter.addAttributePatch(CU, AttrVal.AbbrevDecl, 6101c6dc43dSAlexander Yermolovich dwarf::DW_AT_location, dwarf::DW_AT_location, 6111c6dc43dSAlexander Yermolovich dwarf::DW_FORM_loclistx); 6121c6dc43dSAlexander Yermolovich } 6131c6dc43dSAlexander Yermolovich DebugInfoPatcher.addUDataPatch(AttrVal.Offset, NumberOfEntries, AttrVal.Size); 6141c6dc43dSAlexander Yermolovich RelativeLocListOffsets.push_back(LocBodyBuffer.size()); 6151c6dc43dSAlexander Yermolovich ++NumberOfEntries; 6161c6dc43dSAlexander Yermolovich if (LocList.empty()) { 6171c6dc43dSAlexander Yermolovich writeEmptyListDwarf5(LocBodyStream); 6181c6dc43dSAlexander Yermolovich return; 6191c6dc43dSAlexander Yermolovich } 6201c6dc43dSAlexander Yermolovich 6211c6dc43dSAlexander Yermolovich std::vector<uint64_t> OffsetsArray; 6221c6dc43dSAlexander Yermolovich for (const DebugLocationEntry &Entry : LocList) { 6231c6dc43dSAlexander Yermolovich support::endian::write(LocBodyStream, 6241c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 6251c6dc43dSAlexander Yermolovich support::little); 6261c6dc43dSAlexander Yermolovich const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 6271c6dc43dSAlexander Yermolovich encodeULEB128(Index, LocBodyStream); 6281c6dc43dSAlexander Yermolovich encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream); 6291c6dc43dSAlexander Yermolovich encodeULEB128(Entry.Expr.size(), LocBodyStream); 6301c6dc43dSAlexander Yermolovich LocBodyStream << StringRef( 6311c6dc43dSAlexander Yermolovich reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size()); 6321c6dc43dSAlexander Yermolovich } 6331c6dc43dSAlexander Yermolovich support::endian::write(LocBodyStream, 6341c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 6351c6dc43dSAlexander Yermolovich support::little); 6361c6dc43dSAlexander Yermolovich } 6371c6dc43dSAlexander Yermolovich 6381c6dc43dSAlexander Yermolovich void DebugLoclistWriter::addList(AttrInfo &AttrVal, 6391c6dc43dSAlexander Yermolovich DebugLocationsVector &LocList, 6401c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, 6411c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) { 6421c6dc43dSAlexander Yermolovich if (DwarfVersion < 5) 6431c6dc43dSAlexander Yermolovich writeLegacyLocList(AttrVal, LocList, DebugInfoPatcher, *AddrWriter, 6441c6dc43dSAlexander Yermolovich *LocBuffer, CU, *LocStream); 6451c6dc43dSAlexander Yermolovich else 6461c6dc43dSAlexander Yermolovich writeDWARF5LocList(NumberOfEntries, AttrVal, LocList, DebugInfoPatcher, 6471c6dc43dSAlexander Yermolovich AbbrevWriter, *AddrWriter, *LocBodyBuffer, 6481c6dc43dSAlexander Yermolovich RelativeLocListOffsets, CU, *LocBodyStream); 6491c6dc43dSAlexander Yermolovich } 6501c6dc43dSAlexander Yermolovich 6511c6dc43dSAlexander Yermolovich uint32_t DebugLoclistWriter::LoclistBaseOffset = 0; 6521c6dc43dSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARF5( 6531c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) { 6541c6dc43dSAlexander Yermolovich if (LocBodyBuffer->empty()) 6551c6dc43dSAlexander Yermolovich return; 656014cd37fSAlexander Yermolovich 657014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> LocArrayBuffer = 658014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 659014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> LocArrayStream = 660014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*LocArrayBuffer); 661014cd37fSAlexander Yermolovich 6621c6dc43dSAlexander Yermolovich const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t); 663014cd37fSAlexander Yermolovich // Write out IndexArray 6641c6dc43dSAlexander Yermolovich for (uint32_t RelativeOffset : RelativeLocListOffsets) 665014cd37fSAlexander Yermolovich support::endian::write( 666014cd37fSAlexander Yermolovich *LocArrayStream, 6671c6dc43dSAlexander Yermolovich static_cast<uint32_t>(SizeOfArraySection + RelativeOffset), 668014cd37fSAlexander Yermolovich support::little); 6691c6dc43dSAlexander Yermolovich 6701c6dc43dSAlexander Yermolovich std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 6711c6dc43dSAlexander Yermolovich {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()), 6721c6dc43dSAlexander Yermolovich 5, 8, 0, NumberOfEntries}); 673014cd37fSAlexander Yermolovich *LocStream << *Header; 674014cd37fSAlexander Yermolovich *LocStream << *LocArrayBuffer; 675014cd37fSAlexander Yermolovich *LocStream << *LocBodyBuffer; 6761c6dc43dSAlexander Yermolovich 6771c6dc43dSAlexander Yermolovich if (!isSplitDwarf()) { 6781c6dc43dSAlexander Yermolovich if (Optional<AttrInfo> AttrInfoVal = 6791c6dc43dSAlexander Yermolovich findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base)) 6801c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset, 6811c6dc43dSAlexander Yermolovich LoclistBaseOffset + 6821c6dc43dSAlexander Yermolovich getDWARF5RngListLocListHeaderSize()); 6831c6dc43dSAlexander Yermolovich else { 6841c6dc43dSAlexander Yermolovich AbbrevWriter.addAttribute( 6851c6dc43dSAlexander Yermolovich CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(), 6861c6dc43dSAlexander Yermolovich dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset); 6871c6dc43dSAlexander Yermolovich DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(), 6881c6dc43dSAlexander Yermolovich LoclistBaseOffset + Header->size()); 689014cd37fSAlexander Yermolovich } 6901c6dc43dSAlexander Yermolovich LoclistBaseOffset += LocBuffer->size(); 6911c6dc43dSAlexander Yermolovich } 6921c6dc43dSAlexander Yermolovich clearList(RelativeLocListOffsets); 6931c6dc43dSAlexander Yermolovich clearList(*LocArrayBuffer); 6941c6dc43dSAlexander Yermolovich clearList(*LocBodyBuffer); 695014cd37fSAlexander Yermolovich } 696014cd37fSAlexander Yermolovich 6971c6dc43dSAlexander Yermolovich void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 6981c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) { 6991c6dc43dSAlexander Yermolovich if (DwarfVersion >= 5) 7001c6dc43dSAlexander Yermolovich finalizeDWARF5(DebugInfoPatcher, AbbrevWriter); 701014cd37fSAlexander Yermolovich } 702014cd37fSAlexander Yermolovich 703a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 704a34c753fSRafael Auler 7051c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 7061c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7071c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 708ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 709a34c753fSRafael Auler } 710a34c753fSRafael Auler 7111c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 7121c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7131c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7141c2f4bbeSAlexander Yermolovich auto RetVal = DestinationLabels.insert(Offset); 7151c2f4bbeSAlexander Yermolovich if (!RetVal.second) 7161c2f4bbeSAlexander Yermolovich return; 7171c2f4bbeSAlexander Yermolovich 718ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 719a34c753fSRafael Auler } 720a34c753fSRafael Auler 721bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 722bd1ebe9dSAlexander Yermolovich std::string LE64(ByteSize, 0); 723bd1ebe9dSAlexander Yermolovich for (size_t I = 0; I < ByteSize; ++I) { 724bd1ebe9dSAlexander Yermolovich LE64[I] = NewValue & 0xff; 725bd1ebe9dSAlexander Yermolovich NewValue >>= 8; 726bd1ebe9dSAlexander Yermolovich } 727bd1ebe9dSAlexander Yermolovich return LE64; 728bd1ebe9dSAlexander Yermolovich } 729bd1ebe9dSAlexander Yermolovich 730bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 731bd1ebe9dSAlexander Yermolovich uint32_t Value) { 732bd1ebe9dSAlexander Yermolovich std::string StrValue = encodeLE(4, Value); 733bd1ebe9dSAlexander Yermolovich insertNewEntry(DIE, std::move(StrValue)); 734bd1ebe9dSAlexander Yermolovich } 735bd1ebe9dSAlexander Yermolovich 736bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 737bd1ebe9dSAlexander Yermolovich std::string &&Value) { 738bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl = 739bd1ebe9dSAlexander Yermolovich DIE.getAbbreviationDeclarationPtr(); 740bd1ebe9dSAlexander Yermolovich 741bd1ebe9dSAlexander Yermolovich // In case this DIE has no attributes. 742bd1ebe9dSAlexander Yermolovich uint32_t Offset = DIE.getOffset() + 1; 743bd1ebe9dSAlexander Yermolovich size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 744bd1ebe9dSAlexander Yermolovich if (NumOfAttributes) { 745bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> Val = 746bd1ebe9dSAlexander Yermolovich findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 747bd1ebe9dSAlexander Yermolovich assert(Val && "Invalid Value."); 748bd1ebe9dSAlexander Yermolovich 749bd1ebe9dSAlexander Yermolovich Offset = Val->Offset + Val->Size - DWPUnitOffset; 750bd1ebe9dSAlexander Yermolovich } 751bd1ebe9dSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 752bd1ebe9dSAlexander Yermolovich DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 753bd1ebe9dSAlexander Yermolovich } 754bd1ebe9dSAlexander Yermolovich 7551c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 7561c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset, 7571c2f4bbeSAlexander Yermolovich uint32_t OldValueSize, 7581c2f4bbeSAlexander Yermolovich dwarf::Form Form) { 7591c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7601c2f4bbeSAlexander Yermolovich DestinationOffset -= DWPUnitOffset; 7611c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 762ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back( 763ea6c8b01SAlexander Yermolovich new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 7641c2f4bbeSAlexander Yermolovich } 7651c2f4bbeSAlexander Yermolovich 7661c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 7671c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7681c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7691c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7701c2f4bbeSAlexander Yermolovich DebugPatches.emplace_back( 771ea6c8b01SAlexander Yermolovich new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 7721c2f4bbeSAlexander Yermolovich } 7731c2f4bbeSAlexander Yermolovich 7741c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 7751c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7761c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 777ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 7781c2f4bbeSAlexander Yermolovich } 7791c2f4bbeSAlexander Yermolovich 7801c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 7811c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7821c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7831c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7841c2f4bbeSAlexander Yermolovich if (OldValueSize == 4) 785ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 786a44fe319SAlexander Yermolovich else if (OldValueSize == 8) 787ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 788a44fe319SAlexander Yermolovich else 789a44fe319SAlexander Yermolovich DebugPatches.emplace_back( 790a44fe319SAlexander Yermolovich new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); 7911c2f4bbeSAlexander Yermolovich } 7921c2f4bbeSAlexander Yermolovich 7931c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 7941c2f4bbeSAlexander Yermolovich std::string &&NewValue, 7951c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7961c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(NewValue)); 7971c2f4bbeSAlexander Yermolovich } 7981c2f4bbeSAlexander Yermolovich 7991c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 8001c2f4bbeSAlexander Yermolovich auto Str = std::string(1, Value); 8011c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Str)); 8021c2f4bbeSAlexander Yermolovich } 8031c2f4bbeSAlexander Yermolovich 8041c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 8051c2f4bbeSAlexander Yermolovich size_t ByteSize) { 8061c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 8071c2f4bbeSAlexander Yermolovich } 8081c2f4bbeSAlexander Yermolovich 8091c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 8101c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 811a34c753fSRafael Auler std::string Buff; 812a34c753fSRafael Auler raw_string_ostream OS(Buff); 8131c2f4bbeSAlexander Yermolovich encodeULEB128(Value, OS, OldValueSize); 814a34c753fSRafael Auler 8151c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Buff)); 816a34c753fSRafael Auler } 817a34c753fSRafael Auler 8181c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 819a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 820a34c753fSRafael Auler } 821a34c753fSRafael Auler 8221c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 8231c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 824a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 825a34c753fSRafael Auler } 826a34c753fSRafael Auler 8271c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 8281c2f4bbeSAlexander Yermolovich std::string BinaryContentsStr = std::string(BinaryContents); 829a34c753fSRafael Auler for (const auto &Patch : Patches) { 8301c2f4bbeSAlexander Yermolovich uint32_t Offset = Patch.first; 831a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 832a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 833a34c753fSRafael Auler "Applied patch runs over binary size."); 834a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 8351c2f4bbeSAlexander Yermolovich BinaryContentsStr[Offset + I] = ByteSequence[I]; 836a34c753fSRafael Auler } 837a34c753fSRafael Auler } 8381c2f4bbeSAlexander Yermolovich return BinaryContentsStr; 8391c2f4bbeSAlexander Yermolovich } 8401c2f4bbeSAlexander Yermolovich 841612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 842612f0f45SAlexander Yermolovich bool IsDWOContext) { 843612f0f45SAlexander Yermolovich CUOffsetMap CUMap; 844ea6c8b01SAlexander Yermolovich std::sort(DebugPatches.begin(), DebugPatches.end(), 845ea6c8b01SAlexander Yermolovich [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) { 846bd1ebe9dSAlexander Yermolovich if (V1.get()->Offset == V2.get()->Offset) { 847bd1ebe9dSAlexander Yermolovich if (V1->Kind == DebugPatchKind::NewDebugEntry && 848bd1ebe9dSAlexander Yermolovich V2->Kind == DebugPatchKind::NewDebugEntry) 849bd1ebe9dSAlexander Yermolovich return reinterpret_cast<const NewDebugEntry *>(V1.get()) 850bd1ebe9dSAlexander Yermolovich ->CurrentOrder < 851bd1ebe9dSAlexander Yermolovich reinterpret_cast<const NewDebugEntry *>(V2.get()) 852bd1ebe9dSAlexander Yermolovich ->CurrentOrder; 853bd1ebe9dSAlexander Yermolovich 854bd1ebe9dSAlexander Yermolovich // This is a case where we are modifying first entry of next 855bd1ebe9dSAlexander Yermolovich // DIE, and adding a new one. 856bd1ebe9dSAlexander Yermolovich return V1->Kind == DebugPatchKind::NewDebugEntry; 857bd1ebe9dSAlexander Yermolovich } 8581c2f4bbeSAlexander Yermolovich return V1.get()->Offset < V2.get()->Offset; 8591c2f4bbeSAlexander Yermolovich }); 8601c2f4bbeSAlexander Yermolovich 861612f0f45SAlexander Yermolovich DWARFUnitVector::compile_unit_range CompileUnits = 862612f0f45SAlexander Yermolovich IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 863612f0f45SAlexander Yermolovich 864612f0f45SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 865612f0f45SAlexander Yermolovich CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 866612f0f45SAlexander Yermolovich static_cast<uint32_t>(CU->getLength())}; 867612f0f45SAlexander Yermolovich 8681c2f4bbeSAlexander Yermolovich // Calculating changes in .debug_info size from Patches to build a map of old 8691c2f4bbeSAlexander Yermolovich // to updated reference destination offsets. 870612f0f45SAlexander Yermolovich uint32_t PreviousOffset = 0; 871612f0f45SAlexander Yermolovich int32_t PreviousChangeInSize = 0; 872ea6c8b01SAlexander Yermolovich for (UniquePatchPtrType &PatchBase : DebugPatches) { 8731c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 8741c2f4bbeSAlexander Yermolovich switch (P->Kind) { 8751c2f4bbeSAlexander Yermolovich default: 8761c2f4bbeSAlexander Yermolovich continue; 8771c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 878612f0f45SAlexander Yermolovich PreviousChangeInSize -= 4; 8791c2f4bbeSAlexander Yermolovich break; 8801c2f4bbeSAlexander Yermolovich } 881a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 882a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 883a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 884a44fe319SAlexander Yermolovich PreviousChangeInSize += 4 - DPVS->OldValueSize; 885a44fe319SAlexander Yermolovich break; 886a44fe319SAlexander Yermolovich } 8871c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 8881c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *DPV = 8891c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 8901c2f4bbeSAlexander Yermolovich std::string Temp; 8911c2f4bbeSAlexander Yermolovich raw_string_ostream OS(Temp); 8921c2f4bbeSAlexander Yermolovich encodeULEB128(DPV->Value, OS); 893612f0f45SAlexander Yermolovich PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 8941c2f4bbeSAlexander Yermolovich break; 8951c2f4bbeSAlexander Yermolovich } 8961c2f4bbeSAlexander Yermolovich case DebugPatchKind::DestinationReferenceLabel: { 8971c2f4bbeSAlexander Yermolovich DestinationReferenceLabel *DRL = 8981c2f4bbeSAlexander Yermolovich reinterpret_cast<DestinationReferenceLabel *>(P); 899612f0f45SAlexander Yermolovich OldToNewOffset[DRL->Offset] = 900612f0f45SAlexander Yermolovich DRL->Offset + ChangeInSize + PreviousChangeInSize; 9011c2f4bbeSAlexander Yermolovich break; 9021c2f4bbeSAlexander Yermolovich } 9031c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 9041c2f4bbeSAlexander Yermolovich // This doesn't look to be a common case, so will always encode as 4 bytes 9051c2f4bbeSAlexander Yermolovich // to reduce algorithmic complexity. 9061c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 9071c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.IndirectRelative) { 908612f0f45SAlexander Yermolovich PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 9091c2f4bbeSAlexander Yermolovich assert(RDP->PatchInfo.OldValueSize <= 4 && 9101c2f4bbeSAlexander Yermolovich "Variable encoding reference greater than 4 bytes."); 9111c2f4bbeSAlexander Yermolovich } 9121c2f4bbeSAlexander Yermolovich break; 9131c2f4bbeSAlexander Yermolovich } 9141c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 9151c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 9161c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 9171c2f4bbeSAlexander Yermolovich uint32_t CUOffset = BaseLabel->Offset; 918612f0f45SAlexander Yermolovich ChangeInSize += PreviousChangeInSize; 9191c2f4bbeSAlexander Yermolovich uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 920612f0f45SAlexander Yermolovich CUMap[CUOffset].Offset = CUOffsetUpdate; 921612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 922612f0f45SAlexander Yermolovich PreviousChangeInSize = 0; 923612f0f45SAlexander Yermolovich PreviousOffset = CUOffset; 924bd1ebe9dSAlexander Yermolovich break; 925bd1ebe9dSAlexander Yermolovich } 926bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 927bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 928bd1ebe9dSAlexander Yermolovich PreviousChangeInSize += NDE->Value.size(); 929bd1ebe9dSAlexander Yermolovich break; 9301c2f4bbeSAlexander Yermolovich } 9311c2f4bbeSAlexander Yermolovich } 9321c2f4bbeSAlexander Yermolovich } 933612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 9341c2f4bbeSAlexander Yermolovich return CUMap; 9351c2f4bbeSAlexander Yermolovich } 936bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 9371c2f4bbeSAlexander Yermolovich 9381c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 9391c2f4bbeSAlexander Yermolovich std::string NewBinaryContents; 9401c2f4bbeSAlexander Yermolovich NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 9411c2f4bbeSAlexander Yermolovich uint32_t StartOffset = 0; 9421c2f4bbeSAlexander Yermolovich uint32_t DwarfUnitBaseOffset = 0; 9431c2f4bbeSAlexander Yermolovich uint32_t OldValueSize = 0; 9441c2f4bbeSAlexander Yermolovich uint32_t Offset = 0; 9451c2f4bbeSAlexander Yermolovich std::string ByteSequence; 9461c2f4bbeSAlexander Yermolovich std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 9471c2f4bbeSAlexander Yermolovich // Wasting one entry to avoid checks for first. 9481c2f4bbeSAlexander Yermolovich LengthPatches.push_back({0, 0}); 9491c2f4bbeSAlexander Yermolovich 9501c2f4bbeSAlexander Yermolovich // Applying all the patches replacing current entry. 9511c2f4bbeSAlexander Yermolovich // This might change the size of .debug_info section. 952ea6c8b01SAlexander Yermolovich for (const UniquePatchPtrType &PatchBase : DebugPatches) { 9531c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 9541c2f4bbeSAlexander Yermolovich switch (P->Kind) { 9551c2f4bbeSAlexander Yermolovich default: 9561c2f4bbeSAlexander Yermolovich continue; 9571c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 9581c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 9591c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset = RDP->DestinationOffset; 9601c2f4bbeSAlexander Yermolovich assert(OldToNewOffset.count(DestinationOffset) && 9611c2f4bbeSAlexander Yermolovich "Destination Offset for reference not updated."); 9621c2f4bbeSAlexander Yermolovich uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 9631c2f4bbeSAlexander Yermolovich Offset = RDP->Offset; 9641c2f4bbeSAlexander Yermolovich OldValueSize = RDP->PatchInfo.OldValueSize; 9651c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.DirectRelative) { 9661c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 9671c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 9681c2f4bbeSAlexander Yermolovich // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 9691c2f4bbeSAlexander Yermolovich // and overflow if later debug information grows. 9701c2f4bbeSAlexander Yermolovich if (ByteSequence.size() > OldValueSize) 9711c2f4bbeSAlexander Yermolovich errs() << "BOLT-ERROR: Relative reference of size " 9721c2f4bbeSAlexander Yermolovich << Twine::utohexstr(OldValueSize) 9731c2f4bbeSAlexander Yermolovich << " overflows with the new encoding.\n"; 9741c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.DirectAbsolute) { 9751c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 9761c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.IndirectRelative) { 9771c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 9781c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 9791c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 9801c2f4bbeSAlexander Yermolovich encodeULEB128(UpdatedOffset, OS, 4); 9811c2f4bbeSAlexander Yermolovich } else { 9821c2f4bbeSAlexander Yermolovich llvm_unreachable("Invalid Reference form."); 9831c2f4bbeSAlexander Yermolovich } 9841c2f4bbeSAlexander Yermolovich break; 9851c2f4bbeSAlexander Yermolovich } 9861c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue32: { 9871c2f4bbeSAlexander Yermolovich DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 9881c2f4bbeSAlexander Yermolovich Offset = P32->Offset; 9891c2f4bbeSAlexander Yermolovich OldValueSize = 4; 9901c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P32->Value); 9911c2f4bbeSAlexander Yermolovich break; 9921c2f4bbeSAlexander Yermolovich } 9931c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 9941c2f4bbeSAlexander Yermolovich DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 9951c2f4bbeSAlexander Yermolovich Offset = P64to32->Offset; 9961c2f4bbeSAlexander Yermolovich OldValueSize = 8; 9971c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P64to32->Value); 9981c2f4bbeSAlexander Yermolovich break; 9991c2f4bbeSAlexander Yermolovich } 1000a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 1001a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 1002a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 1003a44fe319SAlexander Yermolovich Offset = DPVS->Offset; 1004a44fe319SAlexander Yermolovich OldValueSize = DPVS->OldValueSize; 1005a44fe319SAlexander Yermolovich ByteSequence = encodeLE(4, DPVS->Value); 1006a44fe319SAlexander Yermolovich break; 1007a44fe319SAlexander Yermolovich } 10081c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 10091c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *PV = 10101c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 10111c2f4bbeSAlexander Yermolovich Offset = PV->Offset; 10121c2f4bbeSAlexander Yermolovich OldValueSize = PV->OldValueSize; 10131c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 10141c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 10151c2f4bbeSAlexander Yermolovich encodeULEB128(PV->Value, OS); 10161c2f4bbeSAlexander Yermolovich break; 10171c2f4bbeSAlexander Yermolovich } 10181c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64: { 10191c2f4bbeSAlexander Yermolovich DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 10201c2f4bbeSAlexander Yermolovich Offset = P64->Offset; 10211c2f4bbeSAlexander Yermolovich OldValueSize = 8; 10221c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(8, P64->Value); 10231c2f4bbeSAlexander Yermolovich break; 10241c2f4bbeSAlexander Yermolovich } 10251c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 10261c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 10271c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 10281c2f4bbeSAlexander Yermolovich Offset = BaseLabel->Offset; 10291c2f4bbeSAlexander Yermolovich OldValueSize = 0; 10301c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 10311c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 10321c2f4bbeSAlexander Yermolovich // Length to copy between last patch entry and next compile unit. 10331c2f4bbeSAlexander Yermolovich uint32_t RemainingLength = Offset - StartOffset; 10341c2f4bbeSAlexander Yermolovich uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 10351c2f4bbeSAlexander Yermolovich DwarfUnitBaseOffset = NewCUOffset; 10361c2f4bbeSAlexander Yermolovich // Length of previous CU = This CU Offset - sizeof(length) - last CU 10371c2f4bbeSAlexander Yermolovich // Offset. 10381c2f4bbeSAlexander Yermolovich Patch.second = NewCUOffset - 4 - Patch.first; 10391c2f4bbeSAlexander Yermolovich LengthPatches.push_back({NewCUOffset, 0}); 10401c2f4bbeSAlexander Yermolovich break; 10411c2f4bbeSAlexander Yermolovich } 1042bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 1043bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1044bd1ebe9dSAlexander Yermolovich Offset = NDE->Offset; 1045bd1ebe9dSAlexander Yermolovich OldValueSize = 0; 1046bd1ebe9dSAlexander Yermolovich ByteSequence = NDE->Value; 1047bd1ebe9dSAlexander Yermolovich break; 1048bd1ebe9dSAlexander Yermolovich } 10491c2f4bbeSAlexander Yermolovich } 10501c2f4bbeSAlexander Yermolovich 1051bd1ebe9dSAlexander Yermolovich assert((P->Kind == DebugPatchKind::NewDebugEntry || 1052bd1ebe9dSAlexander Yermolovich Offset + ByteSequence.size() <= BinaryContents.size()) && 10531c2f4bbeSAlexander Yermolovich "Applied patch runs over binary size."); 10541c2f4bbeSAlexander Yermolovich uint32_t Length = Offset - StartOffset; 10551c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 10561c2f4bbeSAlexander Yermolovich Length); 10571c2f4bbeSAlexander Yermolovich NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 10581c2f4bbeSAlexander Yermolovich StartOffset = Offset + OldValueSize; 10591c2f4bbeSAlexander Yermolovich } 10601c2f4bbeSAlexander Yermolovich uint32_t Length = BinaryContents.size() - StartOffset; 10611c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 10621c2f4bbeSAlexander Yermolovich Length); 10631c2f4bbeSAlexander Yermolovich DebugPatches.clear(); 10641c2f4bbeSAlexander Yermolovich 10651c2f4bbeSAlexander Yermolovich // Patching lengths of CUs 10661c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 10671c2f4bbeSAlexander Yermolovich Patch.second = NewBinaryContents.size() - 4 - Patch.first; 10681c2f4bbeSAlexander Yermolovich for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 10691c2f4bbeSAlexander Yermolovich const auto &Patch = LengthPatches[J]; 10701c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, Patch.second); 10711c2f4bbeSAlexander Yermolovich Offset = Patch.first; 10721c2f4bbeSAlexander Yermolovich for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 10731c2f4bbeSAlexander Yermolovich NewBinaryContents[Offset + I] = ByteSequence[I]; 10741c2f4bbeSAlexander Yermolovich } 10751c2f4bbeSAlexander Yermolovich 10761c2f4bbeSAlexander Yermolovich return NewBinaryContents; 1077a34c753fSRafael Auler } 1078a34c753fSRafael Auler 1079ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::initialize( 1080ba1ac98cSAlexander Yermolovich const DWARFSection &StrOffsetsSection, 1081ba1ac98cSAlexander Yermolovich const Optional<StrOffsetsContributionDescriptor> Contr) { 1082ba1ac98cSAlexander Yermolovich if (!Contr) 1083ba1ac98cSAlexander Yermolovich return; 1084ba1ac98cSAlexander Yermolovich 1085ba1ac98cSAlexander Yermolovich const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize(); 1086ba1ac98cSAlexander Yermolovich assert(DwarfOffsetByteSize == 4 && 1087ba1ac98cSAlexander Yermolovich "Dwarf String Offsets Byte Size is not supported."); 1088ba1ac98cSAlexander Yermolovich uint32_t Index = 0; 1089ba1ac98cSAlexander Yermolovich for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize) 1090ba1ac98cSAlexander Yermolovich IndexToAddressMap[Index++] = *reinterpret_cast<const uint32_t *>( 1091ba1ac98cSAlexander Yermolovich StrOffsetsSection.Data.data() + Contr->Base + Offset); 1092ba1ac98cSAlexander Yermolovich } 1093ba1ac98cSAlexander Yermolovich 1094ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) { 1095ba1ac98cSAlexander Yermolovich assert(IndexToAddressMap.count(Index) > 0 && "Index is not found."); 1096ba1ac98cSAlexander Yermolovich IndexToAddressMap[Index] = Address; 1097ba1ac98cSAlexander Yermolovich } 1098ba1ac98cSAlexander Yermolovich 1099ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::finalizeSection() { 1100ba1ac98cSAlexander Yermolovich if (IndexToAddressMap.empty()) 1101ba1ac98cSAlexander Yermolovich return; 1102ba1ac98cSAlexander Yermolovich // Writing out the header for each section. 1103ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4, 1104ba1ac98cSAlexander Yermolovich support::little); 1105ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5), 1106ba1ac98cSAlexander Yermolovich support::little); 1107ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0), 1108ba1ac98cSAlexander Yermolovich support::little); 1109ba1ac98cSAlexander Yermolovich for (const auto &Entry : IndexToAddressMap) 1110ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, Entry.second, support::little); 1111ba1ac98cSAlexander Yermolovich IndexToAddressMap.clear(); 1112ba1ac98cSAlexander Yermolovich } 1113ba1ac98cSAlexander Yermolovich 1114a34c753fSRafael Auler void DebugStrWriter::create() { 1115a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 1116a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 1117a34c753fSRafael Auler } 1118a34c753fSRafael Auler 1119a34c753fSRafael Auler void DebugStrWriter::initialize() { 1120ba1ac98cSAlexander Yermolovich auto StrSection = BC.DwCtx->getDWARFObj().getStrSection(); 1121a34c753fSRafael Auler (*StrStream) << StrSection; 1122a34c753fSRafael Auler } 1123a34c753fSRafael Auler 1124a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 1125e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 1126a34c753fSRafael Auler if (StrBuffer->empty()) 1127a34c753fSRafael Auler initialize(); 1128a34c753fSRafael Auler auto Offset = StrBuffer->size(); 1129a34c753fSRafael Auler (*StrStream) << Str; 1130a34c753fSRafael Auler StrStream->write_zeros(1); 1131a34c753fSRafael Auler return Offset; 1132a34c753fSRafael Auler } 1133a34c753fSRafael Auler 1134a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 1135a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 1136a34c753fSRafael Auler if (!Abbrevs) 1137a34c753fSRafael Auler return; 1138a34c753fSRafael Auler 113945f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 1140bd1ebe9dSAlexander Yermolovich const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 1141a34c753fSRafael Auler 11429f3f9d19SAlexander Yermolovich // We are duplicating abbrev sections, to handle the case where for one CU we 11439f3f9d19SAlexander Yermolovich // modify it, but for another we don't. 11449f3f9d19SAlexander Yermolovich auto UnitDataPtr = std::make_unique<AbbrevData>(); 11459f3f9d19SAlexander Yermolovich AbbrevData &UnitData = *UnitDataPtr.get(); 11469f3f9d19SAlexander Yermolovich UnitData.Buffer = std::make_unique<DebugBufferVector>(); 11479f3f9d19SAlexander Yermolovich UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 1148bd1ebe9dSAlexander Yermolovich 1149a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 1150a34c753fSRafael Auler 11519f3f9d19SAlexander Yermolovich // Returns true if AbbrevData is re-used, false otherwise. 11529f3f9d19SAlexander Yermolovich auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 11539f3f9d19SAlexander Yermolovich llvm::SHA1 Hasher; 11549f3f9d19SAlexander Yermolovich Hasher.update(AbbrevData); 1155330268baSArgyrios Kyrtzidis std::array<uint8_t, 20> Hash = Hasher.final(); 1156330268baSArgyrios Kyrtzidis StringRef Key((const char *)Hash.data(), Hash.size()); 11579f3f9d19SAlexander Yermolovich auto Iter = AbbrevDataCache.find(Key); 11589f3f9d19SAlexander Yermolovich if (Iter != AbbrevDataCache.end()) { 11599f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = Iter->second.get(); 11609f3f9d19SAlexander Yermolovich return true; 11619f3f9d19SAlexander Yermolovich } 11629f3f9d19SAlexander Yermolovich AbbrevDataCache[Key] = std::move(UnitDataPtr); 11639f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = &UnitData; 11649f3f9d19SAlexander Yermolovich return false; 11659f3f9d19SAlexander Yermolovich }; 1166a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 1167a34c753fSRafael Auler // contents. 1168bd1ebe9dSAlexander Yermolovich if (UnitPatches.empty() && AbbrevEntries.empty()) { 1169a34c753fSRafael Auler StringRef AbbrevSectionContents = 1170a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 1171a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 1172a34c753fSRafael Auler StringRef AbbrevContents; 1173a34c753fSRafael Auler 1174a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 1175a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 1176a34c753fSRafael Auler // Handle DWP section contribution. 1177a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 1178a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 1179a34c753fSRafael Auler if (!DWOEntry) 1180a34c753fSRafael Auler return; 1181a34c753fSRafael Auler 1182a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 1183a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 1184a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 1185a34c753fSRafael Auler DWOContrubution->Length); 118645f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 1187a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 118845f94abcSMaksim Panchenko 118945f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 119045f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 119145f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 119245f94abcSMaksim Panchenko // the set boundaries. 119345f94abcSMaksim Panchenko // 119445f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 119545f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 119645f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 11971c2f4bbeSAlexander Yermolovich for_each( 119845f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 119945f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 120045f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 120145f94abcSMaksim Panchenko }); 12021c2f4bbeSAlexander Yermolovich sort(AbbrevSetOffsets); 120345f94abcSMaksim Panchenko } 12041c2f4bbeSAlexander Yermolovich auto It = upper_bound(AbbrevSetOffsets, StartOffset); 120545f94abcSMaksim Panchenko const uint64_t EndOffset = 120645f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 1207a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 120845f94abcSMaksim Panchenko } else { 120945f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 121045f94abcSMaksim Panchenko // abbreviations for this unit only. 121145f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 1212a34c753fSRafael Auler } 1213a34c753fSRafael Auler 12149f3f9d19SAlexander Yermolovich if (!hashAndAddAbbrev(AbbrevContents)) { 1215a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 1216a34c753fSRafael Auler OS << AbbrevContents; 12179f3f9d19SAlexander Yermolovich } 1218a34c753fSRafael Auler return; 1219a34c753fSRafael Auler } 1220a34c753fSRafael Auler 1221a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 1222a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 1223a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 1224a34c753fSRafael Auler 1225a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 1226a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 1227a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 1228a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 1229a34c753fSRafael Auler Abbrev.attributes()) { 1230a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 1231a34c753fSRafael Auler bool Patched = false; 1232a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 1233a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 1234a34c753fSRafael Auler ++I) { 1235a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 1236a34c753fSRafael Auler continue; 1237a34c753fSRafael Auler 1238a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 1239a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 1240a34c753fSRafael Auler Patched = true; 1241a34c753fSRafael Auler break; 1242a34c753fSRafael Auler } 1243a34c753fSRafael Auler if (Patched) 1244a34c753fSRafael Auler continue; 1245a34c753fSRafael Auler } 1246a34c753fSRafael Auler 1247a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 1248a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 1249a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 1250a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 1251a34c753fSRafael Auler } 1252bd1ebe9dSAlexander Yermolovich const auto Entries = AbbrevEntries.find(&Abbrev); 1253bd1ebe9dSAlexander Yermolovich // Adding new Abbrevs for inserted entries. 1254bd1ebe9dSAlexander Yermolovich if (Entries != AbbrevEntries.end()) { 1255bd1ebe9dSAlexander Yermolovich for (const AbbrevEntry &Entry : Entries->second) { 1256bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Attr, OS); 1257bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Form, OS); 1258bd1ebe9dSAlexander Yermolovich } 1259bd1ebe9dSAlexander Yermolovich } 1260a34c753fSRafael Auler encodeULEB128(0, OS); 1261a34c753fSRafael Auler encodeULEB128(0, OS); 1262a34c753fSRafael Auler } 1263a34c753fSRafael Auler encodeULEB128(0, OS); 12649f3f9d19SAlexander Yermolovich 12659f3f9d19SAlexander Yermolovich hashAndAddAbbrev(OS.str()); 1266a34c753fSRafael Auler } 1267a34c753fSRafael Auler 1268a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 12699f3f9d19SAlexander Yermolovich // Used to create determinism for writing out abbrevs. 12709f3f9d19SAlexander Yermolovich std::vector<AbbrevData *> Abbrevs; 127145f94abcSMaksim Panchenko if (DWOId) { 127245f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 127345f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 127445f94abcSMaksim Panchenko // set with the CU. 12751417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 12761417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 127745f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 12781417f607SAlexander Yermolovich if (!IsDWP) { 127945f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 128045f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 128145f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 128245f94abcSMaksim Panchenko "Unable to update debug info.\n"; 128345f94abcSMaksim Panchenko exit(1); 128445f94abcSMaksim Panchenko } 128545f94abcSMaksim Panchenko } 128645f94abcSMaksim Panchenko } 128745f94abcSMaksim Panchenko 12889f3f9d19SAlexander Yermolovich DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 128945f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 129045f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 12919f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 12929f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 12939f3f9d19SAlexander Yermolovich } else { 12949f3f9d19SAlexander Yermolovich Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 12959f3f9d19SAlexander Yermolovich std::unordered_set<AbbrevData *> ProcessedAbbrevs; 12969f3f9d19SAlexander Yermolovich // Add abbreviations from compile and type non-DWO units. 12979f3f9d19SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 12989f3f9d19SAlexander Yermolovich addUnitAbbreviations(*Unit); 12999f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 13009f3f9d19SAlexander Yermolovich if (!ProcessedAbbrevs.insert(Abbrev).second) 13019f3f9d19SAlexander Yermolovich continue; 13029f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 13039f3f9d19SAlexander Yermolovich } 130445f94abcSMaksim Panchenko } 130545f94abcSMaksim Panchenko 1306a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 1307a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 1308a34c753fSRafael Auler uint64_t Size = 0; 13099f3f9d19SAlexander Yermolovich for (const AbbrevData *UnitData : Abbrevs) 13109f3f9d19SAlexander Yermolovich Size += UnitData->Buffer->size(); 13119f3f9d19SAlexander Yermolovich 1312a34c753fSRafael Auler ReturnBuffer.reserve(Size); 1313a34c753fSRafael Auler 1314a34c753fSRafael Auler uint64_t Pos = 0; 13159f3f9d19SAlexander Yermolovich for (AbbrevData *UnitData : Abbrevs) { 13169f3f9d19SAlexander Yermolovich ReturnBuffer.append(*UnitData->Buffer); 13179f3f9d19SAlexander Yermolovich UnitData->Offset = Pos; 13189f3f9d19SAlexander Yermolovich Pos += UnitData->Buffer->size(); 1319a34c753fSRafael Auler 13209f3f9d19SAlexander Yermolovich UnitData->Buffer.reset(); 13219f3f9d19SAlexander Yermolovich UnitData->Stream.reset(); 1322a34c753fSRafael Auler } 1323a34c753fSRafael Auler 1324a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 1325a34c753fSRafael Auler } 1326a34c753fSRafael Auler 1327a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 1328a34c753fSRafael Auler MCDwarfLineTableParams Params, 1329a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 1330a34c753fSRafael Auler int PointerSize) { 1331a34c753fSRafael Auler // emit the sequence to set the address 1332a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 1333a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 1334a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 1335a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 1336a34c753fSRafael Auler 1337a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 1338a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 1339a34c753fSRafael Auler } 1340a34c753fSRafael Auler 1341a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 1342a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 1343a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 1344a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 1345a34c753fSRafael Auler if (InputSequences.empty()) 1346a34c753fSRafael Auler return; 1347a34c753fSRafael Auler 1348a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 1349a34c753fSRafael Auler unsigned FileNum = 1; 1350a34c753fSRafael Auler unsigned LastLine = 1; 1351a34c753fSRafael Auler unsigned Column = 0; 1352a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1353a34c753fSRafael Auler unsigned Isa = 0; 1354a34c753fSRafael Auler unsigned Discriminator = 0; 1355a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 1356a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 1357a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1358a34c753fSRafael Auler 1359a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 1360a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1361a34c753fSRafael Auler FileNum = 1; 1362a34c753fSRafael Auler LastLine = 1; 1363a34c753fSRafael Auler Column = 0; 1364a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1365a34c753fSRafael Auler Isa = 0; 1366a34c753fSRafael Auler Discriminator = 0; 1367a34c753fSRafael Auler LastAddress = InvalidAddress; 1368a34c753fSRafael Auler }; 1369a34c753fSRafael Auler 1370a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1371a34c753fSRafael Auler const uint64_t SequenceStart = 1372a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 1373a34c753fSRafael Auler 1374a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 1375a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1376a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 1377a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1378a34c753fSRafael Auler } 1379a34c753fSRafael Auler 1380a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 1381a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 1382a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1383a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1384a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 1385a34c753fSRafael Auler 1386a34c753fSRafael Auler if (FileNum != Row.File) { 1387a34c753fSRafael Auler FileNum = Row.File; 1388a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1389a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1390a34c753fSRafael Auler } 1391a34c753fSRafael Auler if (Column != Row.Column) { 1392a34c753fSRafael Auler Column = Row.Column; 1393a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1394a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1395a34c753fSRafael Auler } 1396a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 1397a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1398a34c753fSRafael Auler Discriminator = Row.Discriminator; 1399a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1400a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1401a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1402a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1403a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1404a34c753fSRafael Auler } 1405a34c753fSRafael Auler if (Isa != Row.Isa) { 1406a34c753fSRafael Auler Isa = Row.Isa; 1407a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1408a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1409a34c753fSRafael Auler } 1410a34c753fSRafael Auler if (Row.IsStmt != Flags) { 1411a34c753fSRafael Auler Flags = Row.IsStmt; 1412a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1413a34c753fSRafael Auler } 1414a34c753fSRafael Auler if (Row.BasicBlock) 1415a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1416a34c753fSRafael Auler if (Row.PrologueEnd) 1417a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1418a34c753fSRafael Auler if (Row.EpilogueBegin) 1419a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1420a34c753fSRafael Auler 1421a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 1422a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 1423a34c753fSRafael Auler if (Row.EndSequence) { 1424a34c753fSRafael Auler emitEndOfSequence(Address); 1425a34c753fSRafael Auler } else { 1426a34c753fSRafael Auler if (LastAddress == InvalidAddress) 1427a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1428a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1429a34c753fSRafael Auler else 1430a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1431a34c753fSRafael Auler 1432a34c753fSRafael Auler LastAddress = Address; 1433a34c753fSRafael Auler LastLine = Row.Line; 1434a34c753fSRafael Auler } 1435a34c753fSRafael Auler 1436a34c753fSRafael Auler Discriminator = 0; 1437a34c753fSRafael Auler } 1438a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 1439a34c753fSRafael Auler } 1440a34c753fSRafael Auler 1441a34c753fSRafael Auler // Finish with the end of the sequence. 1442a34c753fSRafael Auler if (LastAddress != InvalidAddress) 1443a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1444a34c753fSRafael Auler } 1445a34c753fSRafael Auler 1446a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 1447a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 1448a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 1449a34c753fSRafael Auler static inline void emitDwarfLineTable( 1450a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 1451a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1452a34c753fSRafael Auler unsigned FileNum = 1; 1453a34c753fSRafael Auler unsigned LastLine = 1; 1454a34c753fSRafael Auler unsigned Column = 0; 1455a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1456a34c753fSRafael Auler unsigned Isa = 0; 1457a34c753fSRafael Auler unsigned Discriminator = 0; 1458a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 1459a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1460a34c753fSRafael Auler 1461a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1462a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1463a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1464a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1465a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1466a34c753fSRafael Auler FileNum = 1; 1467a34c753fSRafael Auler LastLine = 1; 1468a34c753fSRafael Auler Column = 0; 1469a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1470a34c753fSRafael Auler Isa = 0; 1471a34c753fSRafael Auler Discriminator = 0; 1472a34c753fSRafael Auler LastLabel = nullptr; 1473a34c753fSRafael Auler continue; 1474a34c753fSRafael Auler } 1475a34c753fSRafael Auler 1476a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1477a34c753fSRafael Auler 1478a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 1479a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 1480a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1481a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1482a34c753fSRafael Auler } 1483a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 1484a34c753fSRafael Auler Column = LineEntry.getColumn(); 1485a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1486a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1487a34c753fSRafael Auler } 1488a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 1489014cd37fSAlexander Yermolovich MCOS->getContext().getDwarfVersion() >= 2) { 1490a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 1491a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1492a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1493a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1494a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1495a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1496a34c753fSRafael Auler } 1497a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 1498a34c753fSRafael Auler Isa = LineEntry.getIsa(); 1499a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1500a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1501a34c753fSRafael Auler } 1502a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1503a34c753fSRafael Auler Flags = LineEntry.getFlags(); 1504a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1505a34c753fSRafael Auler } 1506a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1507a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1508a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1509a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1510a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1511a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1512a34c753fSRafael Auler 1513a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 1514a34c753fSRafael Auler 1515a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 1516a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 1517a34c753fSRafael Auler // Label and the current Label. 1518a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1519a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1520a34c753fSRafael Auler Discriminator = 0; 1521a34c753fSRafael Auler LastLine = LineEntry.getLine(); 1522a34c753fSRafael Auler LastLabel = Label; 1523a34c753fSRafael Auler } 1524a34c753fSRafael Auler 1525a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 1526a34c753fSRafael Auler } 1527a34c753fSRafael Auler 1528a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1529b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 1530b73c87bcSMaksim Panchenko BinaryContext &BC) const { 1531a34c753fSRafael Auler if (!RawData.empty()) { 1532a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 1533a34c753fSRafael Auler InputSequences.empty() && 1534a34c753fSRafael Auler "cannot combine raw data with new line entries"); 1535a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 1536a34c753fSRafael Auler MCOS->emitBytes(RawData); 1537a34c753fSRafael Auler 1538b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 1539b73c87bcSMaksim Panchenko // 1540b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1541b73c87bcSMaksim Panchenko // without relocations. 1542b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 1543b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1544b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1545b73c87bcSMaksim Panchenko 1546a34c753fSRafael Auler return; 1547a34c753fSRafael Auler } 1548a34c753fSRafael Auler 1549a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1550a34c753fSRafael Auler 1551a34c753fSRafael Auler // Put out the line tables. 1552a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1553a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1554a34c753fSRafael Auler 1555a34c753fSRafael Auler // Emit line tables for the original code. 1556a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1557a34c753fSRafael Auler 1558a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 1559a34c753fSRafael Auler // of this section (that was used in a previous expression). 1560a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 1561a34c753fSRafael Auler } 1562a34c753fSRafael Auler 1563014cd37fSAlexander Yermolovich // Helper function to parse .debug_line_str, and populate one we are using. 1564014cd37fSAlexander Yermolovich // For functions that we do not modify we output them as raw data. 1565014cd37fSAlexander Yermolovich // Re-constructing .debug_line_str so that offsets are correct for those 1566014cd37fSAlexander Yermolovich // debut line tables. 1567014cd37fSAlexander Yermolovich // Bonus is that when we output a final binary we can re-use .debug_line_str 1568014cd37fSAlexander Yermolovich // section. So we don't have to do the SHF_ALLOC trick we did with 1569014cd37fSAlexander Yermolovich // .debug_line. 1570014cd37fSAlexander Yermolovich static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, 1571014cd37fSAlexander Yermolovich MCDwarfLineStr &LineStr, 1572014cd37fSAlexander Yermolovich BinaryContext &BC, 1573014cd37fSAlexander Yermolovich MCStreamer &Streamer) { 1574014cd37fSAlexander Yermolovich DataExtractor StrData(LineStrSection.getContents(), 1575014cd37fSAlexander Yermolovich BC.DwCtx->isLittleEndian(), 0); 1576014cd37fSAlexander Yermolovich uint64_t Offset = 0; 1577014cd37fSAlexander Yermolovich while (StrData.isValidOffset(Offset)) { 1578014cd37fSAlexander Yermolovich Error Err = Error::success(); 1579014cd37fSAlexander Yermolovich const char *CStr = StrData.getCStr(&Offset, &Err); 1580014cd37fSAlexander Yermolovich if (Err) { 1581014cd37fSAlexander Yermolovich errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; 1582014cd37fSAlexander Yermolovich continue; 1583014cd37fSAlexander Yermolovich } 1584014cd37fSAlexander Yermolovich LineStr.emitRef(&Streamer, CStr); 1585014cd37fSAlexander Yermolovich } 1586014cd37fSAlexander Yermolovich } 1587014cd37fSAlexander Yermolovich 1588a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1589a34c753fSRafael Auler MCAssembler &Assembler = 1590a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1591a34c753fSRafael Auler 1592a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1593a34c753fSRafael Auler 1594a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 1595a34c753fSRafael Auler 1596a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 1597a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 1598a34c753fSRafael Auler if (LineTables.empty()) 1599a34c753fSRafael Auler return; 1600a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 1601a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 1602014cd37fSAlexander Yermolovich ErrorOr<BinarySection &> LineStrSection = 1603014cd37fSAlexander Yermolovich BC.getUniqueSectionByName(".debug_line_str"); 1604014cd37fSAlexander Yermolovich // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower 1605014cd37fSAlexander Yermolovich // .debug_line 1606014cd37fSAlexander Yermolovich if (LineStrSection) { 1607a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 1608014cd37fSAlexander Yermolovich parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer); 1609014cd37fSAlexander Yermolovich } 1610a34c753fSRafael Auler 1611a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 1612*adf4142fSFangrui Song Streamer.switchSection(BC.MOFI->getDwarfLineSection()); 1613a34c753fSRafael Auler 1614014cd37fSAlexander Yermolovich const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); 1615a34c753fSRafael Auler // Handle the rest of the Compile Units. 1616a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 1617014cd37fSAlexander Yermolovich Streamer.getContext().setDwarfVersion( 1618014cd37fSAlexander Yermolovich CUIDTablePair.second.getDwarfVersion()); 1619b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1620a34c753fSRafael Auler } 1621014cd37fSAlexander Yermolovich 1622014cd37fSAlexander Yermolovich // Resetting DWARF version for rest of the flow. 1623014cd37fSAlexander Yermolovich BC.Ctx->setDwarfVersion(DwarfVersion); 1624014cd37fSAlexander Yermolovich 1625014cd37fSAlexander Yermolovich // Still need to write the section out for the ExecutionEngine, and temp in 1626014cd37fSAlexander Yermolovich // memory object we are constructing. 1627014cd37fSAlexander Yermolovich if (LineStr) { 1628014cd37fSAlexander Yermolovich LineStr->emitSection(&Streamer); 1629014cd37fSAlexander Yermolovich SmallString<0> Data = LineStr->getFinalizedData(); 1630014cd37fSAlexander Yermolovich BC.registerOrUpdateNoteSection(".debug_line_str", copyByteArray(Data.str()), 1631014cd37fSAlexander Yermolovich Data.size()); 1632014cd37fSAlexander Yermolovich } 1633a34c753fSRafael Auler } 1634a34c753fSRafael Auler 1635a34c753fSRafael Auler } // namespace bolt 1636a34c753fSRafael Auler } // namespace llvm 1637