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" 15a34c753fSRafael Auler #include "bolt/Utils/Utils.h" 16290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 17290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 1857f7c7d9Sserge-sans-paille #include "llvm/MC/MCAssembler.h" 19f8c7fb49SAmir Ayupov #include "llvm/MC/MCContext.h" 20a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h" 21a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 22a34c753fSRafael Auler #include "llvm/Support/EndianStream.h" 23a34c753fSRafael Auler #include "llvm/Support/LEB128.h" 249f3f9d19SAlexander Yermolovich #include "llvm/Support/SHA1.h" 25a34c753fSRafael Auler #include <algorithm> 26a34c753fSRafael Auler #include <cassert> 27a34c753fSRafael Auler #include <cstdint> 28a34c753fSRafael Auler #include <limits> 291c2f4bbeSAlexander Yermolovich #include <unordered_map> 30a34c753fSRafael Auler 31a34c753fSRafael Auler #define DEBUG_TYPE "bolt-debug-info" 32a34c753fSRafael Auler 33a34c753fSRafael Auler namespace opts { 34a34c753fSRafael Auler extern llvm::cl::opt<unsigned> Verbosity; 351c2f4bbeSAlexander Yermolovich } // namespace opts 36a34c753fSRafael Auler 37a34c753fSRafael Auler namespace llvm { 38f8c7fb49SAmir Ayupov class MCSymbol; 39f8c7fb49SAmir Ayupov 40a34c753fSRafael Auler namespace bolt { 41a34c753fSRafael Auler 42*bd1ebe9dSAlexander Yermolovich /// Finds attributes FormValue and Offset. 43*bd1ebe9dSAlexander Yermolovich /// 44*bd1ebe9dSAlexander Yermolovich /// \param DIE die to look up in. 45*bd1ebe9dSAlexander Yermolovich /// \param Index the attribute index to extract. 46*bd1ebe9dSAlexander Yermolovich /// \return an optional AttrInfo with DWARFFormValue and Offset. 47*bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> 48*bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE, 49*bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl, 50*bd1ebe9dSAlexander Yermolovich uint32_t Index) { 51*bd1ebe9dSAlexander Yermolovich const DWARFUnit &U = *DIE.getDwarfUnit(); 52*bd1ebe9dSAlexander Yermolovich uint64_t Offset = 53*bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U); 54*bd1ebe9dSAlexander Yermolovich Optional<DWARFFormValue> Value = 55*bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U); 56*bd1ebe9dSAlexander Yermolovich if (!Value) 57*bd1ebe9dSAlexander Yermolovich return None; 58*bd1ebe9dSAlexander Yermolovich // AttributeSpec 59*bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal = 60*bd1ebe9dSAlexander Yermolovich AbbrevDecl->attributes().begin() + Index; 61*bd1ebe9dSAlexander Yermolovich uint32_t ValSize = 0; 62*bd1ebe9dSAlexander Yermolovich Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U); 63*bd1ebe9dSAlexander Yermolovich if (ValSizeOpt) { 64*bd1ebe9dSAlexander Yermolovich ValSize = static_cast<uint32_t>(*ValSizeOpt); 65*bd1ebe9dSAlexander Yermolovich } else { 66*bd1ebe9dSAlexander Yermolovich DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 67*bd1ebe9dSAlexander Yermolovich uint64_t NewOffset = Offset; 68*bd1ebe9dSAlexander Yermolovich DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset, 69*bd1ebe9dSAlexander Yermolovich U.getFormParams()); 70*bd1ebe9dSAlexander Yermolovich // This includes entire size of the entry, which might not be just the 71*bd1ebe9dSAlexander Yermolovich // encoding part. For example for DW_AT_loc it will include expression 72*bd1ebe9dSAlexander Yermolovich // location. 73*bd1ebe9dSAlexander Yermolovich ValSize = NewOffset - Offset; 74*bd1ebe9dSAlexander Yermolovich } 75*bd1ebe9dSAlexander Yermolovich 76*bd1ebe9dSAlexander Yermolovich return AttrInfo{*Value, Offset, ValSize}; 77*bd1ebe9dSAlexander Yermolovich } 78*bd1ebe9dSAlexander Yermolovich 79a34c753fSRafael Auler const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0}; 80a34c753fSRafael Auler 81a34c753fSRafael Auler namespace { 82a34c753fSRafael Auler 831c2f4bbeSAlexander Yermolovich LLVM_ATTRIBUTE_UNUSED 841c2f4bbeSAlexander Yermolovich static void printLE64(const std::string &S) { 851c2f4bbeSAlexander Yermolovich for (uint32_t I = 0, Size = S.size(); I < Size; ++I) { 861c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr(S[I]); 871c2f4bbeSAlexander Yermolovich errs() << Twine::utohexstr((int8_t)S[I]); 881c2f4bbeSAlexander Yermolovich } 891c2f4bbeSAlexander Yermolovich errs() << "\n"; 901c2f4bbeSAlexander Yermolovich } 911c2f4bbeSAlexander Yermolovich 92a34c753fSRafael Auler // Writes address ranges to Writer as pairs of 64-bit (address, size). 93a34c753fSRafael Auler // If RelativeRange is true, assumes the address range to be written must be of 94a34c753fSRafael Auler // the form (begin address, range size), otherwise (begin address, end address). 95a34c753fSRafael Auler // Terminates the list by writing a pair of two zeroes. 96a34c753fSRafael Auler // Returns the number of written bytes. 9740c2e0faSMaksim Panchenko uint64_t writeAddressRanges(raw_svector_ostream &Stream, 98a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges, 99a34c753fSRafael Auler const bool WriteRelativeRanges = false) { 100a34c753fSRafael Auler for (const DebugAddressRange &Range : AddressRanges) { 101a34c753fSRafael Auler support::endian::write(Stream, Range.LowPC, support::little); 102a34c753fSRafael Auler support::endian::write( 103a34c753fSRafael Auler Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC, 104a34c753fSRafael Auler support::little); 105a34c753fSRafael Auler } 106a34c753fSRafael Auler // Finish with 0 entries. 107a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 108a34c753fSRafael Auler support::endian::write(Stream, 0ULL, support::little); 109a34c753fSRafael Auler return AddressRanges.size() * 16 + 16; 110a34c753fSRafael Auler } 111a34c753fSRafael Auler 112a34c753fSRafael Auler } // namespace 113a34c753fSRafael Auler 114a34c753fSRafael Auler DebugRangesSectionWriter::DebugRangesSectionWriter() { 115a34c753fSRafael Auler RangesBuffer = std::make_unique<DebugBufferVector>(); 116a34c753fSRafael Auler RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer); 117a34c753fSRafael Auler 118a34c753fSRafael Auler // Add an empty range as the first entry; 119a34c753fSRafael Auler SectionOffset += 120a34c753fSRafael Auler writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{}); 121a34c753fSRafael Auler } 122a34c753fSRafael Auler 123a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::addRanges( 124a34c753fSRafael Auler DebugAddressRangesVector &&Ranges, 125a34c753fSRafael Auler std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { 126a34c753fSRafael Auler if (Ranges.empty()) 127a34c753fSRafael Auler return getEmptyRangesOffset(); 128a34c753fSRafael Auler 129a34c753fSRafael Auler const auto RI = CachedRanges.find(Ranges); 130a34c753fSRafael Auler if (RI != CachedRanges.end()) 131a34c753fSRafael Auler return RI->second; 132a34c753fSRafael Auler 133a34c753fSRafael Auler const uint64_t EntryOffset = addRanges(Ranges); 134a34c753fSRafael Auler CachedRanges.emplace(std::move(Ranges), EntryOffset); 135a34c753fSRafael Auler 136a34c753fSRafael Auler return EntryOffset; 137a34c753fSRafael Auler } 138a34c753fSRafael Auler 139a34c753fSRafael Auler uint64_t 140a34c753fSRafael Auler DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) { 141a34c753fSRafael Auler if (Ranges.empty()) 142a34c753fSRafael Auler return getEmptyRangesOffset(); 143a34c753fSRafael Auler 144a34c753fSRafael Auler // Reading the SectionOffset and updating it should be atomic to guarantee 145a34c753fSRafael Auler // unique and correct offsets in patches. 146a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 147a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 148a34c753fSRafael Auler SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges); 149a34c753fSRafael Auler 150a34c753fSRafael Auler return EntryOffset; 151a34c753fSRafael Auler } 152a34c753fSRafael Auler 153a34c753fSRafael Auler uint64_t DebugRangesSectionWriter::getSectionOffset() { 154a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(WriterMutex); 155a34c753fSRafael Auler return SectionOffset; 156a34c753fSRafael Auler } 157a34c753fSRafael Auler 158a34c753fSRafael Auler void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset, 159a34c753fSRafael Auler DebugAddressRangesVector &&Ranges) { 160a34c753fSRafael Auler std::lock_guard<std::mutex> Lock(CUAddressRangesMutex); 161a34c753fSRafael Auler CUAddressRanges.emplace(CUOffset, std::move(Ranges)); 162a34c753fSRafael Auler } 163a34c753fSRafael Auler 164a34c753fSRafael Auler void DebugARangesSectionWriter::writeARangesSection( 165612f0f45SAlexander Yermolovich raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const { 166a34c753fSRafael Auler // For reference on the format of the .debug_aranges section, see the DWARF4 167a34c753fSRafael Auler // specification, section 6.1.4 Lookup by Address 168a34c753fSRafael Auler // http://www.dwarfstd.org/doc/DWARF4.pdf 169a34c753fSRafael Auler for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) { 170a34c753fSRafael Auler const uint64_t Offset = CUOffsetAddressRangesPair.first; 171a34c753fSRafael Auler const DebugAddressRangesVector &AddressRanges = 172a34c753fSRafael Auler CUOffsetAddressRangesPair.second; 173a34c753fSRafael Auler 174a34c753fSRafael Auler // Emit header. 175a34c753fSRafael Auler 176a34c753fSRafael Auler // Size of this set: 8 (size of the header) + 4 (padding after header) 177a34c753fSRafael Auler // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra 178a34c753fSRafael Auler // pair of uint64_t's for the terminating, zero-length range. 179a34c753fSRafael Auler // Does not include size field itself. 180a34c753fSRafael Auler uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1); 181a34c753fSRafael Auler 182a34c753fSRafael Auler // Header field #1: set size. 183a34c753fSRafael Auler support::endian::write(RangesStream, Size, support::little); 184a34c753fSRafael Auler 185a34c753fSRafael Auler // Header field #2: version number, 2 as per the specification. 186a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint16_t>(2), 187a34c753fSRafael Auler support::little); 188a34c753fSRafael Auler 1891c2f4bbeSAlexander Yermolovich assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map"); 190a34c753fSRafael Auler // Header field #3: debug info offset of the correspondent compile unit. 191612f0f45SAlexander Yermolovich support::endian::write( 192612f0f45SAlexander Yermolovich RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset), 193a34c753fSRafael Auler support::little); 194a34c753fSRafael Auler 195a34c753fSRafael Auler // Header field #4: address size. 196a34c753fSRafael Auler // 8 since we only write ELF64 binaries for now. 197a34c753fSRafael Auler RangesStream << char(8); 198a34c753fSRafael Auler 199a34c753fSRafael Auler // Header field #5: segment size of target architecture. 200a34c753fSRafael Auler RangesStream << char(0); 201a34c753fSRafael Auler 202a34c753fSRafael Auler // Padding before address table - 4 bytes in the 64-bit-pointer case. 203a34c753fSRafael Auler support::endian::write(RangesStream, static_cast<uint32_t>(0), 204a34c753fSRafael Auler support::little); 205a34c753fSRafael Auler 206a34c753fSRafael Auler writeAddressRanges(RangesStream, AddressRanges, true); 207a34c753fSRafael Auler } 208a34c753fSRafael Auler } 209a34c753fSRafael Auler 210a34c753fSRafael Auler DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; } 211a34c753fSRafael Auler 212a34c753fSRafael Auler void DebugAddrWriter::AddressForDWOCU::dump() { 213a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(), 214a34c753fSRafael Auler indexToAdddessEnd()); 215a34c753fSRafael Auler // Sorting address in increasing order of indices. 216a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 217a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 218a34c753fSRafael Auler return A.first < B.first; 219a34c753fSRafael Auler }); 220a34c753fSRafael Auler for (auto &Pair : SortedMap) 221a34c753fSRafael Auler dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n"; 222a34c753fSRafael Auler } 223a34c753fSRafael Auler uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, 224a34c753fSRafael Auler uint64_t DWOId) { 225e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 226a34c753fSRafael Auler if (!AddressMaps.count(DWOId)) 227a34c753fSRafael Auler AddressMaps[DWOId] = AddressForDWOCU(); 228a34c753fSRafael Auler 229a34c753fSRafael Auler AddressForDWOCU &Map = AddressMaps[DWOId]; 230a34c753fSRafael Auler auto Entry = Map.find(Address); 231a34c753fSRafael Auler if (Entry == Map.end()) { 232a34c753fSRafael Auler auto Index = Map.getNextIndex(); 233a34c753fSRafael Auler Entry = Map.insert(Address, Index).first; 234a34c753fSRafael Auler } 235a34c753fSRafael Auler return Entry->second; 236a34c753fSRafael Auler } 237a34c753fSRafael Auler 238a34c753fSRafael Auler // Case1) Address is not in map insert in to AddresToIndex and IndexToAddres 239a34c753fSRafael Auler // Case2) Address is in the map but Index is higher or equal. Need to update 240a34c753fSRafael Auler // IndexToAddrss. Case3) Address is in the map but Index is lower. Need to 241a34c753fSRafael Auler // update AddressToIndex and IndexToAddress 242a34c753fSRafael Auler void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, 243a34c753fSRafael Auler uint64_t DWOId) { 244e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 245a34c753fSRafael Auler AddressForDWOCU &Map = AddressMaps[DWOId]; 246a34c753fSRafael Auler auto Entry = Map.find(Address); 247a34c753fSRafael Auler if (Entry != Map.end()) { 248a34c753fSRafael Auler if (Entry->second > Index) 249a34c753fSRafael Auler Map.updateAddressToIndex(Address, Index); 250a34c753fSRafael Auler Map.updateIndexToAddrss(Address, Index); 2513652483cSRafael Auler } else { 252a34c753fSRafael Auler Map.insert(Address, Index); 253a34c753fSRafael Auler } 2543652483cSRafael Auler } 255a34c753fSRafael Auler 256a34c753fSRafael Auler AddressSectionBuffer DebugAddrWriter::finalize() { 257a34c753fSRafael Auler // Need to layout all sections within .debug_addr 258a34c753fSRafael Auler // Within each section sort Address by index. 259a34c753fSRafael Auler AddressSectionBuffer Buffer; 260a34c753fSRafael Auler raw_svector_ostream AddressStream(Buffer); 261a34c753fSRafael Auler for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) { 262a34c753fSRafael Auler Optional<uint64_t> DWOId = CU->getDWOId(); 263a34c753fSRafael Auler // Handling the case wehre debug information is a mix of Debug fission and 264a34c753fSRafael Auler // monolitic. 265a34c753fSRafael Auler if (!DWOId) 266a34c753fSRafael Auler continue; 267a34c753fSRafael Auler auto AM = AddressMaps.find(*DWOId); 268a34c753fSRafael Auler // Adding to map even if it did not contribute to .debug_addr. 269a34c753fSRafael Auler // The Skeleton CU will still have DW_AT_GNU_addr_base. 270a34c753fSRafael Auler DWOIdToOffsetMap[*DWOId] = Buffer.size(); 271a34c753fSRafael Auler // If does not exist this CUs DWO section didn't contribute to .debug_addr. 272a34c753fSRafael Auler if (AM == AddressMaps.end()) 273a34c753fSRafael Auler continue; 274a34c753fSRafael Auler std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), 275a34c753fSRafael Auler AM->second.indexToAdddessEnd()); 276a34c753fSRafael Auler // Sorting address in increasing order of indices. 277a34c753fSRafael Auler std::sort(SortedMap.begin(), SortedMap.end(), 278a34c753fSRafael Auler [](const IndexAddressPair &A, const IndexAddressPair &B) { 279a34c753fSRafael Auler return A.first < B.first; 280a34c753fSRafael Auler }); 281a34c753fSRafael Auler 282a34c753fSRafael Auler uint8_t AddrSize = CU->getAddressByteSize(); 283a34c753fSRafael Auler uint32_t Counter = 0; 284a34c753fSRafael Auler auto WriteAddress = [&](uint64_t Address) -> void { 285a34c753fSRafael Auler ++Counter; 286a34c753fSRafael Auler switch (AddrSize) { 287a34c753fSRafael Auler default: 288a34c753fSRafael Auler assert(false && "Address Size is invalid."); 289a34c753fSRafael Auler break; 290a34c753fSRafael Auler case 4: 291a34c753fSRafael Auler support::endian::write(AddressStream, static_cast<uint32_t>(Address), 292a34c753fSRafael Auler support::little); 293a34c753fSRafael Auler break; 294a34c753fSRafael Auler case 8: 295a34c753fSRafael Auler support::endian::write(AddressStream, Address, support::little); 296a34c753fSRafael Auler break; 297a34c753fSRafael Auler } 298a34c753fSRafael Auler }; 299a34c753fSRafael Auler 300a34c753fSRafael Auler for (const IndexAddressPair &Val : SortedMap) { 301a34c753fSRafael Auler while (Val.first > Counter) 302a34c753fSRafael Auler WriteAddress(0); 303a34c753fSRafael Auler WriteAddress(Val.second); 304a34c753fSRafael Auler } 305a34c753fSRafael Auler } 306a34c753fSRafael Auler 307a34c753fSRafael Auler return Buffer; 308a34c753fSRafael Auler } 309a34c753fSRafael Auler 310a34c753fSRafael Auler uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) { 311a34c753fSRafael Auler auto Iter = DWOIdToOffsetMap.find(DWOId); 312a34c753fSRafael Auler assert(Iter != DWOIdToOffsetMap.end() && 313a34c753fSRafael Auler "Offset in to.debug_addr was not found for DWO ID."); 314a34c753fSRafael Auler return Iter->second; 315a34c753fSRafael Auler } 316a34c753fSRafael Auler 317a34c753fSRafael Auler DebugLocWriter::DebugLocWriter(BinaryContext *BC) { 318a34c753fSRafael Auler LocBuffer = std::make_unique<DebugBufferVector>(); 319a34c753fSRafael Auler LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer); 320a34c753fSRafael Auler } 321a34c753fSRafael Auler 322a34c753fSRafael Auler void DebugLocWriter::addList(uint64_t AttrOffset, 323a34c753fSRafael Auler DebugLocationsVector &&LocList) { 324a34c753fSRafael Auler if (LocList.empty()) { 325a34c753fSRafael Auler EmptyAttrLists.push_back(AttrOffset); 326a34c753fSRafael Auler return; 327a34c753fSRafael Auler } 328a34c753fSRafael Auler // Since there is a separate DebugLocWriter for each thread, 329a34c753fSRafael Auler // we don't need a lock to read the SectionOffset and update it. 330a34c753fSRafael Auler const uint32_t EntryOffset = SectionOffset; 331a34c753fSRafael Auler 332a34c753fSRafael Auler for (const DebugLocationEntry &Entry : LocList) { 333a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC), 334a34c753fSRafael Auler support::little); 335a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC), 336a34c753fSRafael Auler support::little); 337a34c753fSRafael Auler support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()), 338a34c753fSRafael Auler support::little); 339a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 340a34c753fSRafael Auler Entry.Expr.size()); 341a34c753fSRafael Auler SectionOffset += 2 * 8 + 2 + Entry.Expr.size(); 342a34c753fSRafael Auler } 343a34c753fSRafael Auler LocStream->write_zeros(16); 344a34c753fSRafael Auler SectionOffset += 16; 345a34c753fSRafael Auler LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset}); 346a34c753fSRafael Auler } 347a34c753fSRafael Auler 348a34c753fSRafael Auler void DebugLoclistWriter::addList(uint64_t AttrOffset, 349a34c753fSRafael Auler DebugLocationsVector &&LocList) { 350a34c753fSRafael Auler Patches.push_back({AttrOffset, std::move(LocList)}); 351a34c753fSRafael Auler } 352a34c753fSRafael Auler 353a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() { 354a34c753fSRafael Auler return std::move(LocBuffer); 355a34c753fSRafael Auler } 356a34c753fSRafael Auler 357a34c753fSRafael Auler // DWARF 4: 2.6.2 358a34c753fSRafael Auler void DebugLocWriter::finalize(uint64_t SectionOffset, 359a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 360a34c753fSRafael Auler for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) { 361a34c753fSRafael Auler uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset; 362a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset, 363a34c753fSRafael Auler Offset); 364a34c753fSRafael Auler } 365a34c753fSRafael Auler 366a34c753fSRafael Auler for (uint64_t DebugInfoAttrOffset : EmptyAttrLists) 367a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset, 368a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 369a34c753fSRafael Auler } 370a34c753fSRafael Auler 371a34c753fSRafael Auler void DebugLoclistWriter::finalize(uint64_t SectionOffset, 372a34c753fSRafael Auler SimpleBinaryPatcher &DebugInfoPatcher) { 373a34c753fSRafael Auler for (LocPatch &Patch : Patches) { 374a34c753fSRafael Auler if (Patch.LocList.empty()) { 375a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, 376a34c753fSRafael Auler DebugLocWriter::EmptyListOffset); 377a34c753fSRafael Auler continue; 378a34c753fSRafael Auler } 379a34c753fSRafael Auler const uint32_t EntryOffset = LocBuffer->size(); 380a34c753fSRafael Auler for (const DebugLocationEntry &Entry : Patch.LocList) { 381a34c753fSRafael Auler support::endian::write(*LocStream, 382a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_startx_length), 383a34c753fSRafael Auler support::little); 384a34c753fSRafael Auler uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId); 385a34c753fSRafael Auler encodeULEB128(Index, *LocStream); 386a34c753fSRafael Auler 387a34c753fSRafael Auler // TODO: Support DWARF5 388a34c753fSRafael Auler support::endian::write(*LocStream, 389a34c753fSRafael Auler static_cast<uint32_t>(Entry.HighPC - Entry.LowPC), 390a34c753fSRafael Auler support::little); 391a34c753fSRafael Auler support::endian::write(*LocStream, 392a34c753fSRafael Auler static_cast<uint16_t>(Entry.Expr.size()), 393a34c753fSRafael Auler support::little); 394a34c753fSRafael Auler *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()), 395a34c753fSRafael Auler Entry.Expr.size()); 396a34c753fSRafael Auler } 397a34c753fSRafael Auler support::endian::write(*LocStream, 398a34c753fSRafael Auler static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), 399a34c753fSRafael Auler support::little); 400a34c753fSRafael Auler DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset); 401a34c753fSRafael Auler clearList(Patch.LocList); 402a34c753fSRafael Auler } 403a34c753fSRafael Auler clearList(Patches); 404a34c753fSRafael Auler } 405a34c753fSRafael Auler 406a34c753fSRafael Auler DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; 407a34c753fSRafael Auler 4081c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { 4091c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4101c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 411ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); 412a34c753fSRafael Auler } 413a34c753fSRafael Auler 4141c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { 4151c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4161c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 4171c2f4bbeSAlexander Yermolovich auto RetVal = DestinationLabels.insert(Offset); 4181c2f4bbeSAlexander Yermolovich if (!RetVal.second) 4191c2f4bbeSAlexander Yermolovich return; 4201c2f4bbeSAlexander Yermolovich 421ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); 422a34c753fSRafael Auler } 423a34c753fSRafael Auler 424*bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 425*bd1ebe9dSAlexander Yermolovich std::string LE64(ByteSize, 0); 426*bd1ebe9dSAlexander Yermolovich for (size_t I = 0; I < ByteSize; ++I) { 427*bd1ebe9dSAlexander Yermolovich LE64[I] = NewValue & 0xff; 428*bd1ebe9dSAlexander Yermolovich NewValue >>= 8; 429*bd1ebe9dSAlexander Yermolovich } 430*bd1ebe9dSAlexander Yermolovich return LE64; 431*bd1ebe9dSAlexander Yermolovich } 432*bd1ebe9dSAlexander Yermolovich 433*bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 434*bd1ebe9dSAlexander Yermolovich uint32_t Value) { 435*bd1ebe9dSAlexander Yermolovich std::string StrValue = encodeLE(4, Value); 436*bd1ebe9dSAlexander Yermolovich insertNewEntry(DIE, std::move(StrValue)); 437*bd1ebe9dSAlexander Yermolovich } 438*bd1ebe9dSAlexander Yermolovich 439*bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 440*bd1ebe9dSAlexander Yermolovich std::string &&Value) { 441*bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl = 442*bd1ebe9dSAlexander Yermolovich DIE.getAbbreviationDeclarationPtr(); 443*bd1ebe9dSAlexander Yermolovich 444*bd1ebe9dSAlexander Yermolovich // In case this DIE has no attributes. 445*bd1ebe9dSAlexander Yermolovich uint32_t Offset = DIE.getOffset() + 1; 446*bd1ebe9dSAlexander Yermolovich size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 447*bd1ebe9dSAlexander Yermolovich if (NumOfAttributes) { 448*bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> Val = 449*bd1ebe9dSAlexander Yermolovich findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 450*bd1ebe9dSAlexander Yermolovich assert(Val && "Invalid Value."); 451*bd1ebe9dSAlexander Yermolovich 452*bd1ebe9dSAlexander Yermolovich Offset = Val->Offset + Val->Size - DWPUnitOffset; 453*bd1ebe9dSAlexander Yermolovich } 454*bd1ebe9dSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 455*bd1ebe9dSAlexander Yermolovich DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 456*bd1ebe9dSAlexander Yermolovich } 457*bd1ebe9dSAlexander Yermolovich 4581c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, 4591c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset, 4601c2f4bbeSAlexander Yermolovich uint32_t OldValueSize, 4611c2f4bbeSAlexander Yermolovich dwarf::Form Form) { 4621c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4631c2f4bbeSAlexander Yermolovich DestinationOffset -= DWPUnitOffset; 4641c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 465ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back( 466ea6c8b01SAlexander Yermolovich new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); 4671c2f4bbeSAlexander Yermolovich } 4681c2f4bbeSAlexander Yermolovich 4691c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, 4701c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 4711c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4721c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 4731c2f4bbeSAlexander Yermolovich DebugPatches.emplace_back( 474ea6c8b01SAlexander Yermolovich new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); 4751c2f4bbeSAlexander Yermolovich } 4761c2f4bbeSAlexander Yermolovich 4771c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 4781c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4791c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 480ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); 4811c2f4bbeSAlexander Yermolovich } 4821c2f4bbeSAlexander Yermolovich 4831c2f4bbeSAlexander Yermolovich void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 4841c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 4851c2f4bbeSAlexander Yermolovich Offset -= DWPUnitOffset; 4861c2f4bbeSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 4871c2f4bbeSAlexander Yermolovich if (OldValueSize == 4) 488ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); 4891c2f4bbeSAlexander Yermolovich else 490ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 4911c2f4bbeSAlexander Yermolovich } 4921c2f4bbeSAlexander Yermolovich 4931c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 4941c2f4bbeSAlexander Yermolovich std::string &&NewValue, 4951c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 4961c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(NewValue)); 4971c2f4bbeSAlexander Yermolovich } 4981c2f4bbeSAlexander Yermolovich 4991c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 5001c2f4bbeSAlexander Yermolovich auto Str = std::string(1, Value); 5011c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Str)); 5021c2f4bbeSAlexander Yermolovich } 5031c2f4bbeSAlexander Yermolovich 5041c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 5051c2f4bbeSAlexander Yermolovich size_t ByteSize) { 5061c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 5071c2f4bbeSAlexander Yermolovich } 5081c2f4bbeSAlexander Yermolovich 5091c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 5101c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 511a34c753fSRafael Auler std::string Buff; 512a34c753fSRafael Auler raw_string_ostream OS(Buff); 5131c2f4bbeSAlexander Yermolovich encodeULEB128(Value, OS, OldValueSize); 514a34c753fSRafael Auler 5151c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Buff)); 516a34c753fSRafael Auler } 517a34c753fSRafael Auler 5181c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 519a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 520a34c753fSRafael Auler } 521a34c753fSRafael Auler 5221c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 5231c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 524a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 525a34c753fSRafael Auler } 526a34c753fSRafael Auler 5271c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 5281c2f4bbeSAlexander Yermolovich std::string BinaryContentsStr = std::string(BinaryContents); 529a34c753fSRafael Auler for (const auto &Patch : Patches) { 5301c2f4bbeSAlexander Yermolovich uint32_t Offset = Patch.first; 531a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 532a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 533a34c753fSRafael Auler "Applied patch runs over binary size."); 534a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 5351c2f4bbeSAlexander Yermolovich BinaryContentsStr[Offset + I] = ByteSequence[I]; 536a34c753fSRafael Auler } 537a34c753fSRafael Auler } 5381c2f4bbeSAlexander Yermolovich return BinaryContentsStr; 5391c2f4bbeSAlexander Yermolovich } 5401c2f4bbeSAlexander Yermolovich 541612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 542612f0f45SAlexander Yermolovich bool IsDWOContext) { 543612f0f45SAlexander Yermolovich CUOffsetMap CUMap; 544ea6c8b01SAlexander Yermolovich std::sort(DebugPatches.begin(), DebugPatches.end(), 545ea6c8b01SAlexander Yermolovich [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) { 546*bd1ebe9dSAlexander Yermolovich if (V1.get()->Offset == V2.get()->Offset) { 547*bd1ebe9dSAlexander Yermolovich if (V1->Kind == DebugPatchKind::NewDebugEntry && 548*bd1ebe9dSAlexander Yermolovich V2->Kind == DebugPatchKind::NewDebugEntry) 549*bd1ebe9dSAlexander Yermolovich return reinterpret_cast<const NewDebugEntry *>(V1.get()) 550*bd1ebe9dSAlexander Yermolovich ->CurrentOrder < 551*bd1ebe9dSAlexander Yermolovich reinterpret_cast<const NewDebugEntry *>(V2.get()) 552*bd1ebe9dSAlexander Yermolovich ->CurrentOrder; 553*bd1ebe9dSAlexander Yermolovich 554*bd1ebe9dSAlexander Yermolovich // This is a case where we are modifying first entry of next 555*bd1ebe9dSAlexander Yermolovich // DIE, and adding a new one. 556*bd1ebe9dSAlexander Yermolovich return V1->Kind == DebugPatchKind::NewDebugEntry; 557*bd1ebe9dSAlexander Yermolovich } 5581c2f4bbeSAlexander Yermolovich return V1.get()->Offset < V2.get()->Offset; 5591c2f4bbeSAlexander Yermolovich }); 5601c2f4bbeSAlexander Yermolovich 561612f0f45SAlexander Yermolovich DWARFUnitVector::compile_unit_range CompileUnits = 562612f0f45SAlexander Yermolovich IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 563612f0f45SAlexander Yermolovich 564612f0f45SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 565612f0f45SAlexander Yermolovich CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 566612f0f45SAlexander Yermolovich static_cast<uint32_t>(CU->getLength())}; 567612f0f45SAlexander Yermolovich 5681c2f4bbeSAlexander Yermolovich // Calculating changes in .debug_info size from Patches to build a map of old 5691c2f4bbeSAlexander Yermolovich // to updated reference destination offsets. 570612f0f45SAlexander Yermolovich uint32_t PreviousOffset = 0; 571612f0f45SAlexander Yermolovich int32_t PreviousChangeInSize = 0; 572ea6c8b01SAlexander Yermolovich for (UniquePatchPtrType &PatchBase : DebugPatches) { 5731c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 5741c2f4bbeSAlexander Yermolovich switch (P->Kind) { 5751c2f4bbeSAlexander Yermolovich default: 5761c2f4bbeSAlexander Yermolovich continue; 5771c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 578612f0f45SAlexander Yermolovich PreviousChangeInSize -= 4; 5791c2f4bbeSAlexander Yermolovich break; 5801c2f4bbeSAlexander Yermolovich } 5811c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 5821c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *DPV = 5831c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 5841c2f4bbeSAlexander Yermolovich std::string Temp; 5851c2f4bbeSAlexander Yermolovich raw_string_ostream OS(Temp); 5861c2f4bbeSAlexander Yermolovich encodeULEB128(DPV->Value, OS); 587612f0f45SAlexander Yermolovich PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 5881c2f4bbeSAlexander Yermolovich break; 5891c2f4bbeSAlexander Yermolovich } 5901c2f4bbeSAlexander Yermolovich case DebugPatchKind::DestinationReferenceLabel: { 5911c2f4bbeSAlexander Yermolovich DestinationReferenceLabel *DRL = 5921c2f4bbeSAlexander Yermolovich reinterpret_cast<DestinationReferenceLabel *>(P); 593612f0f45SAlexander Yermolovich OldToNewOffset[DRL->Offset] = 594612f0f45SAlexander Yermolovich DRL->Offset + ChangeInSize + PreviousChangeInSize; 5951c2f4bbeSAlexander Yermolovich break; 5961c2f4bbeSAlexander Yermolovich } 5971c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 5981c2f4bbeSAlexander Yermolovich // This doesn't look to be a common case, so will always encode as 4 bytes 5991c2f4bbeSAlexander Yermolovich // to reduce algorithmic complexity. 6001c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 6011c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.IndirectRelative) { 602612f0f45SAlexander Yermolovich PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 6031c2f4bbeSAlexander Yermolovich assert(RDP->PatchInfo.OldValueSize <= 4 && 6041c2f4bbeSAlexander Yermolovich "Variable encoding reference greater than 4 bytes."); 6051c2f4bbeSAlexander Yermolovich } 6061c2f4bbeSAlexander Yermolovich break; 6071c2f4bbeSAlexander Yermolovich } 6081c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 6091c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 6101c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 6111c2f4bbeSAlexander Yermolovich uint32_t CUOffset = BaseLabel->Offset; 612612f0f45SAlexander Yermolovich ChangeInSize += PreviousChangeInSize; 6131c2f4bbeSAlexander Yermolovich uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 614612f0f45SAlexander Yermolovich CUMap[CUOffset].Offset = CUOffsetUpdate; 615612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 616612f0f45SAlexander Yermolovich PreviousChangeInSize = 0; 617612f0f45SAlexander Yermolovich PreviousOffset = CUOffset; 618*bd1ebe9dSAlexander Yermolovich break; 619*bd1ebe9dSAlexander Yermolovich } 620*bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 621*bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 622*bd1ebe9dSAlexander Yermolovich PreviousChangeInSize += NDE->Value.size(); 623*bd1ebe9dSAlexander Yermolovich break; 6241c2f4bbeSAlexander Yermolovich } 6251c2f4bbeSAlexander Yermolovich } 6261c2f4bbeSAlexander Yermolovich } 627612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 6281c2f4bbeSAlexander Yermolovich return CUMap; 6291c2f4bbeSAlexander Yermolovich } 630*bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 6311c2f4bbeSAlexander Yermolovich 6321c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 6331c2f4bbeSAlexander Yermolovich std::string NewBinaryContents; 6341c2f4bbeSAlexander Yermolovich NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 6351c2f4bbeSAlexander Yermolovich uint32_t StartOffset = 0; 6361c2f4bbeSAlexander Yermolovich uint32_t DwarfUnitBaseOffset = 0; 6371c2f4bbeSAlexander Yermolovich uint32_t OldValueSize = 0; 6381c2f4bbeSAlexander Yermolovich uint32_t Offset = 0; 6391c2f4bbeSAlexander Yermolovich std::string ByteSequence; 6401c2f4bbeSAlexander Yermolovich std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 6411c2f4bbeSAlexander Yermolovich // Wasting one entry to avoid checks for first. 6421c2f4bbeSAlexander Yermolovich LengthPatches.push_back({0, 0}); 6431c2f4bbeSAlexander Yermolovich 6441c2f4bbeSAlexander Yermolovich // Applying all the patches replacing current entry. 6451c2f4bbeSAlexander Yermolovich // This might change the size of .debug_info section. 646ea6c8b01SAlexander Yermolovich for (const UniquePatchPtrType &PatchBase : DebugPatches) { 6471c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 6481c2f4bbeSAlexander Yermolovich switch (P->Kind) { 6491c2f4bbeSAlexander Yermolovich default: 6501c2f4bbeSAlexander Yermolovich continue; 6511c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 6521c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 6531c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset = RDP->DestinationOffset; 6541c2f4bbeSAlexander Yermolovich assert(OldToNewOffset.count(DestinationOffset) && 6551c2f4bbeSAlexander Yermolovich "Destination Offset for reference not updated."); 6561c2f4bbeSAlexander Yermolovich uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 6571c2f4bbeSAlexander Yermolovich Offset = RDP->Offset; 6581c2f4bbeSAlexander Yermolovich OldValueSize = RDP->PatchInfo.OldValueSize; 6591c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.DirectRelative) { 6601c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 6611c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 6621c2f4bbeSAlexander Yermolovich // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 6631c2f4bbeSAlexander Yermolovich // and overflow if later debug information grows. 6641c2f4bbeSAlexander Yermolovich if (ByteSequence.size() > OldValueSize) 6651c2f4bbeSAlexander Yermolovich errs() << "BOLT-ERROR: Relative reference of size " 6661c2f4bbeSAlexander Yermolovich << Twine::utohexstr(OldValueSize) 6671c2f4bbeSAlexander Yermolovich << " overflows with the new encoding.\n"; 6681c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.DirectAbsolute) { 6691c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 6701c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.IndirectRelative) { 6711c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 6721c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 6731c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 6741c2f4bbeSAlexander Yermolovich encodeULEB128(UpdatedOffset, OS, 4); 6751c2f4bbeSAlexander Yermolovich } else { 6761c2f4bbeSAlexander Yermolovich llvm_unreachable("Invalid Reference form."); 6771c2f4bbeSAlexander Yermolovich } 6781c2f4bbeSAlexander Yermolovich break; 6791c2f4bbeSAlexander Yermolovich } 6801c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue32: { 6811c2f4bbeSAlexander Yermolovich DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 6821c2f4bbeSAlexander Yermolovich Offset = P32->Offset; 6831c2f4bbeSAlexander Yermolovich OldValueSize = 4; 6841c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P32->Value); 6851c2f4bbeSAlexander Yermolovich break; 6861c2f4bbeSAlexander Yermolovich } 6871c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 6881c2f4bbeSAlexander Yermolovich DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 6891c2f4bbeSAlexander Yermolovich Offset = P64to32->Offset; 6901c2f4bbeSAlexander Yermolovich OldValueSize = 8; 6911c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P64to32->Value); 6921c2f4bbeSAlexander Yermolovich break; 6931c2f4bbeSAlexander Yermolovich } 6941c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 6951c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *PV = 6961c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 6971c2f4bbeSAlexander Yermolovich Offset = PV->Offset; 6981c2f4bbeSAlexander Yermolovich OldValueSize = PV->OldValueSize; 6991c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 7001c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 7011c2f4bbeSAlexander Yermolovich encodeULEB128(PV->Value, OS); 7021c2f4bbeSAlexander Yermolovich break; 7031c2f4bbeSAlexander Yermolovich } 7041c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64: { 7051c2f4bbeSAlexander Yermolovich DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 7061c2f4bbeSAlexander Yermolovich Offset = P64->Offset; 7071c2f4bbeSAlexander Yermolovich OldValueSize = 8; 7081c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(8, P64->Value); 7091c2f4bbeSAlexander Yermolovich break; 7101c2f4bbeSAlexander Yermolovich } 7111c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 7121c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 7131c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 7141c2f4bbeSAlexander Yermolovich Offset = BaseLabel->Offset; 7151c2f4bbeSAlexander Yermolovich OldValueSize = 0; 7161c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 7171c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 7181c2f4bbeSAlexander Yermolovich // Length to copy between last patch entry and next compile unit. 7191c2f4bbeSAlexander Yermolovich uint32_t RemainingLength = Offset - StartOffset; 7201c2f4bbeSAlexander Yermolovich uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 7211c2f4bbeSAlexander Yermolovich DwarfUnitBaseOffset = NewCUOffset; 7221c2f4bbeSAlexander Yermolovich // Length of previous CU = This CU Offset - sizeof(length) - last CU 7231c2f4bbeSAlexander Yermolovich // Offset. 7241c2f4bbeSAlexander Yermolovich Patch.second = NewCUOffset - 4 - Patch.first; 7251c2f4bbeSAlexander Yermolovich LengthPatches.push_back({NewCUOffset, 0}); 7261c2f4bbeSAlexander Yermolovich break; 7271c2f4bbeSAlexander Yermolovich } 728*bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 729*bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 730*bd1ebe9dSAlexander Yermolovich Offset = NDE->Offset; 731*bd1ebe9dSAlexander Yermolovich OldValueSize = 0; 732*bd1ebe9dSAlexander Yermolovich ByteSequence = NDE->Value; 733*bd1ebe9dSAlexander Yermolovich break; 734*bd1ebe9dSAlexander Yermolovich } 7351c2f4bbeSAlexander Yermolovich } 7361c2f4bbeSAlexander Yermolovich 737*bd1ebe9dSAlexander Yermolovich assert((P->Kind == DebugPatchKind::NewDebugEntry || 738*bd1ebe9dSAlexander Yermolovich Offset + ByteSequence.size() <= BinaryContents.size()) && 7391c2f4bbeSAlexander Yermolovich "Applied patch runs over binary size."); 7401c2f4bbeSAlexander Yermolovich uint32_t Length = Offset - StartOffset; 7411c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 7421c2f4bbeSAlexander Yermolovich Length); 7431c2f4bbeSAlexander Yermolovich NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 7441c2f4bbeSAlexander Yermolovich StartOffset = Offset + OldValueSize; 7451c2f4bbeSAlexander Yermolovich } 7461c2f4bbeSAlexander Yermolovich uint32_t Length = BinaryContents.size() - StartOffset; 7471c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 7481c2f4bbeSAlexander Yermolovich Length); 7491c2f4bbeSAlexander Yermolovich DebugPatches.clear(); 7501c2f4bbeSAlexander Yermolovich 7511c2f4bbeSAlexander Yermolovich // Patching lengths of CUs 7521c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 7531c2f4bbeSAlexander Yermolovich Patch.second = NewBinaryContents.size() - 4 - Patch.first; 7541c2f4bbeSAlexander Yermolovich for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 7551c2f4bbeSAlexander Yermolovich const auto &Patch = LengthPatches[J]; 7561c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, Patch.second); 7571c2f4bbeSAlexander Yermolovich Offset = Patch.first; 7581c2f4bbeSAlexander Yermolovich for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 7591c2f4bbeSAlexander Yermolovich NewBinaryContents[Offset + I] = ByteSequence[I]; 7601c2f4bbeSAlexander Yermolovich } 7611c2f4bbeSAlexander Yermolovich 7621c2f4bbeSAlexander Yermolovich return NewBinaryContents; 763a34c753fSRafael Auler } 764a34c753fSRafael Auler 765a34c753fSRafael Auler void DebugStrWriter::create() { 766a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 767a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 768a34c753fSRafael Auler } 769a34c753fSRafael Auler 770a34c753fSRafael Auler void DebugStrWriter::initialize() { 771a34c753fSRafael Auler auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); 772a34c753fSRafael Auler (*StrStream) << StrSection; 773a34c753fSRafael Auler } 774a34c753fSRafael Auler 775a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 776e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 777a34c753fSRafael Auler if (StrBuffer->empty()) 778a34c753fSRafael Auler initialize(); 779a34c753fSRafael Auler auto Offset = StrBuffer->size(); 780a34c753fSRafael Auler (*StrStream) << Str; 781a34c753fSRafael Auler StrStream->write_zeros(1); 782a34c753fSRafael Auler return Offset; 783a34c753fSRafael Auler } 784a34c753fSRafael Auler 785a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 786a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 787a34c753fSRafael Auler if (!Abbrevs) 788a34c753fSRafael Auler return; 789a34c753fSRafael Auler 79045f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 791*bd1ebe9dSAlexander Yermolovich const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 792a34c753fSRafael Auler 7939f3f9d19SAlexander Yermolovich // We are duplicating abbrev sections, to handle the case where for one CU we 7949f3f9d19SAlexander Yermolovich // modify it, but for another we don't. 7959f3f9d19SAlexander Yermolovich auto UnitDataPtr = std::make_unique<AbbrevData>(); 7969f3f9d19SAlexander Yermolovich AbbrevData &UnitData = *UnitDataPtr.get(); 7979f3f9d19SAlexander Yermolovich UnitData.Buffer = std::make_unique<DebugBufferVector>(); 7989f3f9d19SAlexander Yermolovich UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 799*bd1ebe9dSAlexander Yermolovich 800a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 801a34c753fSRafael Auler 8029f3f9d19SAlexander Yermolovich // Returns true if AbbrevData is re-used, false otherwise. 8039f3f9d19SAlexander Yermolovich auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 8049f3f9d19SAlexander Yermolovich llvm::SHA1 Hasher; 8059f3f9d19SAlexander Yermolovich Hasher.update(AbbrevData); 8069f3f9d19SAlexander Yermolovich StringRef Key = Hasher.final(); 8079f3f9d19SAlexander Yermolovich auto Iter = AbbrevDataCache.find(Key); 8089f3f9d19SAlexander Yermolovich if (Iter != AbbrevDataCache.end()) { 8099f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = Iter->second.get(); 8109f3f9d19SAlexander Yermolovich return true; 8119f3f9d19SAlexander Yermolovich } 8129f3f9d19SAlexander Yermolovich AbbrevDataCache[Key] = std::move(UnitDataPtr); 8139f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = &UnitData; 8149f3f9d19SAlexander Yermolovich return false; 8159f3f9d19SAlexander Yermolovich }; 816a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 817a34c753fSRafael Auler // contents. 818*bd1ebe9dSAlexander Yermolovich if (UnitPatches.empty() && AbbrevEntries.empty()) { 819a34c753fSRafael Auler StringRef AbbrevSectionContents = 820a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 821a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 822a34c753fSRafael Auler StringRef AbbrevContents; 823a34c753fSRafael Auler 824a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 825a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 826a34c753fSRafael Auler // Handle DWP section contribution. 827a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 828a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 829a34c753fSRafael Auler if (!DWOEntry) 830a34c753fSRafael Auler return; 831a34c753fSRafael Auler 832a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 833a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 834a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 835a34c753fSRafael Auler DWOContrubution->Length); 83645f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 837a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 83845f94abcSMaksim Panchenko 83945f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 84045f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 84145f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 84245f94abcSMaksim Panchenko // the set boundaries. 84345f94abcSMaksim Panchenko // 84445f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 84545f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 84645f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 8471c2f4bbeSAlexander Yermolovich for_each( 84845f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 84945f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 85045f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 85145f94abcSMaksim Panchenko }); 8521c2f4bbeSAlexander Yermolovich sort(AbbrevSetOffsets); 85345f94abcSMaksim Panchenko } 8541c2f4bbeSAlexander Yermolovich auto It = upper_bound(AbbrevSetOffsets, StartOffset); 85545f94abcSMaksim Panchenko const uint64_t EndOffset = 85645f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 857a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 85845f94abcSMaksim Panchenko } else { 85945f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 86045f94abcSMaksim Panchenko // abbreviations for this unit only. 86145f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 862a34c753fSRafael Auler } 863a34c753fSRafael Auler 8649f3f9d19SAlexander Yermolovich if (!hashAndAddAbbrev(AbbrevContents)) { 865a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 866a34c753fSRafael Auler OS << AbbrevContents; 8679f3f9d19SAlexander Yermolovich } 868a34c753fSRafael Auler return; 869a34c753fSRafael Auler } 870a34c753fSRafael Auler 871a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 872a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 873a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 874a34c753fSRafael Auler 875a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 876a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 877a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 878a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 879a34c753fSRafael Auler Abbrev.attributes()) { 880a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 881a34c753fSRafael Auler bool Patched = false; 882a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 883a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 884a34c753fSRafael Auler ++I) { 885a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 886a34c753fSRafael Auler continue; 887a34c753fSRafael Auler 888a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 889a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 890a34c753fSRafael Auler Patched = true; 891a34c753fSRafael Auler break; 892a34c753fSRafael Auler } 893a34c753fSRafael Auler if (Patched) 894a34c753fSRafael Auler continue; 895a34c753fSRafael Auler } 896a34c753fSRafael Auler 897a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 898a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 899a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 900a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 901a34c753fSRafael Auler } 902*bd1ebe9dSAlexander Yermolovich const auto Entries = AbbrevEntries.find(&Abbrev); 903*bd1ebe9dSAlexander Yermolovich // Adding new Abbrevs for inserted entries. 904*bd1ebe9dSAlexander Yermolovich if (Entries != AbbrevEntries.end()) { 905*bd1ebe9dSAlexander Yermolovich for (const AbbrevEntry &Entry : Entries->second) { 906*bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Attr, OS); 907*bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Form, OS); 908*bd1ebe9dSAlexander Yermolovich } 909*bd1ebe9dSAlexander Yermolovich } 910a34c753fSRafael Auler encodeULEB128(0, OS); 911a34c753fSRafael Auler encodeULEB128(0, OS); 912a34c753fSRafael Auler } 913a34c753fSRafael Auler encodeULEB128(0, OS); 9149f3f9d19SAlexander Yermolovich 9159f3f9d19SAlexander Yermolovich hashAndAddAbbrev(OS.str()); 916a34c753fSRafael Auler } 917a34c753fSRafael Auler 918a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 9199f3f9d19SAlexander Yermolovich // Used to create determinism for writing out abbrevs. 9209f3f9d19SAlexander Yermolovich std::vector<AbbrevData *> Abbrevs; 92145f94abcSMaksim Panchenko if (DWOId) { 92245f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 92345f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 92445f94abcSMaksim Panchenko // set with the CU. 9251417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 9261417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 92745f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 9281417f607SAlexander Yermolovich if (!IsDWP) { 92945f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 93045f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 93145f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 93245f94abcSMaksim Panchenko "Unable to update debug info.\n"; 93345f94abcSMaksim Panchenko exit(1); 93445f94abcSMaksim Panchenko } 93545f94abcSMaksim Panchenko } 93645f94abcSMaksim Panchenko } 93745f94abcSMaksim Panchenko 9389f3f9d19SAlexander Yermolovich DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 93945f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 94045f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 9419f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 9429f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 9439f3f9d19SAlexander Yermolovich } else { 9449f3f9d19SAlexander Yermolovich Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 9459f3f9d19SAlexander Yermolovich std::unordered_set<AbbrevData *> ProcessedAbbrevs; 9469f3f9d19SAlexander Yermolovich // Add abbreviations from compile and type non-DWO units. 9479f3f9d19SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 9489f3f9d19SAlexander Yermolovich addUnitAbbreviations(*Unit); 9499f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 9509f3f9d19SAlexander Yermolovich if (!ProcessedAbbrevs.insert(Abbrev).second) 9519f3f9d19SAlexander Yermolovich continue; 9529f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 9539f3f9d19SAlexander Yermolovich } 95445f94abcSMaksim Panchenko } 95545f94abcSMaksim Panchenko 956a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 957a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 958a34c753fSRafael Auler uint64_t Size = 0; 9599f3f9d19SAlexander Yermolovich for (const AbbrevData *UnitData : Abbrevs) 9609f3f9d19SAlexander Yermolovich Size += UnitData->Buffer->size(); 9619f3f9d19SAlexander Yermolovich 962a34c753fSRafael Auler ReturnBuffer.reserve(Size); 963a34c753fSRafael Auler 964a34c753fSRafael Auler uint64_t Pos = 0; 9659f3f9d19SAlexander Yermolovich for (AbbrevData *UnitData : Abbrevs) { 9669f3f9d19SAlexander Yermolovich ReturnBuffer.append(*UnitData->Buffer); 9679f3f9d19SAlexander Yermolovich UnitData->Offset = Pos; 9689f3f9d19SAlexander Yermolovich Pos += UnitData->Buffer->size(); 969a34c753fSRafael Auler 9709f3f9d19SAlexander Yermolovich UnitData->Buffer.reset(); 9719f3f9d19SAlexander Yermolovich UnitData->Stream.reset(); 972a34c753fSRafael Auler } 973a34c753fSRafael Auler 974a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 975a34c753fSRafael Auler } 976a34c753fSRafael Auler 977a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 978a34c753fSRafael Auler MCDwarfLineTableParams Params, 979a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 980a34c753fSRafael Auler int PointerSize) { 981a34c753fSRafael Auler // emit the sequence to set the address 982a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 983a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 984a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 985a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 986a34c753fSRafael Auler 987a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 988a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 989a34c753fSRafael Auler } 990a34c753fSRafael Auler 991a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 992a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 993a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 994a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 995a34c753fSRafael Auler if (InputSequences.empty()) 996a34c753fSRafael Auler return; 997a34c753fSRafael Auler 998a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 999a34c753fSRafael Auler unsigned FileNum = 1; 1000a34c753fSRafael Auler unsigned LastLine = 1; 1001a34c753fSRafael Auler unsigned Column = 0; 1002a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1003a34c753fSRafael Auler unsigned Isa = 0; 1004a34c753fSRafael Auler unsigned Discriminator = 0; 1005a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 1006a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 1007a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1008a34c753fSRafael Auler 1009a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 1010a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1011a34c753fSRafael Auler FileNum = 1; 1012a34c753fSRafael Auler LastLine = 1; 1013a34c753fSRafael Auler Column = 0; 1014a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1015a34c753fSRafael Auler Isa = 0; 1016a34c753fSRafael Auler Discriminator = 0; 1017a34c753fSRafael Auler LastAddress = InvalidAddress; 1018a34c753fSRafael Auler }; 1019a34c753fSRafael Auler 1020a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1021a34c753fSRafael Auler const uint64_t SequenceStart = 1022a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 1023a34c753fSRafael Auler 1024a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 1025a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1026a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 1027a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1028a34c753fSRafael Auler } 1029a34c753fSRafael Auler 1030a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 1031a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 1032a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1033a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1034a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 1035a34c753fSRafael Auler 1036a34c753fSRafael Auler if (FileNum != Row.File) { 1037a34c753fSRafael Auler FileNum = Row.File; 1038a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1039a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1040a34c753fSRafael Auler } 1041a34c753fSRafael Auler if (Column != Row.Column) { 1042a34c753fSRafael Auler Column = Row.Column; 1043a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1044a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1045a34c753fSRafael Auler } 1046a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 1047a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1048a34c753fSRafael Auler Discriminator = Row.Discriminator; 1049a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1050a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1051a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1052a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1053a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1054a34c753fSRafael Auler } 1055a34c753fSRafael Auler if (Isa != Row.Isa) { 1056a34c753fSRafael Auler Isa = Row.Isa; 1057a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1058a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1059a34c753fSRafael Auler } 1060a34c753fSRafael Auler if (Row.IsStmt != Flags) { 1061a34c753fSRafael Auler Flags = Row.IsStmt; 1062a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1063a34c753fSRafael Auler } 1064a34c753fSRafael Auler if (Row.BasicBlock) 1065a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1066a34c753fSRafael Auler if (Row.PrologueEnd) 1067a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1068a34c753fSRafael Auler if (Row.EpilogueBegin) 1069a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1070a34c753fSRafael Auler 1071a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 1072a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 1073a34c753fSRafael Auler if (Row.EndSequence) { 1074a34c753fSRafael Auler emitEndOfSequence(Address); 1075a34c753fSRafael Auler } else { 1076a34c753fSRafael Auler if (LastAddress == InvalidAddress) 1077a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1078a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1079a34c753fSRafael Auler else 1080a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1081a34c753fSRafael Auler 1082a34c753fSRafael Auler LastAddress = Address; 1083a34c753fSRafael Auler LastLine = Row.Line; 1084a34c753fSRafael Auler } 1085a34c753fSRafael Auler 1086a34c753fSRafael Auler Discriminator = 0; 1087a34c753fSRafael Auler } 1088a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 1089a34c753fSRafael Auler } 1090a34c753fSRafael Auler 1091a34c753fSRafael Auler // Finish with the end of the sequence. 1092a34c753fSRafael Auler if (LastAddress != InvalidAddress) 1093a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1094a34c753fSRafael Auler } 1095a34c753fSRafael Auler 1096a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 1097a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 1098a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 1099a34c753fSRafael Auler static inline void emitDwarfLineTable( 1100a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 1101a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1102a34c753fSRafael Auler unsigned FileNum = 1; 1103a34c753fSRafael Auler unsigned LastLine = 1; 1104a34c753fSRafael Auler unsigned Column = 0; 1105a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1106a34c753fSRafael Auler unsigned Isa = 0; 1107a34c753fSRafael Auler unsigned Discriminator = 0; 1108a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 1109a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1110a34c753fSRafael Auler 1111a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1112a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1113a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1114a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1115a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1116a34c753fSRafael Auler FileNum = 1; 1117a34c753fSRafael Auler LastLine = 1; 1118a34c753fSRafael Auler Column = 0; 1119a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1120a34c753fSRafael Auler Isa = 0; 1121a34c753fSRafael Auler Discriminator = 0; 1122a34c753fSRafael Auler LastLabel = nullptr; 1123a34c753fSRafael Auler continue; 1124a34c753fSRafael Auler } 1125a34c753fSRafael Auler 1126a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1127a34c753fSRafael Auler 1128a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 1129a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 1130a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1131a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1132a34c753fSRafael Auler } 1133a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 1134a34c753fSRafael Auler Column = LineEntry.getColumn(); 1135a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1136a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1137a34c753fSRafael Auler } 1138a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 1139a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1140a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 1141a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1142a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1143a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1144a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1145a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1146a34c753fSRafael Auler } 1147a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 1148a34c753fSRafael Auler Isa = LineEntry.getIsa(); 1149a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1150a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1151a34c753fSRafael Auler } 1152a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1153a34c753fSRafael Auler Flags = LineEntry.getFlags(); 1154a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1155a34c753fSRafael Auler } 1156a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1157a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1158a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1159a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1160a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1161a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1162a34c753fSRafael Auler 1163a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 1164a34c753fSRafael Auler 1165a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 1166a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 1167a34c753fSRafael Auler // Label and the current Label. 1168a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1169a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1170a34c753fSRafael Auler Discriminator = 0; 1171a34c753fSRafael Auler LastLine = LineEntry.getLine(); 1172a34c753fSRafael Auler LastLabel = Label; 1173a34c753fSRafael Auler } 1174a34c753fSRafael Auler 1175a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 1176a34c753fSRafael Auler } 1177a34c753fSRafael Auler 1178a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1179b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 1180b73c87bcSMaksim Panchenko BinaryContext &BC) const { 1181a34c753fSRafael Auler if (!RawData.empty()) { 1182a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 1183a34c753fSRafael Auler InputSequences.empty() && 1184a34c753fSRafael Auler "cannot combine raw data with new line entries"); 1185a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 1186a34c753fSRafael Auler MCOS->emitBytes(RawData); 1187a34c753fSRafael Auler 1188b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 1189b73c87bcSMaksim Panchenko // 1190b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1191b73c87bcSMaksim Panchenko // without relocations. 1192b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 1193b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1194b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1195b73c87bcSMaksim Panchenko 1196a34c753fSRafael Auler return; 1197a34c753fSRafael Auler } 1198a34c753fSRafael Auler 1199a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1200a34c753fSRafael Auler 1201a34c753fSRafael Auler // Put out the line tables. 1202a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1203a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1204a34c753fSRafael Auler 1205a34c753fSRafael Auler // Emit line tables for the original code. 1206a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1207a34c753fSRafael Auler 1208a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 1209a34c753fSRafael Auler // of this section (that was used in a previous expression). 1210a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 1211a34c753fSRafael Auler } 1212a34c753fSRafael Auler 1213a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1214a34c753fSRafael Auler MCAssembler &Assembler = 1215a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1216a34c753fSRafael Auler 1217a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1218a34c753fSRafael Auler 1219a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 1220a34c753fSRafael Auler 1221a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 1222a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 1223a34c753fSRafael Auler if (LineTables.empty()) 1224a34c753fSRafael Auler return; 1225a34c753fSRafael Auler 1226a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 1227a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 1228a34c753fSRafael Auler if (BC.Ctx->getDwarfVersion() >= 5) 1229a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 1230a34c753fSRafael Auler 1231a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 1232a34c753fSRafael Auler Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); 1233a34c753fSRafael Auler 1234a34c753fSRafael Auler // Handle the rest of the Compile Units. 1235a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 1236b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1237a34c753fSRafael Auler } 1238a34c753fSRafael Auler } 1239a34c753fSRafael Auler 1240a34c753fSRafael Auler } // namespace bolt 1241a34c753fSRafael Auler } // namespace llvm 1242