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. 316c4302e4fSAmir Ayupov llvm::sort(SortedMap, llvm::less_first()); 317a34c753fSRafael Auler for (auto &Pair : SortedMap) 318a34c753fSRafael Auler dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 319a34c753fSRafael Auler } 320ba1ac98cSAlexander Yermolovich uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { 321e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 322ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(CU); 323014cd37fSAlexander Yermolovich if (!AddressMaps.count(CUID)) 324014cd37fSAlexander Yermolovich AddressMaps[CUID] = AddressForDWOCU(); 325a34c753fSRafael Auler 326014cd37fSAlexander Yermolovich AddressForDWOCU &Map = AddressMaps[CUID]; 327a34c753fSRafael Auler auto Entry = Map.find(Address); 328a34c753fSRafael Auler if (Entry == Map.end()) { 329a34c753fSRafael Auler auto Index = Map.getNextIndex(); 330a34c753fSRafael Auler Entry = Map.insert(Address, Index).first; 331a34c753fSRafael Auler } 332a34c753fSRafael Auler return Entry->second; 333a34c753fSRafael Auler } 334a34c753fSRafael Auler 335a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 336a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update 337a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 338a34c753fSRafael Auler // update AddressToIndex and IndexToAddress 339a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 340ba1ac98cSAlexander Yermolovich DWARFUnit &CU) { 341e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 342ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(CU); 343014cd37fSAlexander Yermolovich AddressForDWOCU &Map = AddressMaps[CUID]; 344a34c753fSRafael Auler auto Entry = Map.find(Address); 345a34c753fSRafael Auler if (Entry != Map.end()) { 346a34c753fSRafael Auler if (Entry->second > Index) 347a34c753fSRafael Auler Map.updateAddressToIndex(Address, Index); 348a34c753fSRafael Auler Map.updateIndexToAddrss(Address, Index); 3493652483cSRafael Auler } else { 350a34c753fSRafael Auler Map.insert(Address, Index); 351a34c753fSRafael Auler } 3523652483cSRafael Auler } 353a34c753fSRafael Auler 354a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() { 355a34c753fSRafael Auler // Need to layout all sections within .debug_addr 356a34c753fSRafael Auler // Within each section sort Address by index. 357a34c753fSRafael Auler AddressSectionBuffer Buffer; 358a34c753fSRafael Auler raw_svector_ostream AddressStream(Buffer); 359a34c753fSRafael Auler for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 360a34c753fSRafael Auler // Handling the case wehre debug information is a mix of Debug fission and 361a34c753fSRafael Auler // monolitic. 362ba1ac98cSAlexander Yermolovich if (!CU->getDWOId()) 363a34c753fSRafael Auler continue; 364ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(*CU.get()); 365ba1ac98cSAlexander Yermolovich auto AM = AddressMaps.find(CUID); 366a34c753fSRafael Auler // Adding to map even if it did not contribute to .debug_addr. 3673abb68a6SAlexander Yermolovich // The Skeleton CU might still have DW_AT_GNU_addr_base. 368ba1ac98cSAlexander Yermolovich DWOIdToOffsetMap[CUID] = Buffer.size(); 369a34c753fSRafael Auler // If does not exist this CUs DWO section didn't contribute to .debug_addr. 370a34c753fSRafael Auler if (AM == AddressMaps.end()) 371a34c753fSRafael Auler continue; 372a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 373a34c753fSRafael Auler AM->second.indexToAdddessEnd()); 374a34c753fSRafael Auler // Sorting address in increasing order of indices. 375c4302e4fSAmir Ayupov llvm::sort(SortedMap, llvm::less_first()); 376a34c753fSRafael Auler 377a34c753fSRafael Auler uint8_t AddrSize = CU->getAddressByteSize(); 378a34c753fSRafael Auler uint32_t Counter = 0; 379a34c753fSRafael Auler auto WriteAddress = [&](uint64_t Address) -> void { 380a34c753fSRafael Auler ++Counter; 381a34c753fSRafael Auler switch (AddrSize) { 382a34c753fSRafael Auler default: 383a34c753fSRafael Auler assert(false && "Address Size is invalid."); 384a34c753fSRafael Auler break; 385a34c753fSRafael Auler case 4: 386a34c753fSRafael Auler support::endian::write(AddressStream, static_cast<uint32_t>(Address), 387a34c753fSRafael Auler support::little); 388a34c753fSRafael Auler break; 389a34c753fSRafael Auler case 8: 390a34c753fSRafael Auler support::endian::write(AddressStream, Address, support::little); 391a34c753fSRafael Auler break; 392a34c753fSRafael Auler } 393a34c753fSRafael Auler }; 394a34c753fSRafael Auler 395a34c753fSRafael Auler for (const IndexAddressPair &Val : SortedMap) { 396a34c753fSRafael Auler while (Val.first > Counter) 397a34c753fSRafael Auler WriteAddress(0); 398a34c753fSRafael Auler WriteAddress(Val.second); 399a34c753fSRafael Auler } 400a34c753fSRafael Auler } 401a34c753fSRafael Auler 402a34c753fSRafael Auler return Buffer; 403a34c753fSRafael Auler } 404014cd37fSAlexander Yermolovich AddressSectionBuffer DebugAddrWriterDwarf5::finalize() { 405014cd37fSAlexander Yermolovich // Need to layout all sections within .debug_addr 406014cd37fSAlexander Yermolovich // Within each section sort Address by index. 407014cd37fSAlexander Yermolovich AddressSectionBuffer Buffer; 408014cd37fSAlexander Yermolovich raw_svector_ostream AddressStream(Buffer); 409014cd37fSAlexander Yermolovich const endianness Endian = 410014cd37fSAlexander Yermolovich BC->DwCtx->isLittleEndian() ? support::little : support::big; 411014cd37fSAlexander Yermolovich const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection(); 412014cd37fSAlexander Yermolovich DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec, Endian, 0); 413014cd37fSAlexander Yermolovich DWARFDebugAddrTable AddrTable; 414014cd37fSAlexander Yermolovich DIDumpOptions DumpOpts; 415014cd37fSAlexander Yermolovich constexpr uint32_t HeaderSize = 8; 416014cd37fSAlexander Yermolovich for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 417ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(*CU.get()); 418014cd37fSAlexander Yermolovich const uint8_t AddrSize = CU->getAddressByteSize(); 419ba1ac98cSAlexander Yermolovich auto AMIter = AddressMaps.find(CUID); 420014cd37fSAlexander Yermolovich // A case where CU has entry in .debug_addr, but we don't modify addresses 421014cd37fSAlexander Yermolovich // for it. 422ba1ac98cSAlexander Yermolovich if (AMIter == AddressMaps.end()) { 423ba1ac98cSAlexander Yermolovich AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; 424014cd37fSAlexander Yermolovich Optional<uint64_t> BaseOffset = CU->getAddrOffsetSectionBase(); 425014cd37fSAlexander Yermolovich if (!BaseOffset) 426014cd37fSAlexander Yermolovich continue; 427014cd37fSAlexander Yermolovich // Address base offset is to the first entry. 428014cd37fSAlexander Yermolovich // The size of header is 8 bytes. 429014cd37fSAlexander Yermolovich uint64_t Offset = *BaseOffset - HeaderSize; 430014cd37fSAlexander Yermolovich if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize, 431014cd37fSAlexander Yermolovich DumpOpts.WarningHandler)) { 432014cd37fSAlexander Yermolovich DumpOpts.RecoverableErrorHandler(std::move(Err)); 433014cd37fSAlexander Yermolovich continue; 434014cd37fSAlexander Yermolovich } 435014cd37fSAlexander Yermolovich uint32_t Index = 0; 436014cd37fSAlexander Yermolovich for (uint64_t Addr : AddrTable.getAddressEntries()) 437ba1ac98cSAlexander Yermolovich AMIter->second.insert(Addr, Index++); 438014cd37fSAlexander Yermolovich } 439a34c753fSRafael Auler 440014cd37fSAlexander Yermolovich DWOIdToOffsetMap[CUID] = Buffer.size() + HeaderSize; 441014cd37fSAlexander Yermolovich 442ba1ac98cSAlexander Yermolovich std::vector<IndexAddressPair> SortedMap( 443ba1ac98cSAlexander Yermolovich AMIter->second.indexToAddressBegin(), 444ba1ac98cSAlexander Yermolovich AMIter->second.indexToAdddessEnd()); 445014cd37fSAlexander Yermolovich // Sorting address in increasing order of indices. 446c4302e4fSAmir Ayupov llvm::sort(SortedMap, llvm::less_first()); 447014cd37fSAlexander Yermolovich // Writing out Header 448014cd37fSAlexander Yermolovich const uint32_t Length = SortedMap.size() * AddrSize + 4; 449014cd37fSAlexander Yermolovich support::endian::write(AddressStream, Length, Endian); 450014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint16_t>(5), Endian); 451014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint8_t>(AddrSize), 452014cd37fSAlexander Yermolovich Endian); 453014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint8_t>(0), Endian); 454014cd37fSAlexander Yermolovich 455014cd37fSAlexander Yermolovich uint32_t Counter = 0; 456014cd37fSAlexander Yermolovich auto writeAddress = [&](uint64_t Address) -> void { 457014cd37fSAlexander Yermolovich ++Counter; 458014cd37fSAlexander Yermolovich switch (AddrSize) { 459014cd37fSAlexander Yermolovich default: 460014cd37fSAlexander Yermolovich llvm_unreachable("Address Size is invalid."); 461014cd37fSAlexander Yermolovich break; 462014cd37fSAlexander Yermolovich case 4: 463014cd37fSAlexander Yermolovich support::endian::write(AddressStream, static_cast<uint32_t>(Address), 464014cd37fSAlexander Yermolovich Endian); 465014cd37fSAlexander Yermolovich break; 466014cd37fSAlexander Yermolovich case 8: 467014cd37fSAlexander Yermolovich support::endian::write(AddressStream, Address, Endian); 468014cd37fSAlexander Yermolovich break; 469014cd37fSAlexander Yermolovich } 470014cd37fSAlexander Yermolovich }; 471014cd37fSAlexander Yermolovich 472014cd37fSAlexander Yermolovich for (const IndexAddressPair &Val : SortedMap) { 473014cd37fSAlexander Yermolovich while (Val.first > Counter) 474014cd37fSAlexander Yermolovich writeAddress(0); 475014cd37fSAlexander Yermolovich writeAddress(Val.second); 476014cd37fSAlexander Yermolovich } 477014cd37fSAlexander Yermolovich } 478014cd37fSAlexander Yermolovich 479014cd37fSAlexander Yermolovich return Buffer; 480014cd37fSAlexander Yermolovich } 481014cd37fSAlexander Yermolovich 482014cd37fSAlexander Yermolovich uint64_t DebugAddrWriter::getOffset(DWARFUnit &Unit) { 483ba1ac98cSAlexander Yermolovich const uint64_t CUID = getCUID(Unit); 484ba1ac98cSAlexander Yermolovich assert(CUID && "Can't get offset, not a skeleton CU."); 485ba1ac98cSAlexander Yermolovich auto Iter = DWOIdToOffsetMap.find(CUID); 486014cd37fSAlexander Yermolovich assert(Iter != DWOIdToOffsetMap.end() && 487014cd37fSAlexander Yermolovich "Offset in to.debug_addr was not found for DWO ID."); 488014cd37fSAlexander Yermolovich return Iter->second; 489014cd37fSAlexander Yermolovich } 490014cd37fSAlexander Yermolovich 491014cd37fSAlexander Yermolovich uint64_t DebugAddrWriterDwarf5::getOffset(DWARFUnit &Unit) { 492ba1ac98cSAlexander Yermolovich auto Iter = DWOIdToOffsetMap.find(getCUID(Unit)); 493a34c753fSRafael Auler assert(Iter != DWOIdToOffsetMap.end() && 4943abb68a6SAlexander Yermolovich "Offset in to.debug_addr was not found for CU ID."); 495a34c753fSRafael Auler return Iter->second; 496a34c753fSRafael Auler } 497a34c753fSRafael Auler 4981c6dc43dSAlexander Yermolovich void DebugLocWriter::init() { 499a34c753fSRafael Auler LocBuffer = std::make_unique<DebugBufferVector>(); 500a34c753fSRafael Auler LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 5011c6dc43dSAlexander Yermolovich // Writing out empty location list to which all references to empty location 5021c6dc43dSAlexander Yermolovich // lists will point. 5031c6dc43dSAlexander Yermolovich if (!LocSectionOffset && DwarfVersion < 5) { 5041c6dc43dSAlexander Yermolovich const char Zeroes[16] = {0}; 5051c6dc43dSAlexander Yermolovich *LocStream << StringRef(Zeroes, 16); 5061c6dc43dSAlexander Yermolovich LocSectionOffset += 16; 5071c6dc43dSAlexander Yermolovich } 508a34c753fSRafael Auler } 509a34c753fSRafael Auler 5101c6dc43dSAlexander Yermolovich uint32_t DebugLocWriter::LocSectionOffset = 0; 5111c6dc43dSAlexander Yermolovich void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList, 5121c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, 5131c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) { 5141c6dc43dSAlexander Yermolovich const uint64_t AttrOffset = AttrVal.Offset; 515a34c753fSRafael Auler if (LocList.empty()) { 5161c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); 517a34c753fSRafael Auler return; 518a34c753fSRafael Auler } 519a34c753fSRafael Auler // Since there is a separate DebugLocWriter for each thread, 520a34c753fSRafael Auler // we don't need a lock to read the SectionOffset and update it. 5211c6dc43dSAlexander Yermolovich const uint32_t EntryOffset = LocSectionOffset; 522a34c753fSRafael Auler 523a34c753fSRafael Auler for (const DebugLocationEntry &Entry : LocList) { 524a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 525a34c753fSRafael Auler support::little); 526a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 527a34c753fSRafael Auler support::little); 528a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 529a34c753fSRafael Auler support::little); 530a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 531a34c753fSRafael Auler Entry.Expr.size()); 5321c6dc43dSAlexander Yermolovich LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 533a34c753fSRafael Auler } 534a34c753fSRafael Auler LocStream->write_zeros(16); 5351c6dc43dSAlexander Yermolovich LocSectionOffset += 16; 536a34c753fSRafael Auler LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 5371c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); 538a34c753fSRafael Auler } 539a34c753fSRafael Auler 540a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 541a34c753fSRafael Auler return std::move(LocBuffer); 542a34c753fSRafael Auler } 543a34c753fSRafael Auler 544a34c753fSRafael Auler // DWARF 4: 2.6.2 5451c6dc43dSAlexander Yermolovich void DebugLocWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 5461c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) {} 547a34c753fSRafael Auler 548014cd37fSAlexander Yermolovich static void writeEmptyListDwarf5(raw_svector_ostream &Stream) { 549014cd37fSAlexander Yermolovich support::endian::write(Stream, static_cast<uint32_t>(4), support::little); 550014cd37fSAlexander Yermolovich support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end), 551014cd37fSAlexander Yermolovich support::little); 552014cd37fSAlexander Yermolovich 553014cd37fSAlexander Yermolovich const char Zeroes[16] = {0}; 554014cd37fSAlexander Yermolovich Stream << StringRef(Zeroes, 16); 555014cd37fSAlexander Yermolovich encodeULEB128(0, Stream); 556014cd37fSAlexander Yermolovich support::endian::write( 557014cd37fSAlexander Yermolovich Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little); 558014cd37fSAlexander Yermolovich } 559014cd37fSAlexander Yermolovich 5601c6dc43dSAlexander Yermolovich static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList, 5611c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, 5621c6dc43dSAlexander Yermolovich DebugAddrWriter &AddrWriter, 5631c6dc43dSAlexander Yermolovich DebugBufferVector &LocBuffer, DWARFUnit &CU, 5641c6dc43dSAlexander Yermolovich raw_svector_ostream &LocStream) { 5651c6dc43dSAlexander Yermolovich const uint64_t AttrOffset = AttrVal.Offset; 5661c6dc43dSAlexander Yermolovich if (LocList.empty()) { 5671c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset); 5681c6dc43dSAlexander Yermolovich return; 5691c6dc43dSAlexander Yermolovich } 5701c6dc43dSAlexander Yermolovich 5711c6dc43dSAlexander Yermolovich const uint32_t EntryOffset = LocBuffer.size(); 5721c6dc43dSAlexander Yermolovich for (const DebugLocationEntry &Entry : LocList) { 5731c6dc43dSAlexander Yermolovich support::endian::write(LocStream, 5741c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 5751c6dc43dSAlexander Yermolovich support::little); 5761c6dc43dSAlexander Yermolovich const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 5771c6dc43dSAlexander Yermolovich encodeULEB128(Index, LocStream); 5781c6dc43dSAlexander Yermolovich 5791c6dc43dSAlexander Yermolovich support::endian::write(LocStream, 5801c6dc43dSAlexander Yermolovich static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 5811c6dc43dSAlexander Yermolovich support::little); 5821c6dc43dSAlexander Yermolovich support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()), 5831c6dc43dSAlexander Yermolovich support::little); 5841c6dc43dSAlexander Yermolovich LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 5851c6dc43dSAlexander Yermolovich Entry.Expr.size()); 5861c6dc43dSAlexander Yermolovich } 5871c6dc43dSAlexander Yermolovich support::endian::write(LocStream, 5881c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 5891c6dc43dSAlexander Yermolovich support::little); 5901c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset); 5911c6dc43dSAlexander Yermolovich } 5921c6dc43dSAlexander Yermolovich 5931c6dc43dSAlexander Yermolovich static void writeDWARF5LocList( 5941c6dc43dSAlexander Yermolovich uint32_t &NumberOfEntries, AttrInfo &AttrVal, DebugLocationsVector &LocList, 5951c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter, 5961c6dc43dSAlexander Yermolovich DebugAddrWriter &AddrWriter, DebugBufferVector &LocBodyBuffer, 5971c6dc43dSAlexander Yermolovich std::vector<uint32_t> &RelativeLocListOffsets, DWARFUnit &CU, 5981c6dc43dSAlexander Yermolovich raw_svector_ostream &LocBodyStream) { 5991c6dc43dSAlexander Yermolovich if (AttrVal.V.getForm() != dwarf::DW_FORM_loclistx) { 6001c6dc43dSAlexander Yermolovich AbbrevWriter.addAttributePatch(CU, AttrVal.AbbrevDecl, 6011c6dc43dSAlexander Yermolovich dwarf::DW_AT_location, dwarf::DW_AT_location, 6021c6dc43dSAlexander Yermolovich dwarf::DW_FORM_loclistx); 6031c6dc43dSAlexander Yermolovich } 6041c6dc43dSAlexander Yermolovich DebugInfoPatcher.addUDataPatch(AttrVal.Offset, NumberOfEntries, AttrVal.Size); 6051c6dc43dSAlexander Yermolovich RelativeLocListOffsets.push_back(LocBodyBuffer.size()); 6061c6dc43dSAlexander Yermolovich ++NumberOfEntries; 6071c6dc43dSAlexander Yermolovich if (LocList.empty()) { 6081c6dc43dSAlexander Yermolovich writeEmptyListDwarf5(LocBodyStream); 6091c6dc43dSAlexander Yermolovich return; 6101c6dc43dSAlexander Yermolovich } 6111c6dc43dSAlexander Yermolovich 6121c6dc43dSAlexander Yermolovich std::vector<uint64_t> OffsetsArray; 6131c6dc43dSAlexander Yermolovich for (const DebugLocationEntry &Entry : LocList) { 6141c6dc43dSAlexander Yermolovich support::endian::write(LocBodyStream, 6151c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 6161c6dc43dSAlexander Yermolovich support::little); 6171c6dc43dSAlexander Yermolovich const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU); 6181c6dc43dSAlexander Yermolovich encodeULEB128(Index, LocBodyStream); 6191c6dc43dSAlexander Yermolovich encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream); 6201c6dc43dSAlexander Yermolovich encodeULEB128(Entry.Expr.size(), LocBodyStream); 6211c6dc43dSAlexander Yermolovich LocBodyStream << StringRef( 6221c6dc43dSAlexander Yermolovich reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size()); 6231c6dc43dSAlexander Yermolovich } 6241c6dc43dSAlexander Yermolovich support::endian::write(LocBodyStream, 6251c6dc43dSAlexander Yermolovich static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 6261c6dc43dSAlexander Yermolovich support::little); 6271c6dc43dSAlexander Yermolovich } 6281c6dc43dSAlexander Yermolovich 6291c6dc43dSAlexander Yermolovich void DebugLoclistWriter::addList(AttrInfo &AttrVal, 6301c6dc43dSAlexander Yermolovich DebugLocationsVector &LocList, 6311c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, 6321c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) { 6331c6dc43dSAlexander Yermolovich if (DwarfVersion < 5) 6341c6dc43dSAlexander Yermolovich writeLegacyLocList(AttrVal, LocList, DebugInfoPatcher, *AddrWriter, 6351c6dc43dSAlexander Yermolovich *LocBuffer, CU, *LocStream); 6361c6dc43dSAlexander Yermolovich else 6371c6dc43dSAlexander Yermolovich writeDWARF5LocList(NumberOfEntries, AttrVal, LocList, DebugInfoPatcher, 6381c6dc43dSAlexander Yermolovich AbbrevWriter, *AddrWriter, *LocBodyBuffer, 6391c6dc43dSAlexander Yermolovich RelativeLocListOffsets, CU, *LocBodyStream); 6401c6dc43dSAlexander Yermolovich } 6411c6dc43dSAlexander Yermolovich 6421c6dc43dSAlexander Yermolovich uint32_t DebugLoclistWriter::LoclistBaseOffset = 0; 6431c6dc43dSAlexander Yermolovich void DebugLoclistWriter::finalizeDWARF5( 6441c6dc43dSAlexander Yermolovich DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) { 6451c6dc43dSAlexander Yermolovich if (LocBodyBuffer->empty()) 6461c6dc43dSAlexander Yermolovich return; 647014cd37fSAlexander Yermolovich 648014cd37fSAlexander Yermolovich std::unique_ptr<DebugBufferVector> LocArrayBuffer = 649014cd37fSAlexander Yermolovich std::make_unique<DebugBufferVector>(); 650014cd37fSAlexander Yermolovich std::unique_ptr<raw_svector_ostream> LocArrayStream = 651014cd37fSAlexander Yermolovich std::make_unique<raw_svector_ostream>(*LocArrayBuffer); 652014cd37fSAlexander Yermolovich 6531c6dc43dSAlexander Yermolovich const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t); 654014cd37fSAlexander Yermolovich // Write out IndexArray 6551c6dc43dSAlexander Yermolovich for (uint32_t RelativeOffset : RelativeLocListOffsets) 656014cd37fSAlexander Yermolovich support::endian::write( 657014cd37fSAlexander Yermolovich *LocArrayStream, 6581c6dc43dSAlexander Yermolovich static_cast<uint32_t>(SizeOfArraySection + RelativeOffset), 659014cd37fSAlexander Yermolovich support::little); 6601c6dc43dSAlexander Yermolovich 6611c6dc43dSAlexander Yermolovich std::unique_ptr<DebugBufferVector> Header = getDWARF5Header( 6621c6dc43dSAlexander Yermolovich {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()), 6631c6dc43dSAlexander Yermolovich 5, 8, 0, NumberOfEntries}); 664014cd37fSAlexander Yermolovich *LocStream << *Header; 665014cd37fSAlexander Yermolovich *LocStream << *LocArrayBuffer; 666014cd37fSAlexander Yermolovich *LocStream << *LocBodyBuffer; 6671c6dc43dSAlexander Yermolovich 6681c6dc43dSAlexander Yermolovich if (!isSplitDwarf()) { 6691c6dc43dSAlexander Yermolovich if (Optional<AttrInfo> AttrInfoVal = 6701c6dc43dSAlexander Yermolovich findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base)) 6711c6dc43dSAlexander Yermolovich DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset, 6721c6dc43dSAlexander Yermolovich LoclistBaseOffset + 6731c6dc43dSAlexander Yermolovich getDWARF5RngListLocListHeaderSize()); 6741c6dc43dSAlexander Yermolovich else { 6751c6dc43dSAlexander Yermolovich AbbrevWriter.addAttribute( 6761c6dc43dSAlexander Yermolovich CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(), 6771c6dc43dSAlexander Yermolovich dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset); 6781c6dc43dSAlexander Yermolovich DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(), 6791c6dc43dSAlexander Yermolovich LoclistBaseOffset + Header->size()); 680014cd37fSAlexander Yermolovich } 6811c6dc43dSAlexander Yermolovich LoclistBaseOffset += LocBuffer->size(); 6821c6dc43dSAlexander Yermolovich } 6831c6dc43dSAlexander Yermolovich clearList(RelativeLocListOffsets); 6841c6dc43dSAlexander Yermolovich clearList(*LocArrayBuffer); 6851c6dc43dSAlexander Yermolovich clearList(*LocBodyBuffer); 686014cd37fSAlexander Yermolovich } 687014cd37fSAlexander Yermolovich 6881c6dc43dSAlexander Yermolovich void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher, 6891c6dc43dSAlexander Yermolovich DebugAbbrevWriter &AbbrevWriter) { 6901c6dc43dSAlexander Yermolovich if (DwarfVersion >= 5) 6911c6dc43dSAlexander Yermolovich finalizeDWARF5(DebugInfoPatcher, AbbrevWriter); 692014cd37fSAlexander Yermolovich } 693014cd37fSAlexander Yermolovich 694a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 695a34c753fSRafael Auler 6961c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 6971c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 6981c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 699ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 700a34c753fSRafael Auler } 701a34c753fSRafael Auler 7021c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 7031c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7041c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7051c2f4bbeSAlexander Yermolovich auto RetVal = DestinationLabels.insert(Offset); 7061c2f4bbeSAlexander Yermolovich if (!RetVal.second) 7071c2f4bbeSAlexander Yermolovich return; 7081c2f4bbeSAlexander Yermolovich 709ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 710a34c753fSRafael Auler } 711a34c753fSRafael Auler 712bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 713bd1ebe9dSAlexander Yermolovich std::string LE64(ByteSize, 0); 714bd1ebe9dSAlexander Yermolovich for (size_t I = 0; I < ByteSize; ++I) { 715bd1ebe9dSAlexander Yermolovich LE64[I] = NewValue & 0xff; 716bd1ebe9dSAlexander Yermolovich NewValue >>= 8; 717bd1ebe9dSAlexander Yermolovich } 718bd1ebe9dSAlexander Yermolovich return LE64; 719bd1ebe9dSAlexander Yermolovich } 720bd1ebe9dSAlexander Yermolovich 721bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 722bd1ebe9dSAlexander Yermolovich uint32_t Value) { 723bd1ebe9dSAlexander Yermolovich std::string StrValue = encodeLE(4, Value); 724bd1ebe9dSAlexander Yermolovich insertNewEntry(DIE, std::move(StrValue)); 725bd1ebe9dSAlexander Yermolovich } 726bd1ebe9dSAlexander Yermolovich 727bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 728bd1ebe9dSAlexander Yermolovich std::string &&Value) { 729bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl = 730bd1ebe9dSAlexander Yermolovich DIE.getAbbreviationDeclarationPtr(); 731bd1ebe9dSAlexander Yermolovich 732bd1ebe9dSAlexander Yermolovich // In case this DIE has no attributes. 733bd1ebe9dSAlexander Yermolovich uint32_t Offset = DIE.getOffset() + 1; 734bd1ebe9dSAlexander Yermolovich size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 735bd1ebe9dSAlexander Yermolovich if (NumOfAttributes) { 736bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> Val = 737bd1ebe9dSAlexander Yermolovich findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 738bd1ebe9dSAlexander Yermolovich assert(Val && "Invalid Value."); 739bd1ebe9dSAlexander Yermolovich 740bd1ebe9dSAlexander Yermolovich Offset = Val->Offset + Val->Size - DWPUnitOffset; 741bd1ebe9dSAlexander Yermolovich } 742bd1ebe9dSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 743bd1ebe9dSAlexander Yermolovich DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 744bd1ebe9dSAlexander Yermolovich } 745bd1ebe9dSAlexander Yermolovich 7461c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 7471c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset, 7481c2f4bbeSAlexander Yermolovich uint32_t OldValueSize, 7491c2f4bbeSAlexander Yermolovich dwarf::Form Form) { 7501c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7511c2f4bbeSAlexander Yermolovich DestinationOffset -= DWPUnitOffset; 7521c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 753ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back( 754ea6c8b01SAlexander Yermolovich new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 7551c2f4bbeSAlexander Yermolovich } 7561c2f4bbeSAlexander Yermolovich 7571c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 7581c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7591c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7601c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7611c2f4bbeSAlexander Yermolovich DebugPatches.emplace_back( 762ea6c8b01SAlexander Yermolovich new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 7631c2f4bbeSAlexander Yermolovich } 7641c2f4bbeSAlexander Yermolovich 7651c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 7661c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7671c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 768ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 7691c2f4bbeSAlexander Yermolovich } 7701c2f4bbeSAlexander Yermolovich 7711c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 7721c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7731c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 7741c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 7751c2f4bbeSAlexander Yermolovich if (OldValueSize == 4) 776ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 777a44fe319SAlexander Yermolovich else if (OldValueSize == 8) 778ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 779a44fe319SAlexander Yermolovich else 780a44fe319SAlexander Yermolovich DebugPatches.emplace_back( 781a44fe319SAlexander Yermolovich new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); 7821c2f4bbeSAlexander Yermolovich } 7831c2f4bbeSAlexander Yermolovich 7841c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 7851c2f4bbeSAlexander Yermolovich std::string &&NewValue, 7861c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 7871c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(NewValue)); 7881c2f4bbeSAlexander Yermolovich } 7891c2f4bbeSAlexander Yermolovich 7901c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 7911c2f4bbeSAlexander Yermolovich auto Str = std::string(1, Value); 7921c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Str)); 7931c2f4bbeSAlexander Yermolovich } 7941c2f4bbeSAlexander Yermolovich 7951c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 7961c2f4bbeSAlexander Yermolovich size_t ByteSize) { 7971c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 7981c2f4bbeSAlexander Yermolovich } 7991c2f4bbeSAlexander Yermolovich 8001c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 8011c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 802a34c753fSRafael Auler std::string Buff; 803a34c753fSRafael Auler raw_string_ostream OS(Buff); 8041c2f4bbeSAlexander Yermolovich encodeULEB128(Value, OS, OldValueSize); 805a34c753fSRafael Auler 8061c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Buff)); 807a34c753fSRafael Auler } 808a34c753fSRafael Auler 8091c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 810a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 811a34c753fSRafael Auler } 812a34c753fSRafael Auler 8131c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 8141c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 815a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 816a34c753fSRafael Auler } 817a34c753fSRafael Auler 8181c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 8191c2f4bbeSAlexander Yermolovich std::string BinaryContentsStr = std::string(BinaryContents); 820a34c753fSRafael Auler for (const auto &Patch : Patches) { 8211c2f4bbeSAlexander Yermolovich uint32_t Offset = Patch.first; 822a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 823a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 824a34c753fSRafael Auler "Applied patch runs over binary size."); 825a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 8261c2f4bbeSAlexander Yermolovich BinaryContentsStr[Offset + I] = ByteSequence[I]; 827a34c753fSRafael Auler } 828a34c753fSRafael Auler } 8291c2f4bbeSAlexander Yermolovich return BinaryContentsStr; 8301c2f4bbeSAlexander Yermolovich } 8311c2f4bbeSAlexander Yermolovich 832612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 833612f0f45SAlexander Yermolovich bool IsDWOContext) { 834612f0f45SAlexander Yermolovich CUOffsetMap CUMap; 835d2c87699SAmir Ayupov llvm::sort(DebugPatches, [](const UniquePatchPtrType &V1, 836d2c87699SAmir Ayupov const UniquePatchPtrType &V2) { 837bd1ebe9dSAlexander Yermolovich if (V1.get()->Offset == V2.get()->Offset) { 838bd1ebe9dSAlexander Yermolovich if (V1->Kind == DebugPatchKind::NewDebugEntry && 839bd1ebe9dSAlexander Yermolovich V2->Kind == DebugPatchKind::NewDebugEntry) 840d2c87699SAmir Ayupov return reinterpret_cast<const NewDebugEntry *>(V1.get())->CurrentOrder < 841d2c87699SAmir Ayupov reinterpret_cast<const NewDebugEntry *>(V2.get())->CurrentOrder; 842bd1ebe9dSAlexander Yermolovich 843bd1ebe9dSAlexander Yermolovich // This is a case where we are modifying first entry of next 844bd1ebe9dSAlexander Yermolovich // DIE, and adding a new one. 845bd1ebe9dSAlexander Yermolovich return V1->Kind == DebugPatchKind::NewDebugEntry; 846bd1ebe9dSAlexander Yermolovich } 8471c2f4bbeSAlexander Yermolovich return V1.get()->Offset < V2.get()->Offset; 8481c2f4bbeSAlexander Yermolovich }); 8491c2f4bbeSAlexander Yermolovich 850612f0f45SAlexander Yermolovich DWARFUnitVector::compile_unit_range CompileUnits = 851612f0f45SAlexander Yermolovich IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 852612f0f45SAlexander Yermolovich 853612f0f45SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 854612f0f45SAlexander Yermolovich CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 855612f0f45SAlexander Yermolovich static_cast<uint32_t>(CU->getLength())}; 856612f0f45SAlexander Yermolovich 8571c2f4bbeSAlexander Yermolovich // Calculating changes in .debug_info size from Patches to build a map of old 8581c2f4bbeSAlexander Yermolovich // to updated reference destination offsets. 859612f0f45SAlexander Yermolovich uint32_t PreviousOffset = 0; 860612f0f45SAlexander Yermolovich int32_t PreviousChangeInSize = 0; 861ea6c8b01SAlexander Yermolovich for (UniquePatchPtrType &PatchBase : DebugPatches) { 8621c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 8631c2f4bbeSAlexander Yermolovich switch (P->Kind) { 8641c2f4bbeSAlexander Yermolovich default: 8651c2f4bbeSAlexander Yermolovich continue; 8661c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 867612f0f45SAlexander Yermolovich PreviousChangeInSize -= 4; 8681c2f4bbeSAlexander Yermolovich break; 8691c2f4bbeSAlexander Yermolovich } 870a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 871a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 872a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 873a44fe319SAlexander Yermolovich PreviousChangeInSize += 4 - DPVS->OldValueSize; 874a44fe319SAlexander Yermolovich break; 875a44fe319SAlexander Yermolovich } 8761c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 8771c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *DPV = 8781c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 8791c2f4bbeSAlexander Yermolovich std::string Temp; 8801c2f4bbeSAlexander Yermolovich raw_string_ostream OS(Temp); 8811c2f4bbeSAlexander Yermolovich encodeULEB128(DPV->Value, OS); 882612f0f45SAlexander Yermolovich PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 8831c2f4bbeSAlexander Yermolovich break; 8841c2f4bbeSAlexander Yermolovich } 8851c2f4bbeSAlexander Yermolovich case DebugPatchKind::DestinationReferenceLabel: { 8861c2f4bbeSAlexander Yermolovich DestinationReferenceLabel *DRL = 8871c2f4bbeSAlexander Yermolovich reinterpret_cast<DestinationReferenceLabel *>(P); 888612f0f45SAlexander Yermolovich OldToNewOffset[DRL->Offset] = 889612f0f45SAlexander Yermolovich DRL->Offset + ChangeInSize + PreviousChangeInSize; 8901c2f4bbeSAlexander Yermolovich break; 8911c2f4bbeSAlexander Yermolovich } 8921c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 8931c2f4bbeSAlexander Yermolovich // This doesn't look to be a common case, so will always encode as 4 bytes 8941c2f4bbeSAlexander Yermolovich // to reduce algorithmic complexity. 8951c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 8961c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.IndirectRelative) { 897612f0f45SAlexander Yermolovich PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 8981c2f4bbeSAlexander Yermolovich assert(RDP->PatchInfo.OldValueSize <= 4 && 8991c2f4bbeSAlexander Yermolovich "Variable encoding reference greater than 4 bytes."); 9001c2f4bbeSAlexander Yermolovich } 9011c2f4bbeSAlexander Yermolovich break; 9021c2f4bbeSAlexander Yermolovich } 9031c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 9041c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 9051c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 9061c2f4bbeSAlexander Yermolovich uint32_t CUOffset = BaseLabel->Offset; 907612f0f45SAlexander Yermolovich ChangeInSize += PreviousChangeInSize; 9081c2f4bbeSAlexander Yermolovich uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 909612f0f45SAlexander Yermolovich CUMap[CUOffset].Offset = CUOffsetUpdate; 910612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 911612f0f45SAlexander Yermolovich PreviousChangeInSize = 0; 912612f0f45SAlexander Yermolovich PreviousOffset = CUOffset; 913bd1ebe9dSAlexander Yermolovich break; 914bd1ebe9dSAlexander Yermolovich } 915bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 916bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 917bd1ebe9dSAlexander Yermolovich PreviousChangeInSize += NDE->Value.size(); 918bd1ebe9dSAlexander Yermolovich break; 9191c2f4bbeSAlexander Yermolovich } 9201c2f4bbeSAlexander Yermolovich } 9211c2f4bbeSAlexander Yermolovich } 922612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 9231c2f4bbeSAlexander Yermolovich return CUMap; 9241c2f4bbeSAlexander Yermolovich } 925bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 9261c2f4bbeSAlexander Yermolovich 9271c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 9281c2f4bbeSAlexander Yermolovich std::string NewBinaryContents; 9291c2f4bbeSAlexander Yermolovich NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 9301c2f4bbeSAlexander Yermolovich uint32_t StartOffset = 0; 9311c2f4bbeSAlexander Yermolovich uint32_t DwarfUnitBaseOffset = 0; 9321c2f4bbeSAlexander Yermolovich uint32_t OldValueSize = 0; 9331c2f4bbeSAlexander Yermolovich uint32_t Offset = 0; 9341c2f4bbeSAlexander Yermolovich std::string ByteSequence; 9351c2f4bbeSAlexander Yermolovich std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 9361c2f4bbeSAlexander Yermolovich // Wasting one entry to avoid checks for first. 9371c2f4bbeSAlexander Yermolovich LengthPatches.push_back({0, 0}); 9381c2f4bbeSAlexander Yermolovich 9391c2f4bbeSAlexander Yermolovich // Applying all the patches replacing current entry. 9401c2f4bbeSAlexander Yermolovich // This might change the size of .debug_info section. 941ea6c8b01SAlexander Yermolovich for (const UniquePatchPtrType &PatchBase : DebugPatches) { 9421c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 9431c2f4bbeSAlexander Yermolovich switch (P->Kind) { 9441c2f4bbeSAlexander Yermolovich default: 9451c2f4bbeSAlexander Yermolovich continue; 9461c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 9471c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 9481c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset = RDP->DestinationOffset; 9491c2f4bbeSAlexander Yermolovich assert(OldToNewOffset.count(DestinationOffset) && 9501c2f4bbeSAlexander Yermolovich "Destination Offset for reference not updated."); 9511c2f4bbeSAlexander Yermolovich uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 9521c2f4bbeSAlexander Yermolovich Offset = RDP->Offset; 9531c2f4bbeSAlexander Yermolovich OldValueSize = RDP->PatchInfo.OldValueSize; 9541c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.DirectRelative) { 9551c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 9561c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 9571c2f4bbeSAlexander Yermolovich // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 9581c2f4bbeSAlexander Yermolovich // and overflow if later debug information grows. 9591c2f4bbeSAlexander Yermolovich if (ByteSequence.size() > OldValueSize) 9601c2f4bbeSAlexander Yermolovich errs() << "BOLT-ERROR: Relative reference of size " 9611c2f4bbeSAlexander Yermolovich << Twine::utohexstr(OldValueSize) 9621c2f4bbeSAlexander Yermolovich << " overflows with the new encoding.\n"; 9631c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.DirectAbsolute) { 9641c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 9651c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.IndirectRelative) { 9661c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 9671c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 9681c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 9691c2f4bbeSAlexander Yermolovich encodeULEB128(UpdatedOffset, OS, 4); 9701c2f4bbeSAlexander Yermolovich } else { 9711c2f4bbeSAlexander Yermolovich llvm_unreachable("Invalid Reference form."); 9721c2f4bbeSAlexander Yermolovich } 9731c2f4bbeSAlexander Yermolovich break; 9741c2f4bbeSAlexander Yermolovich } 9751c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue32: { 9761c2f4bbeSAlexander Yermolovich DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 9771c2f4bbeSAlexander Yermolovich Offset = P32->Offset; 9781c2f4bbeSAlexander Yermolovich OldValueSize = 4; 9791c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P32->Value); 9801c2f4bbeSAlexander Yermolovich break; 9811c2f4bbeSAlexander Yermolovich } 9821c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 9831c2f4bbeSAlexander Yermolovich DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 9841c2f4bbeSAlexander Yermolovich Offset = P64to32->Offset; 9851c2f4bbeSAlexander Yermolovich OldValueSize = 8; 9861c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P64to32->Value); 9871c2f4bbeSAlexander Yermolovich break; 9881c2f4bbeSAlexander Yermolovich } 989a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 990a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 991a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 992a44fe319SAlexander Yermolovich Offset = DPVS->Offset; 993a44fe319SAlexander Yermolovich OldValueSize = DPVS->OldValueSize; 994a44fe319SAlexander Yermolovich ByteSequence = encodeLE(4, DPVS->Value); 995a44fe319SAlexander Yermolovich break; 996a44fe319SAlexander Yermolovich } 9971c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 9981c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *PV = 9991c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 10001c2f4bbeSAlexander Yermolovich Offset = PV->Offset; 10011c2f4bbeSAlexander Yermolovich OldValueSize = PV->OldValueSize; 10021c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 10031c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 10041c2f4bbeSAlexander Yermolovich encodeULEB128(PV->Value, OS); 10051c2f4bbeSAlexander Yermolovich break; 10061c2f4bbeSAlexander Yermolovich } 10071c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64: { 10081c2f4bbeSAlexander Yermolovich DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 10091c2f4bbeSAlexander Yermolovich Offset = P64->Offset; 10101c2f4bbeSAlexander Yermolovich OldValueSize = 8; 10111c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(8, P64->Value); 10121c2f4bbeSAlexander Yermolovich break; 10131c2f4bbeSAlexander Yermolovich } 10141c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 10151c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 10161c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 10171c2f4bbeSAlexander Yermolovich Offset = BaseLabel->Offset; 10181c2f4bbeSAlexander Yermolovich OldValueSize = 0; 10191c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 10201c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 10211c2f4bbeSAlexander Yermolovich // Length to copy between last patch entry and next compile unit. 10221c2f4bbeSAlexander Yermolovich uint32_t RemainingLength = Offset - StartOffset; 10231c2f4bbeSAlexander Yermolovich uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 10241c2f4bbeSAlexander Yermolovich DwarfUnitBaseOffset = NewCUOffset; 10251c2f4bbeSAlexander Yermolovich // Length of previous CU = This CU Offset - sizeof(length) - last CU 10261c2f4bbeSAlexander Yermolovich // Offset. 10271c2f4bbeSAlexander Yermolovich Patch.second = NewCUOffset - 4 - Patch.first; 10281c2f4bbeSAlexander Yermolovich LengthPatches.push_back({NewCUOffset, 0}); 10291c2f4bbeSAlexander Yermolovich break; 10301c2f4bbeSAlexander Yermolovich } 1031bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 1032bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 1033bd1ebe9dSAlexander Yermolovich Offset = NDE->Offset; 1034bd1ebe9dSAlexander Yermolovich OldValueSize = 0; 1035bd1ebe9dSAlexander Yermolovich ByteSequence = NDE->Value; 1036bd1ebe9dSAlexander Yermolovich break; 1037bd1ebe9dSAlexander Yermolovich } 10381c2f4bbeSAlexander Yermolovich } 10391c2f4bbeSAlexander Yermolovich 1040bd1ebe9dSAlexander Yermolovich assert((P->Kind == DebugPatchKind::NewDebugEntry || 1041bd1ebe9dSAlexander Yermolovich Offset + ByteSequence.size() <= BinaryContents.size()) && 10421c2f4bbeSAlexander Yermolovich "Applied patch runs over binary size."); 10431c2f4bbeSAlexander Yermolovich uint32_t Length = Offset - StartOffset; 10441c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 10451c2f4bbeSAlexander Yermolovich Length); 10461c2f4bbeSAlexander Yermolovich NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 10471c2f4bbeSAlexander Yermolovich StartOffset = Offset + OldValueSize; 10481c2f4bbeSAlexander Yermolovich } 10491c2f4bbeSAlexander Yermolovich uint32_t Length = BinaryContents.size() - StartOffset; 10501c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 10511c2f4bbeSAlexander Yermolovich Length); 10521c2f4bbeSAlexander Yermolovich DebugPatches.clear(); 10531c2f4bbeSAlexander Yermolovich 10541c2f4bbeSAlexander Yermolovich // Patching lengths of CUs 10551c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 10561c2f4bbeSAlexander Yermolovich Patch.second = NewBinaryContents.size() - 4 - Patch.first; 10571c2f4bbeSAlexander Yermolovich for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 10581c2f4bbeSAlexander Yermolovich const auto &Patch = LengthPatches[J]; 10591c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, Patch.second); 10601c2f4bbeSAlexander Yermolovich Offset = Patch.first; 10611c2f4bbeSAlexander Yermolovich for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 10621c2f4bbeSAlexander Yermolovich NewBinaryContents[Offset + I] = ByteSequence[I]; 10631c2f4bbeSAlexander Yermolovich } 10641c2f4bbeSAlexander Yermolovich 10651c2f4bbeSAlexander Yermolovich return NewBinaryContents; 1066a34c753fSRafael Auler } 1067a34c753fSRafael Auler 1068ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::initialize( 1069ba1ac98cSAlexander Yermolovich const DWARFSection &StrOffsetsSection, 1070ba1ac98cSAlexander Yermolovich const Optional<StrOffsetsContributionDescriptor> Contr) { 1071ba1ac98cSAlexander Yermolovich if (!Contr) 1072ba1ac98cSAlexander Yermolovich return; 1073ba1ac98cSAlexander Yermolovich 1074ba1ac98cSAlexander Yermolovich const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize(); 1075ba1ac98cSAlexander Yermolovich assert(DwarfOffsetByteSize == 4 && 1076ba1ac98cSAlexander Yermolovich "Dwarf String Offsets Byte Size is not supported."); 1077ba1ac98cSAlexander Yermolovich uint32_t Index = 0; 1078ba1ac98cSAlexander Yermolovich for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize) 1079ba1ac98cSAlexander Yermolovich IndexToAddressMap[Index++] = *reinterpret_cast<const uint32_t *>( 1080ba1ac98cSAlexander Yermolovich StrOffsetsSection.Data.data() + Contr->Base + Offset); 1081ba1ac98cSAlexander Yermolovich } 1082ba1ac98cSAlexander Yermolovich 1083ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) { 1084ba1ac98cSAlexander Yermolovich assert(IndexToAddressMap.count(Index) > 0 && "Index is not found."); 1085ba1ac98cSAlexander Yermolovich IndexToAddressMap[Index] = Address; 1086ba1ac98cSAlexander Yermolovich } 1087ba1ac98cSAlexander Yermolovich 1088ba1ac98cSAlexander Yermolovich void DebugStrOffsetsWriter::finalizeSection() { 1089ba1ac98cSAlexander Yermolovich if (IndexToAddressMap.empty()) 1090ba1ac98cSAlexander Yermolovich return; 1091ba1ac98cSAlexander Yermolovich // Writing out the header for each section. 1092ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, CurrentSectionSize + 4, 1093ba1ac98cSAlexander Yermolovich support::little); 1094ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5), 1095ba1ac98cSAlexander Yermolovich support::little); 1096ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0), 1097ba1ac98cSAlexander Yermolovich support::little); 1098ba1ac98cSAlexander Yermolovich for (const auto &Entry : IndexToAddressMap) 1099ba1ac98cSAlexander Yermolovich support::endian::write(*StrOffsetsStream, Entry.second, support::little); 1100ba1ac98cSAlexander Yermolovich IndexToAddressMap.clear(); 1101ba1ac98cSAlexander Yermolovich } 1102ba1ac98cSAlexander Yermolovich 1103a34c753fSRafael Auler void DebugStrWriter::create() { 1104a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 1105a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 1106a34c753fSRafael Auler } 1107a34c753fSRafael Auler 1108a34c753fSRafael Auler void DebugStrWriter::initialize() { 1109ba1ac98cSAlexander Yermolovich auto StrSection = BC.DwCtx->getDWARFObj().getStrSection(); 1110a34c753fSRafael Auler (*StrStream) << StrSection; 1111a34c753fSRafael Auler } 1112a34c753fSRafael Auler 1113a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 1114e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 1115a34c753fSRafael Auler if (StrBuffer->empty()) 1116a34c753fSRafael Auler initialize(); 1117a34c753fSRafael Auler auto Offset = StrBuffer->size(); 1118a34c753fSRafael Auler (*StrStream) << Str; 1119a34c753fSRafael Auler StrStream->write_zeros(1); 1120a34c753fSRafael Auler return Offset; 1121a34c753fSRafael Auler } 1122a34c753fSRafael Auler 1123a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 1124a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 1125a34c753fSRafael Auler if (!Abbrevs) 1126a34c753fSRafael Auler return; 1127a34c753fSRafael Auler 112845f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 1129bd1ebe9dSAlexander Yermolovich const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 1130a34c753fSRafael Auler 11319f3f9d19SAlexander Yermolovich // We are duplicating abbrev sections, to handle the case where for one CU we 11329f3f9d19SAlexander Yermolovich // modify it, but for another we don't. 11339f3f9d19SAlexander Yermolovich auto UnitDataPtr = std::make_unique<AbbrevData>(); 11349f3f9d19SAlexander Yermolovich AbbrevData &UnitData = *UnitDataPtr.get(); 11359f3f9d19SAlexander Yermolovich UnitData.Buffer = std::make_unique<DebugBufferVector>(); 11369f3f9d19SAlexander Yermolovich UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 1137bd1ebe9dSAlexander Yermolovich 1138a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 1139a34c753fSRafael Auler 11409f3f9d19SAlexander Yermolovich // Returns true if AbbrevData is re-used, false otherwise. 11419f3f9d19SAlexander Yermolovich auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 11429f3f9d19SAlexander Yermolovich llvm::SHA1 Hasher; 11439f3f9d19SAlexander Yermolovich Hasher.update(AbbrevData); 1144330268baSArgyrios Kyrtzidis std::array<uint8_t, 20> Hash = Hasher.final(); 1145330268baSArgyrios Kyrtzidis StringRef Key((const char *)Hash.data(), Hash.size()); 11469f3f9d19SAlexander Yermolovich auto Iter = AbbrevDataCache.find(Key); 11479f3f9d19SAlexander Yermolovich if (Iter != AbbrevDataCache.end()) { 11489f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = Iter->second.get(); 11499f3f9d19SAlexander Yermolovich return true; 11509f3f9d19SAlexander Yermolovich } 11519f3f9d19SAlexander Yermolovich AbbrevDataCache[Key] = std::move(UnitDataPtr); 11529f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = &UnitData; 11539f3f9d19SAlexander Yermolovich return false; 11549f3f9d19SAlexander Yermolovich }; 1155a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 1156a34c753fSRafael Auler // contents. 1157bd1ebe9dSAlexander Yermolovich if (UnitPatches.empty() && AbbrevEntries.empty()) { 1158a34c753fSRafael Auler StringRef AbbrevSectionContents = 1159a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 1160a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 1161a34c753fSRafael Auler StringRef AbbrevContents; 1162a34c753fSRafael Auler 1163a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 1164a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 1165a34c753fSRafael Auler // Handle DWP section contribution. 1166a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 1167a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 1168a34c753fSRafael Auler if (!DWOEntry) 1169a34c753fSRafael Auler return; 1170a34c753fSRafael Auler 1171a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 1172a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 1173a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 1174a34c753fSRafael Auler DWOContrubution->Length); 117545f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 1176a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 117745f94abcSMaksim Panchenko 117845f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 117945f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 118045f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 118145f94abcSMaksim Panchenko // the set boundaries. 118245f94abcSMaksim Panchenko // 118345f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 118445f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 118545f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 1186*a0c7ca8aSKazu Hirata for (const std::pair<const uint64_t, DWARFAbbreviationDeclarationSet> 1187*a0c7ca8aSKazu Hirata &P : *Unit.getContext().getDebugAbbrev()) 118845f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 11891c2f4bbeSAlexander Yermolovich sort(AbbrevSetOffsets); 119045f94abcSMaksim Panchenko } 11911c2f4bbeSAlexander Yermolovich auto It = upper_bound(AbbrevSetOffsets, StartOffset); 119245f94abcSMaksim Panchenko const uint64_t EndOffset = 119345f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 1194a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 119545f94abcSMaksim Panchenko } else { 119645f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 119745f94abcSMaksim Panchenko // abbreviations for this unit only. 119845f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 1199a34c753fSRafael Auler } 1200a34c753fSRafael Auler 12019f3f9d19SAlexander Yermolovich if (!hashAndAddAbbrev(AbbrevContents)) { 1202a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 1203a34c753fSRafael Auler OS << AbbrevContents; 12049f3f9d19SAlexander Yermolovich } 1205a34c753fSRafael Auler return; 1206a34c753fSRafael Auler } 1207a34c753fSRafael Auler 1208a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 1209a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 1210a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 1211a34c753fSRafael Auler 1212a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 1213a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 1214a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 1215a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 1216a34c753fSRafael Auler Abbrev.attributes()) { 1217a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 1218a34c753fSRafael Auler bool Patched = false; 1219a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 1220a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 1221a34c753fSRafael Auler ++I) { 1222a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 1223a34c753fSRafael Auler continue; 1224a34c753fSRafael Auler 1225a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 1226a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 1227a34c753fSRafael Auler Patched = true; 1228a34c753fSRafael Auler break; 1229a34c753fSRafael Auler } 1230a34c753fSRafael Auler if (Patched) 1231a34c753fSRafael Auler continue; 1232a34c753fSRafael Auler } 1233a34c753fSRafael Auler 1234a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 1235a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 1236a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 1237a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 1238a34c753fSRafael Auler } 1239bd1ebe9dSAlexander Yermolovich const auto Entries = AbbrevEntries.find(&Abbrev); 1240bd1ebe9dSAlexander Yermolovich // Adding new Abbrevs for inserted entries. 1241bd1ebe9dSAlexander Yermolovich if (Entries != AbbrevEntries.end()) { 1242bd1ebe9dSAlexander Yermolovich for (const AbbrevEntry &Entry : Entries->second) { 1243bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Attr, OS); 1244bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Form, OS); 1245bd1ebe9dSAlexander Yermolovich } 1246bd1ebe9dSAlexander Yermolovich } 1247a34c753fSRafael Auler encodeULEB128(0, OS); 1248a34c753fSRafael Auler encodeULEB128(0, OS); 1249a34c753fSRafael Auler } 1250a34c753fSRafael Auler encodeULEB128(0, OS); 12519f3f9d19SAlexander Yermolovich 12529f3f9d19SAlexander Yermolovich hashAndAddAbbrev(OS.str()); 1253a34c753fSRafael Auler } 1254a34c753fSRafael Auler 1255a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 12569f3f9d19SAlexander Yermolovich // Used to create determinism for writing out abbrevs. 12579f3f9d19SAlexander Yermolovich std::vector<AbbrevData *> Abbrevs; 125845f94abcSMaksim Panchenko if (DWOId) { 125945f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 126045f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 126145f94abcSMaksim Panchenko // set with the CU. 12621417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 12631417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 126445f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 12651417f607SAlexander Yermolovich if (!IsDWP) { 126645f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 126745f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 126845f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 126945f94abcSMaksim Panchenko "Unable to update debug info.\n"; 127045f94abcSMaksim Panchenko exit(1); 127145f94abcSMaksim Panchenko } 127245f94abcSMaksim Panchenko } 127345f94abcSMaksim Panchenko } 127445f94abcSMaksim Panchenko 12759f3f9d19SAlexander Yermolovich DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 127645f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 127745f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 12789f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 12799f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 12809f3f9d19SAlexander Yermolovich } else { 12819f3f9d19SAlexander Yermolovich Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 12829f3f9d19SAlexander Yermolovich std::unordered_set<AbbrevData *> ProcessedAbbrevs; 12839f3f9d19SAlexander Yermolovich // Add abbreviations from compile and type non-DWO units. 12849f3f9d19SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 12859f3f9d19SAlexander Yermolovich addUnitAbbreviations(*Unit); 12869f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 12879f3f9d19SAlexander Yermolovich if (!ProcessedAbbrevs.insert(Abbrev).second) 12889f3f9d19SAlexander Yermolovich continue; 12899f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 12909f3f9d19SAlexander Yermolovich } 129145f94abcSMaksim Panchenko } 129245f94abcSMaksim Panchenko 1293a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 1294a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 1295a34c753fSRafael Auler uint64_t Size = 0; 12969f3f9d19SAlexander Yermolovich for (const AbbrevData *UnitData : Abbrevs) 12979f3f9d19SAlexander Yermolovich Size += UnitData->Buffer->size(); 12989f3f9d19SAlexander Yermolovich 1299a34c753fSRafael Auler ReturnBuffer.reserve(Size); 1300a34c753fSRafael Auler 1301a34c753fSRafael Auler uint64_t Pos = 0; 13029f3f9d19SAlexander Yermolovich for (AbbrevData *UnitData : Abbrevs) { 13039f3f9d19SAlexander Yermolovich ReturnBuffer.append(*UnitData->Buffer); 13049f3f9d19SAlexander Yermolovich UnitData->Offset = Pos; 13059f3f9d19SAlexander Yermolovich Pos += UnitData->Buffer->size(); 1306a34c753fSRafael Auler 13079f3f9d19SAlexander Yermolovich UnitData->Buffer.reset(); 13089f3f9d19SAlexander Yermolovich UnitData->Stream.reset(); 1309a34c753fSRafael Auler } 1310a34c753fSRafael Auler 1311a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 1312a34c753fSRafael Auler } 1313a34c753fSRafael Auler 1314a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 1315a34c753fSRafael Auler MCDwarfLineTableParams Params, 1316a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 1317a34c753fSRafael Auler int PointerSize) { 1318a34c753fSRafael Auler // emit the sequence to set the address 1319a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 1320a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 1321a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 1322a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 1323a34c753fSRafael Auler 1324a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 1325a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 1326a34c753fSRafael Auler } 1327a34c753fSRafael Auler 1328a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 1329a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 1330a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 1331a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 1332a34c753fSRafael Auler if (InputSequences.empty()) 1333a34c753fSRafael Auler return; 1334a34c753fSRafael Auler 1335a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 1336a34c753fSRafael Auler unsigned FileNum = 1; 1337a34c753fSRafael Auler unsigned LastLine = 1; 1338a34c753fSRafael Auler unsigned Column = 0; 1339a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1340a34c753fSRafael Auler unsigned Isa = 0; 1341a34c753fSRafael Auler unsigned Discriminator = 0; 1342a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 1343a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 1344a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1345a34c753fSRafael Auler 1346a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 1347a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1348a34c753fSRafael Auler FileNum = 1; 1349a34c753fSRafael Auler LastLine = 1; 1350a34c753fSRafael Auler Column = 0; 1351a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1352a34c753fSRafael Auler Isa = 0; 1353a34c753fSRafael Auler Discriminator = 0; 1354a34c753fSRafael Auler LastAddress = InvalidAddress; 1355a34c753fSRafael Auler }; 1356a34c753fSRafael Auler 1357a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1358a34c753fSRafael Auler const uint64_t SequenceStart = 1359a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 1360a34c753fSRafael Auler 1361a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 1362a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1363a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 1364a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1365a34c753fSRafael Auler } 1366a34c753fSRafael Auler 1367a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 1368a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 1369a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1370a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1371a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 1372a34c753fSRafael Auler 1373a34c753fSRafael Auler if (FileNum != Row.File) { 1374a34c753fSRafael Auler FileNum = Row.File; 1375a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1376a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1377a34c753fSRafael Auler } 1378a34c753fSRafael Auler if (Column != Row.Column) { 1379a34c753fSRafael Auler Column = Row.Column; 1380a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1381a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1382a34c753fSRafael Auler } 1383a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 1384a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1385a34c753fSRafael Auler Discriminator = Row.Discriminator; 1386a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1387a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1388a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1389a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1390a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1391a34c753fSRafael Auler } 1392a34c753fSRafael Auler if (Isa != Row.Isa) { 1393a34c753fSRafael Auler Isa = Row.Isa; 1394a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1395a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1396a34c753fSRafael Auler } 1397a34c753fSRafael Auler if (Row.IsStmt != Flags) { 1398a34c753fSRafael Auler Flags = Row.IsStmt; 1399a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1400a34c753fSRafael Auler } 1401a34c753fSRafael Auler if (Row.BasicBlock) 1402a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1403a34c753fSRafael Auler if (Row.PrologueEnd) 1404a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1405a34c753fSRafael Auler if (Row.EpilogueBegin) 1406a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1407a34c753fSRafael Auler 1408a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 1409a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 1410a34c753fSRafael Auler if (Row.EndSequence) { 1411a34c753fSRafael Auler emitEndOfSequence(Address); 1412a34c753fSRafael Auler } else { 1413a34c753fSRafael Auler if (LastAddress == InvalidAddress) 1414a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1415a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1416a34c753fSRafael Auler else 1417a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1418a34c753fSRafael Auler 1419a34c753fSRafael Auler LastAddress = Address; 1420a34c753fSRafael Auler LastLine = Row.Line; 1421a34c753fSRafael Auler } 1422a34c753fSRafael Auler 1423a34c753fSRafael Auler Discriminator = 0; 1424a34c753fSRafael Auler } 1425a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 1426a34c753fSRafael Auler } 1427a34c753fSRafael Auler 1428a34c753fSRafael Auler // Finish with the end of the sequence. 1429a34c753fSRafael Auler if (LastAddress != InvalidAddress) 1430a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1431a34c753fSRafael Auler } 1432a34c753fSRafael Auler 1433a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 1434a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 1435a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 1436a34c753fSRafael Auler static inline void emitDwarfLineTable( 1437a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 1438a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1439a34c753fSRafael Auler unsigned FileNum = 1; 1440a34c753fSRafael Auler unsigned LastLine = 1; 1441a34c753fSRafael Auler unsigned Column = 0; 1442a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1443a34c753fSRafael Auler unsigned Isa = 0; 1444a34c753fSRafael Auler unsigned Discriminator = 0; 1445a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 1446a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1447a34c753fSRafael Auler 1448a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1449a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1450a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1451a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1452a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1453a34c753fSRafael Auler FileNum = 1; 1454a34c753fSRafael Auler LastLine = 1; 1455a34c753fSRafael Auler Column = 0; 1456a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1457a34c753fSRafael Auler Isa = 0; 1458a34c753fSRafael Auler Discriminator = 0; 1459a34c753fSRafael Auler LastLabel = nullptr; 1460a34c753fSRafael Auler continue; 1461a34c753fSRafael Auler } 1462a34c753fSRafael Auler 1463a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1464a34c753fSRafael Auler 1465a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 1466a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 1467a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1468a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1469a34c753fSRafael Auler } 1470a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 1471a34c753fSRafael Auler Column = LineEntry.getColumn(); 1472a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1473a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1474a34c753fSRafael Auler } 1475a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 1476014cd37fSAlexander Yermolovich MCOS->getContext().getDwarfVersion() >= 2) { 1477a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 1478a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1479a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1480a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1481a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1482a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1483a34c753fSRafael Auler } 1484a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 1485a34c753fSRafael Auler Isa = LineEntry.getIsa(); 1486a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1487a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1488a34c753fSRafael Auler } 1489a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1490a34c753fSRafael Auler Flags = LineEntry.getFlags(); 1491a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1492a34c753fSRafael Auler } 1493a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1494a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1495a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1496a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1497a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1498a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1499a34c753fSRafael Auler 1500a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 1501a34c753fSRafael Auler 1502a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 1503a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 1504a34c753fSRafael Auler // Label and the current Label. 1505a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1506a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1507a34c753fSRafael Auler Discriminator = 0; 1508a34c753fSRafael Auler LastLine = LineEntry.getLine(); 1509a34c753fSRafael Auler LastLabel = Label; 1510a34c753fSRafael Auler } 1511a34c753fSRafael Auler 1512a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 1513a34c753fSRafael Auler } 1514a34c753fSRafael Auler 1515a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1516b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 1517b73c87bcSMaksim Panchenko BinaryContext &BC) const { 1518a34c753fSRafael Auler if (!RawData.empty()) { 1519a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 1520a34c753fSRafael Auler InputSequences.empty() && 1521a34c753fSRafael Auler "cannot combine raw data with new line entries"); 1522a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 1523a34c753fSRafael Auler MCOS->emitBytes(RawData); 1524a34c753fSRafael Auler 1525b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 1526b73c87bcSMaksim Panchenko // 1527b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1528b73c87bcSMaksim Panchenko // without relocations. 1529b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 1530b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1531b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1532b73c87bcSMaksim Panchenko 1533a34c753fSRafael Auler return; 1534a34c753fSRafael Auler } 1535a34c753fSRafael Auler 1536a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1537a34c753fSRafael Auler 1538a34c753fSRafael Auler // Put out the line tables. 1539a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1540a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1541a34c753fSRafael Auler 1542a34c753fSRafael Auler // Emit line tables for the original code. 1543a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1544a34c753fSRafael Auler 1545a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 1546a34c753fSRafael Auler // of this section (that was used in a previous expression). 1547a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 1548a34c753fSRafael Auler } 1549a34c753fSRafael Auler 1550014cd37fSAlexander Yermolovich // Helper function to parse .debug_line_str, and populate one we are using. 1551014cd37fSAlexander Yermolovich // For functions that we do not modify we output them as raw data. 1552014cd37fSAlexander Yermolovich // Re-constructing .debug_line_str so that offsets are correct for those 1553014cd37fSAlexander Yermolovich // debut line tables. 1554014cd37fSAlexander Yermolovich // Bonus is that when we output a final binary we can re-use .debug_line_str 1555014cd37fSAlexander Yermolovich // section. So we don't have to do the SHF_ALLOC trick we did with 1556014cd37fSAlexander Yermolovich // .debug_line. 1557014cd37fSAlexander Yermolovich static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection, 1558014cd37fSAlexander Yermolovich MCDwarfLineStr &LineStr, 1559014cd37fSAlexander Yermolovich BinaryContext &BC, 1560014cd37fSAlexander Yermolovich MCStreamer &Streamer) { 1561014cd37fSAlexander Yermolovich DataExtractor StrData(LineStrSection.getContents(), 1562014cd37fSAlexander Yermolovich BC.DwCtx->isLittleEndian(), 0); 1563014cd37fSAlexander Yermolovich uint64_t Offset = 0; 1564014cd37fSAlexander Yermolovich while (StrData.isValidOffset(Offset)) { 1565014cd37fSAlexander Yermolovich Error Err = Error::success(); 1566014cd37fSAlexander Yermolovich const char *CStr = StrData.getCStr(&Offset, &Err); 1567014cd37fSAlexander Yermolovich if (Err) { 1568014cd37fSAlexander Yermolovich errs() << "BOLT-ERROR: could not extract string from .debug_line_str"; 1569014cd37fSAlexander Yermolovich continue; 1570014cd37fSAlexander Yermolovich } 1571014cd37fSAlexander Yermolovich LineStr.emitRef(&Streamer, CStr); 1572014cd37fSAlexander Yermolovich } 1573014cd37fSAlexander Yermolovich } 1574014cd37fSAlexander Yermolovich 1575a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1576a34c753fSRafael Auler MCAssembler &Assembler = 1577a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1578a34c753fSRafael Auler 1579a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1580a34c753fSRafael Auler 1581a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 1582a34c753fSRafael Auler 1583a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 1584a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 1585a34c753fSRafael Auler if (LineTables.empty()) 1586a34c753fSRafael Auler return; 1587a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 1588a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 1589014cd37fSAlexander Yermolovich ErrorOr<BinarySection &> LineStrSection = 1590014cd37fSAlexander Yermolovich BC.getUniqueSectionByName(".debug_line_str"); 1591014cd37fSAlexander Yermolovich // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower 1592014cd37fSAlexander Yermolovich // .debug_line 1593014cd37fSAlexander Yermolovich if (LineStrSection) { 159453113515SFangrui Song LineStr.emplace(*BC.Ctx); 1595014cd37fSAlexander Yermolovich parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC, Streamer); 1596014cd37fSAlexander Yermolovich } 1597a34c753fSRafael Auler 1598a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 1599adf4142fSFangrui Song Streamer.switchSection(BC.MOFI->getDwarfLineSection()); 1600a34c753fSRafael Auler 1601014cd37fSAlexander Yermolovich const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion(); 1602a34c753fSRafael Auler // Handle the rest of the Compile Units. 1603a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 1604014cd37fSAlexander Yermolovich Streamer.getContext().setDwarfVersion( 1605014cd37fSAlexander Yermolovich CUIDTablePair.second.getDwarfVersion()); 1606b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1607a34c753fSRafael Auler } 1608014cd37fSAlexander Yermolovich 1609014cd37fSAlexander Yermolovich // Resetting DWARF version for rest of the flow. 1610014cd37fSAlexander Yermolovich BC.Ctx->setDwarfVersion(DwarfVersion); 1611014cd37fSAlexander Yermolovich 1612014cd37fSAlexander Yermolovich // Still need to write the section out for the ExecutionEngine, and temp in 1613014cd37fSAlexander Yermolovich // memory object we are constructing. 1614014cd37fSAlexander Yermolovich if (LineStr) { 1615014cd37fSAlexander Yermolovich LineStr->emitSection(&Streamer); 1616014cd37fSAlexander Yermolovich SmallString<0> Data = LineStr->getFinalizedData(); 1617014cd37fSAlexander Yermolovich BC.registerOrUpdateNoteSection(".debug_line_str", copyByteArray(Data.str()), 1618014cd37fSAlexander Yermolovich Data.size()); 1619014cd37fSAlexander Yermolovich } 1620a34c753fSRafael Auler } 1621a34c753fSRafael Auler 1622a34c753fSRafael Auler } // namespace bolt 1623a34c753fSRafael Auler } // namespace llvm 1624