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 42bd1ebe9dSAlexander Yermolovich /// Finds attributes FormValue and Offset. 43bd1ebe9dSAlexander Yermolovich /// 44bd1ebe9dSAlexander Yermolovich /// \param DIE die to look up in. 45bd1ebe9dSAlexander Yermolovich /// \param Index the attribute index to extract. 46bd1ebe9dSAlexander Yermolovich /// \return an optional AttrInfo with DWARFFormValue and Offset. 47bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> 48bd1ebe9dSAlexander Yermolovich findAttributeInfo(const DWARFDie DIE, 49bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl, 50bd1ebe9dSAlexander Yermolovich uint32_t Index) { 51bd1ebe9dSAlexander Yermolovich const DWARFUnit &U = *DIE.getDwarfUnit(); 52bd1ebe9dSAlexander Yermolovich uint64_t Offset = 53bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U); 54bd1ebe9dSAlexander Yermolovich Optional<DWARFFormValue> Value = 55bd1ebe9dSAlexander Yermolovich AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U); 56bd1ebe9dSAlexander Yermolovich if (!Value) 57bd1ebe9dSAlexander Yermolovich return None; 58bd1ebe9dSAlexander Yermolovich // AttributeSpec 59bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal = 60bd1ebe9dSAlexander Yermolovich AbbrevDecl->attributes().begin() + Index; 61bd1ebe9dSAlexander Yermolovich uint32_t ValSize = 0; 62bd1ebe9dSAlexander Yermolovich Optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U); 63bd1ebe9dSAlexander Yermolovich if (ValSizeOpt) { 64bd1ebe9dSAlexander Yermolovich ValSize = static_cast<uint32_t>(*ValSizeOpt); 65bd1ebe9dSAlexander Yermolovich } else { 66bd1ebe9dSAlexander Yermolovich DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 67bd1ebe9dSAlexander Yermolovich uint64_t NewOffset = Offset; 68bd1ebe9dSAlexander Yermolovich DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset, 69bd1ebe9dSAlexander Yermolovich U.getFormParams()); 70bd1ebe9dSAlexander Yermolovich // This includes entire size of the entry, which might not be just the 71bd1ebe9dSAlexander Yermolovich // encoding part. For example for DW_AT_loc it will include expression 72bd1ebe9dSAlexander Yermolovich // location. 73bd1ebe9dSAlexander Yermolovich ValSize = NewOffset - Offset; 74bd1ebe9dSAlexander Yermolovich } 75bd1ebe9dSAlexander Yermolovich 76bd1ebe9dSAlexander Yermolovich return AttrInfo{*Value, Offset, ValSize}; 77bd1ebe9dSAlexander Yermolovich } 78bd1ebe9dSAlexander 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 424bd1ebe9dSAlexander Yermolovich static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { 425bd1ebe9dSAlexander Yermolovich std::string LE64(ByteSize, 0); 426bd1ebe9dSAlexander Yermolovich for (size_t I = 0; I < ByteSize; ++I) { 427bd1ebe9dSAlexander Yermolovich LE64[I] = NewValue & 0xff; 428bd1ebe9dSAlexander Yermolovich NewValue >>= 8; 429bd1ebe9dSAlexander Yermolovich } 430bd1ebe9dSAlexander Yermolovich return LE64; 431bd1ebe9dSAlexander Yermolovich } 432bd1ebe9dSAlexander Yermolovich 433bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 434bd1ebe9dSAlexander Yermolovich uint32_t Value) { 435bd1ebe9dSAlexander Yermolovich std::string StrValue = encodeLE(4, Value); 436bd1ebe9dSAlexander Yermolovich insertNewEntry(DIE, std::move(StrValue)); 437bd1ebe9dSAlexander Yermolovich } 438bd1ebe9dSAlexander Yermolovich 439bd1ebe9dSAlexander Yermolovich void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, 440bd1ebe9dSAlexander Yermolovich std::string &&Value) { 441bd1ebe9dSAlexander Yermolovich const DWARFAbbreviationDeclaration *AbbrevDecl = 442bd1ebe9dSAlexander Yermolovich DIE.getAbbreviationDeclarationPtr(); 443bd1ebe9dSAlexander Yermolovich 444bd1ebe9dSAlexander Yermolovich // In case this DIE has no attributes. 445bd1ebe9dSAlexander Yermolovich uint32_t Offset = DIE.getOffset() + 1; 446bd1ebe9dSAlexander Yermolovich size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); 447bd1ebe9dSAlexander Yermolovich if (NumOfAttributes) { 448bd1ebe9dSAlexander Yermolovich Optional<AttrInfo> Val = 449bd1ebe9dSAlexander Yermolovich findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); 450bd1ebe9dSAlexander Yermolovich assert(Val && "Invalid Value."); 451bd1ebe9dSAlexander Yermolovich 452bd1ebe9dSAlexander Yermolovich Offset = Val->Offset + Val->Size - DWPUnitOffset; 453bd1ebe9dSAlexander Yermolovich } 454bd1ebe9dSAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 455bd1ebe9dSAlexander Yermolovich DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); 456bd1ebe9dSAlexander Yermolovich } 457bd1ebe9dSAlexander 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)); 489a44fe319SAlexander Yermolovich else if (OldValueSize == 8) 490ea6c8b01SAlexander Yermolovich DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); 491a44fe319SAlexander Yermolovich else 492a44fe319SAlexander Yermolovich DebugPatches.emplace_back( 493a44fe319SAlexander Yermolovich new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); 4941c2f4bbeSAlexander Yermolovich } 4951c2f4bbeSAlexander Yermolovich 4961c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, 4971c2f4bbeSAlexander Yermolovich std::string &&NewValue, 4981c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 4991c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(NewValue)); 5001c2f4bbeSAlexander Yermolovich } 5011c2f4bbeSAlexander Yermolovich 5021c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) { 5031c2f4bbeSAlexander Yermolovich auto Str = std::string(1, Value); 5041c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Str)); 5051c2f4bbeSAlexander Yermolovich } 5061c2f4bbeSAlexander Yermolovich 5071c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue, 5081c2f4bbeSAlexander Yermolovich size_t ByteSize) { 5091c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue)); 5101c2f4bbeSAlexander Yermolovich } 5111c2f4bbeSAlexander Yermolovich 5121c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value, 5131c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 514a34c753fSRafael Auler std::string Buff; 515a34c753fSRafael Auler raw_string_ostream OS(Buff); 5161c2f4bbeSAlexander Yermolovich encodeULEB128(Value, OS, OldValueSize); 517a34c753fSRafael Auler 5181c2f4bbeSAlexander Yermolovich Patches.emplace_back(Offset, std::move(Buff)); 519a34c753fSRafael Auler } 520a34c753fSRafael Auler 5211c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { 522a34c753fSRafael Auler addLEPatch(Offset, NewValue, 8); 523a34c753fSRafael Auler } 524a34c753fSRafael Auler 5251c2f4bbeSAlexander Yermolovich void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, 5261c2f4bbeSAlexander Yermolovich uint32_t OldValueSize) { 527a34c753fSRafael Auler addLEPatch(Offset, NewValue, 4); 528a34c753fSRafael Auler } 529a34c753fSRafael Auler 5301c2f4bbeSAlexander Yermolovich std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) { 5311c2f4bbeSAlexander Yermolovich std::string BinaryContentsStr = std::string(BinaryContents); 532a34c753fSRafael Auler for (const auto &Patch : Patches) { 5331c2f4bbeSAlexander Yermolovich uint32_t Offset = Patch.first; 534a34c753fSRafael Auler const std::string &ByteSequence = Patch.second; 535a34c753fSRafael Auler assert(Offset + ByteSequence.size() <= BinaryContents.size() && 536a34c753fSRafael Auler "Applied patch runs over binary size."); 537a34c753fSRafael Auler for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) { 5381c2f4bbeSAlexander Yermolovich BinaryContentsStr[Offset + I] = ByteSequence[I]; 539a34c753fSRafael Auler } 540a34c753fSRafael Auler } 5411c2f4bbeSAlexander Yermolovich return BinaryContentsStr; 5421c2f4bbeSAlexander Yermolovich } 5431c2f4bbeSAlexander Yermolovich 544612f0f45SAlexander Yermolovich CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, 545612f0f45SAlexander Yermolovich bool IsDWOContext) { 546612f0f45SAlexander Yermolovich CUOffsetMap CUMap; 547ea6c8b01SAlexander Yermolovich std::sort(DebugPatches.begin(), DebugPatches.end(), 548ea6c8b01SAlexander Yermolovich [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) { 549bd1ebe9dSAlexander Yermolovich if (V1.get()->Offset == V2.get()->Offset) { 550bd1ebe9dSAlexander Yermolovich if (V1->Kind == DebugPatchKind::NewDebugEntry && 551bd1ebe9dSAlexander Yermolovich V2->Kind == DebugPatchKind::NewDebugEntry) 552bd1ebe9dSAlexander Yermolovich return reinterpret_cast<const NewDebugEntry *>(V1.get()) 553bd1ebe9dSAlexander Yermolovich ->CurrentOrder < 554bd1ebe9dSAlexander Yermolovich reinterpret_cast<const NewDebugEntry *>(V2.get()) 555bd1ebe9dSAlexander Yermolovich ->CurrentOrder; 556bd1ebe9dSAlexander Yermolovich 557bd1ebe9dSAlexander Yermolovich // This is a case where we are modifying first entry of next 558bd1ebe9dSAlexander Yermolovich // DIE, and adding a new one. 559bd1ebe9dSAlexander Yermolovich return V1->Kind == DebugPatchKind::NewDebugEntry; 560bd1ebe9dSAlexander Yermolovich } 5611c2f4bbeSAlexander Yermolovich return V1.get()->Offset < V2.get()->Offset; 5621c2f4bbeSAlexander Yermolovich }); 5631c2f4bbeSAlexander Yermolovich 564612f0f45SAlexander Yermolovich DWARFUnitVector::compile_unit_range CompileUnits = 565612f0f45SAlexander Yermolovich IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); 566612f0f45SAlexander Yermolovich 567612f0f45SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits) 568612f0f45SAlexander Yermolovich CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()), 569612f0f45SAlexander Yermolovich static_cast<uint32_t>(CU->getLength())}; 570612f0f45SAlexander Yermolovich 5711c2f4bbeSAlexander Yermolovich // Calculating changes in .debug_info size from Patches to build a map of old 5721c2f4bbeSAlexander Yermolovich // to updated reference destination offsets. 573612f0f45SAlexander Yermolovich uint32_t PreviousOffset = 0; 574612f0f45SAlexander Yermolovich int32_t PreviousChangeInSize = 0; 575ea6c8b01SAlexander Yermolovich for (UniquePatchPtrType &PatchBase : DebugPatches) { 5761c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 5771c2f4bbeSAlexander Yermolovich switch (P->Kind) { 5781c2f4bbeSAlexander Yermolovich default: 5791c2f4bbeSAlexander Yermolovich continue; 5801c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 581612f0f45SAlexander Yermolovich PreviousChangeInSize -= 4; 5821c2f4bbeSAlexander Yermolovich break; 5831c2f4bbeSAlexander Yermolovich } 584a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 585a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 586a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 587a44fe319SAlexander Yermolovich PreviousChangeInSize += 4 - DPVS->OldValueSize; 588a44fe319SAlexander Yermolovich break; 589a44fe319SAlexander Yermolovich } 5901c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 5911c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *DPV = 5921c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 5931c2f4bbeSAlexander Yermolovich std::string Temp; 5941c2f4bbeSAlexander Yermolovich raw_string_ostream OS(Temp); 5951c2f4bbeSAlexander Yermolovich encodeULEB128(DPV->Value, OS); 596612f0f45SAlexander Yermolovich PreviousChangeInSize += Temp.size() - DPV->OldValueSize; 5971c2f4bbeSAlexander Yermolovich break; 5981c2f4bbeSAlexander Yermolovich } 5991c2f4bbeSAlexander Yermolovich case DebugPatchKind::DestinationReferenceLabel: { 6001c2f4bbeSAlexander Yermolovich DestinationReferenceLabel *DRL = 6011c2f4bbeSAlexander Yermolovich reinterpret_cast<DestinationReferenceLabel *>(P); 602612f0f45SAlexander Yermolovich OldToNewOffset[DRL->Offset] = 603612f0f45SAlexander Yermolovich DRL->Offset + ChangeInSize + PreviousChangeInSize; 6041c2f4bbeSAlexander Yermolovich break; 6051c2f4bbeSAlexander Yermolovich } 6061c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 6071c2f4bbeSAlexander Yermolovich // This doesn't look to be a common case, so will always encode as 4 bytes 6081c2f4bbeSAlexander Yermolovich // to reduce algorithmic complexity. 6091c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 6101c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.IndirectRelative) { 611612f0f45SAlexander Yermolovich PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; 6121c2f4bbeSAlexander Yermolovich assert(RDP->PatchInfo.OldValueSize <= 4 && 6131c2f4bbeSAlexander Yermolovich "Variable encoding reference greater than 4 bytes."); 6141c2f4bbeSAlexander Yermolovich } 6151c2f4bbeSAlexander Yermolovich break; 6161c2f4bbeSAlexander Yermolovich } 6171c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 6181c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 6191c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 6201c2f4bbeSAlexander Yermolovich uint32_t CUOffset = BaseLabel->Offset; 621612f0f45SAlexander Yermolovich ChangeInSize += PreviousChangeInSize; 6221c2f4bbeSAlexander Yermolovich uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; 623612f0f45SAlexander Yermolovich CUMap[CUOffset].Offset = CUOffsetUpdate; 624612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 625612f0f45SAlexander Yermolovich PreviousChangeInSize = 0; 626612f0f45SAlexander Yermolovich PreviousOffset = CUOffset; 627bd1ebe9dSAlexander Yermolovich break; 628bd1ebe9dSAlexander Yermolovich } 629bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 630bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 631bd1ebe9dSAlexander Yermolovich PreviousChangeInSize += NDE->Value.size(); 632bd1ebe9dSAlexander Yermolovich break; 6331c2f4bbeSAlexander Yermolovich } 6341c2f4bbeSAlexander Yermolovich } 6351c2f4bbeSAlexander Yermolovich } 636612f0f45SAlexander Yermolovich CUMap[PreviousOffset].Length += PreviousChangeInSize; 6371c2f4bbeSAlexander Yermolovich return CUMap; 6381c2f4bbeSAlexander Yermolovich } 639bd1ebe9dSAlexander Yermolovich uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; 6401c2f4bbeSAlexander Yermolovich 6411c2f4bbeSAlexander Yermolovich std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { 6421c2f4bbeSAlexander Yermolovich std::string NewBinaryContents; 6431c2f4bbeSAlexander Yermolovich NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); 6441c2f4bbeSAlexander Yermolovich uint32_t StartOffset = 0; 6451c2f4bbeSAlexander Yermolovich uint32_t DwarfUnitBaseOffset = 0; 6461c2f4bbeSAlexander Yermolovich uint32_t OldValueSize = 0; 6471c2f4bbeSAlexander Yermolovich uint32_t Offset = 0; 6481c2f4bbeSAlexander Yermolovich std::string ByteSequence; 6491c2f4bbeSAlexander Yermolovich std::vector<std::pair<uint32_t, uint32_t>> LengthPatches; 6501c2f4bbeSAlexander Yermolovich // Wasting one entry to avoid checks for first. 6511c2f4bbeSAlexander Yermolovich LengthPatches.push_back({0, 0}); 6521c2f4bbeSAlexander Yermolovich 6531c2f4bbeSAlexander Yermolovich // Applying all the patches replacing current entry. 6541c2f4bbeSAlexander Yermolovich // This might change the size of .debug_info section. 655ea6c8b01SAlexander Yermolovich for (const UniquePatchPtrType &PatchBase : DebugPatches) { 6561c2f4bbeSAlexander Yermolovich Patch *P = PatchBase.get(); 6571c2f4bbeSAlexander Yermolovich switch (P->Kind) { 6581c2f4bbeSAlexander Yermolovich default: 6591c2f4bbeSAlexander Yermolovich continue; 6601c2f4bbeSAlexander Yermolovich case DebugPatchKind::ReferencePatchValue: { 6611c2f4bbeSAlexander Yermolovich DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P); 6621c2f4bbeSAlexander Yermolovich uint32_t DestinationOffset = RDP->DestinationOffset; 6631c2f4bbeSAlexander Yermolovich assert(OldToNewOffset.count(DestinationOffset) && 6641c2f4bbeSAlexander Yermolovich "Destination Offset for reference not updated."); 6651c2f4bbeSAlexander Yermolovich uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; 6661c2f4bbeSAlexander Yermolovich Offset = RDP->Offset; 6671c2f4bbeSAlexander Yermolovich OldValueSize = RDP->PatchInfo.OldValueSize; 6681c2f4bbeSAlexander Yermolovich if (RDP->PatchInfo.DirectRelative) { 6691c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 6701c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 6711c2f4bbeSAlexander Yermolovich // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge 6721c2f4bbeSAlexander Yermolovich // and overflow if later debug information grows. 6731c2f4bbeSAlexander Yermolovich if (ByteSequence.size() > OldValueSize) 6741c2f4bbeSAlexander Yermolovich errs() << "BOLT-ERROR: Relative reference of size " 6751c2f4bbeSAlexander Yermolovich << Twine::utohexstr(OldValueSize) 6761c2f4bbeSAlexander Yermolovich << " overflows with the new encoding.\n"; 6771c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.DirectAbsolute) { 6781c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(OldValueSize, UpdatedOffset); 6791c2f4bbeSAlexander Yermolovich } else if (RDP->PatchInfo.IndirectRelative) { 6801c2f4bbeSAlexander Yermolovich UpdatedOffset -= DwarfUnitBaseOffset; 6811c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 6821c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 6831c2f4bbeSAlexander Yermolovich encodeULEB128(UpdatedOffset, OS, 4); 6841c2f4bbeSAlexander Yermolovich } else { 6851c2f4bbeSAlexander Yermolovich llvm_unreachable("Invalid Reference form."); 6861c2f4bbeSAlexander Yermolovich } 6871c2f4bbeSAlexander Yermolovich break; 6881c2f4bbeSAlexander Yermolovich } 6891c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue32: { 6901c2f4bbeSAlexander Yermolovich DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P); 6911c2f4bbeSAlexander Yermolovich Offset = P32->Offset; 6921c2f4bbeSAlexander Yermolovich OldValueSize = 4; 6931c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P32->Value); 6941c2f4bbeSAlexander Yermolovich break; 6951c2f4bbeSAlexander Yermolovich } 6961c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64to32: { 6971c2f4bbeSAlexander Yermolovich DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P); 6981c2f4bbeSAlexander Yermolovich Offset = P64to32->Offset; 6991c2f4bbeSAlexander Yermolovich OldValueSize = 8; 7001c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, P64to32->Value); 7011c2f4bbeSAlexander Yermolovich break; 7021c2f4bbeSAlexander Yermolovich } 703a44fe319SAlexander Yermolovich case DebugPatchKind::PatchValue32GenericSize: { 704a44fe319SAlexander Yermolovich DebugPatch32GenericSize *DPVS = 705a44fe319SAlexander Yermolovich reinterpret_cast<DebugPatch32GenericSize *>(P); 706a44fe319SAlexander Yermolovich Offset = DPVS->Offset; 707a44fe319SAlexander Yermolovich OldValueSize = DPVS->OldValueSize; 708a44fe319SAlexander Yermolovich ByteSequence = encodeLE(4, DPVS->Value); 709a44fe319SAlexander Yermolovich break; 710a44fe319SAlexander Yermolovich } 7111c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValueVariable: { 7121c2f4bbeSAlexander Yermolovich DebugPatchVariableSize *PV = 7131c2f4bbeSAlexander Yermolovich reinterpret_cast<DebugPatchVariableSize *>(P); 7141c2f4bbeSAlexander Yermolovich Offset = PV->Offset; 7151c2f4bbeSAlexander Yermolovich OldValueSize = PV->OldValueSize; 7161c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 7171c2f4bbeSAlexander Yermolovich raw_string_ostream OS(ByteSequence); 7181c2f4bbeSAlexander Yermolovich encodeULEB128(PV->Value, OS); 7191c2f4bbeSAlexander Yermolovich break; 7201c2f4bbeSAlexander Yermolovich } 7211c2f4bbeSAlexander Yermolovich case DebugPatchKind::PatchValue64: { 7221c2f4bbeSAlexander Yermolovich DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P); 7231c2f4bbeSAlexander Yermolovich Offset = P64->Offset; 7241c2f4bbeSAlexander Yermolovich OldValueSize = 8; 7251c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(8, P64->Value); 7261c2f4bbeSAlexander Yermolovich break; 7271c2f4bbeSAlexander Yermolovich } 7281c2f4bbeSAlexander Yermolovich case DebugPatchKind::DWARFUnitOffsetBaseLabel: { 7291c2f4bbeSAlexander Yermolovich DWARFUnitOffsetBaseLabel *BaseLabel = 7301c2f4bbeSAlexander Yermolovich reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P); 7311c2f4bbeSAlexander Yermolovich Offset = BaseLabel->Offset; 7321c2f4bbeSAlexander Yermolovich OldValueSize = 0; 7331c2f4bbeSAlexander Yermolovich ByteSequence.clear(); 7341c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 7351c2f4bbeSAlexander Yermolovich // Length to copy between last patch entry and next compile unit. 7361c2f4bbeSAlexander Yermolovich uint32_t RemainingLength = Offset - StartOffset; 7371c2f4bbeSAlexander Yermolovich uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; 7381c2f4bbeSAlexander Yermolovich DwarfUnitBaseOffset = NewCUOffset; 7391c2f4bbeSAlexander Yermolovich // Length of previous CU = This CU Offset - sizeof(length) - last CU 7401c2f4bbeSAlexander Yermolovich // Offset. 7411c2f4bbeSAlexander Yermolovich Patch.second = NewCUOffset - 4 - Patch.first; 7421c2f4bbeSAlexander Yermolovich LengthPatches.push_back({NewCUOffset, 0}); 7431c2f4bbeSAlexander Yermolovich break; 7441c2f4bbeSAlexander Yermolovich } 745bd1ebe9dSAlexander Yermolovich case DebugPatchKind::NewDebugEntry: { 746bd1ebe9dSAlexander Yermolovich NewDebugEntry *NDE = reinterpret_cast<NewDebugEntry *>(P); 747bd1ebe9dSAlexander Yermolovich Offset = NDE->Offset; 748bd1ebe9dSAlexander Yermolovich OldValueSize = 0; 749bd1ebe9dSAlexander Yermolovich ByteSequence = NDE->Value; 750bd1ebe9dSAlexander Yermolovich break; 751bd1ebe9dSAlexander Yermolovich } 7521c2f4bbeSAlexander Yermolovich } 7531c2f4bbeSAlexander Yermolovich 754bd1ebe9dSAlexander Yermolovich assert((P->Kind == DebugPatchKind::NewDebugEntry || 755bd1ebe9dSAlexander Yermolovich Offset + ByteSequence.size() <= BinaryContents.size()) && 7561c2f4bbeSAlexander Yermolovich "Applied patch runs over binary size."); 7571c2f4bbeSAlexander Yermolovich uint32_t Length = Offset - StartOffset; 7581c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 7591c2f4bbeSAlexander Yermolovich Length); 7601c2f4bbeSAlexander Yermolovich NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); 7611c2f4bbeSAlexander Yermolovich StartOffset = Offset + OldValueSize; 7621c2f4bbeSAlexander Yermolovich } 7631c2f4bbeSAlexander Yermolovich uint32_t Length = BinaryContents.size() - StartOffset; 7641c2f4bbeSAlexander Yermolovich NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), 7651c2f4bbeSAlexander Yermolovich Length); 7661c2f4bbeSAlexander Yermolovich DebugPatches.clear(); 7671c2f4bbeSAlexander Yermolovich 7681c2f4bbeSAlexander Yermolovich // Patching lengths of CUs 7691c2f4bbeSAlexander Yermolovich auto &Patch = LengthPatches.back(); 7701c2f4bbeSAlexander Yermolovich Patch.second = NewBinaryContents.size() - 4 - Patch.first; 7711c2f4bbeSAlexander Yermolovich for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { 7721c2f4bbeSAlexander Yermolovich const auto &Patch = LengthPatches[J]; 7731c2f4bbeSAlexander Yermolovich ByteSequence = encodeLE(4, Patch.second); 7741c2f4bbeSAlexander Yermolovich Offset = Patch.first; 7751c2f4bbeSAlexander Yermolovich for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) 7761c2f4bbeSAlexander Yermolovich NewBinaryContents[Offset + I] = ByteSequence[I]; 7771c2f4bbeSAlexander Yermolovich } 7781c2f4bbeSAlexander Yermolovich 7791c2f4bbeSAlexander Yermolovich return NewBinaryContents; 780a34c753fSRafael Auler } 781a34c753fSRafael Auler 782a34c753fSRafael Auler void DebugStrWriter::create() { 783a34c753fSRafael Auler StrBuffer = std::make_unique<DebugStrBufferVector>(); 784a34c753fSRafael Auler StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer); 785a34c753fSRafael Auler } 786a34c753fSRafael Auler 787a34c753fSRafael Auler void DebugStrWriter::initialize() { 788a34c753fSRafael Auler auto StrSection = BC->DwCtx->getDWARFObj().getStrSection(); 789a34c753fSRafael Auler (*StrStream) << StrSection; 790a34c753fSRafael Auler } 791a34c753fSRafael Auler 792a34c753fSRafael Auler uint32_t DebugStrWriter::addString(StringRef Str) { 793e579f5c6SAlexander Yermolovich std::lock_guard<std::mutex> Lock(WriterMutex); 794a34c753fSRafael Auler if (StrBuffer->empty()) 795a34c753fSRafael Auler initialize(); 796a34c753fSRafael Auler auto Offset = StrBuffer->size(); 797a34c753fSRafael Auler (*StrStream) << Str; 798a34c753fSRafael Auler StrStream->write_zeros(1); 799a34c753fSRafael Auler return Offset; 800a34c753fSRafael Auler } 801a34c753fSRafael Auler 802a34c753fSRafael Auler void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { 803a34c753fSRafael Auler const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); 804a34c753fSRafael Auler if (!Abbrevs) 805a34c753fSRafael Auler return; 806a34c753fSRafael Auler 80745f94abcSMaksim Panchenko const PatchesTy &UnitPatches = Patches[&Unit]; 808bd1ebe9dSAlexander Yermolovich const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; 809a34c753fSRafael Auler 8109f3f9d19SAlexander Yermolovich // We are duplicating abbrev sections, to handle the case where for one CU we 8119f3f9d19SAlexander Yermolovich // modify it, but for another we don't. 8129f3f9d19SAlexander Yermolovich auto UnitDataPtr = std::make_unique<AbbrevData>(); 8139f3f9d19SAlexander Yermolovich AbbrevData &UnitData = *UnitDataPtr.get(); 8149f3f9d19SAlexander Yermolovich UnitData.Buffer = std::make_unique<DebugBufferVector>(); 8159f3f9d19SAlexander Yermolovich UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer); 816bd1ebe9dSAlexander Yermolovich 817a34c753fSRafael Auler raw_svector_ostream &OS = *UnitData.Stream.get(); 818a34c753fSRafael Auler 8199f3f9d19SAlexander Yermolovich // Returns true if AbbrevData is re-used, false otherwise. 8209f3f9d19SAlexander Yermolovich auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { 8219f3f9d19SAlexander Yermolovich llvm::SHA1 Hasher; 8229f3f9d19SAlexander Yermolovich Hasher.update(AbbrevData); 823*330268baSArgyrios Kyrtzidis std::array<uint8_t, 20> Hash = Hasher.final(); 824*330268baSArgyrios Kyrtzidis StringRef Key((const char *)Hash.data(), Hash.size()); 8259f3f9d19SAlexander Yermolovich auto Iter = AbbrevDataCache.find(Key); 8269f3f9d19SAlexander Yermolovich if (Iter != AbbrevDataCache.end()) { 8279f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = Iter->second.get(); 8289f3f9d19SAlexander Yermolovich return true; 8299f3f9d19SAlexander Yermolovich } 8309f3f9d19SAlexander Yermolovich AbbrevDataCache[Key] = std::move(UnitDataPtr); 8319f3f9d19SAlexander Yermolovich UnitsAbbrevData[&Unit] = &UnitData; 8329f3f9d19SAlexander Yermolovich return false; 8339f3f9d19SAlexander Yermolovich }; 834a34c753fSRafael Auler // Take a fast path if there are no patches to apply. Simply copy the original 835a34c753fSRafael Auler // contents. 836bd1ebe9dSAlexander Yermolovich if (UnitPatches.empty() && AbbrevEntries.empty()) { 837a34c753fSRafael Auler StringRef AbbrevSectionContents = 838a34c753fSRafael Auler Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() 839a34c753fSRafael Auler : Unit.getContext().getDWARFObj().getAbbrevSection(); 840a34c753fSRafael Auler StringRef AbbrevContents; 841a34c753fSRafael Auler 842a34c753fSRafael Auler const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); 843a34c753fSRafael Auler if (!CUIndex.getRows().empty()) { 844a34c753fSRafael Auler // Handle DWP section contribution. 845a34c753fSRafael Auler const DWARFUnitIndex::Entry *DWOEntry = 846a34c753fSRafael Auler CUIndex.getFromHash(*Unit.getDWOId()); 847a34c753fSRafael Auler if (!DWOEntry) 848a34c753fSRafael Auler return; 849a34c753fSRafael Auler 850a34c753fSRafael Auler const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = 851a34c753fSRafael Auler DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); 852a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset, 853a34c753fSRafael Auler DWOContrubution->Length); 85445f94abcSMaksim Panchenko } else if (!Unit.isDWOUnit()) { 855a34c753fSRafael Auler const uint64_t StartOffset = Unit.getAbbreviationsOffset(); 85645f94abcSMaksim Panchenko 85745f94abcSMaksim Panchenko // We know where the unit's abbreviation set starts, but not where it ends 85845f94abcSMaksim Panchenko // as such data is not readily available. Hence, we have to build a sorted 85945f94abcSMaksim Panchenko // list of start addresses and find the next starting address to determine 86045f94abcSMaksim Panchenko // the set boundaries. 86145f94abcSMaksim Panchenko // 86245f94abcSMaksim Panchenko // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets 86345f94abcSMaksim Panchenko // we wouldn't have to build our own sorted list for the quick lookup. 86445f94abcSMaksim Panchenko if (AbbrevSetOffsets.empty()) { 8651c2f4bbeSAlexander Yermolovich for_each( 86645f94abcSMaksim Panchenko *Unit.getContext().getDebugAbbrev(), 86745f94abcSMaksim Panchenko [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) { 86845f94abcSMaksim Panchenko AbbrevSetOffsets.push_back(P.first); 86945f94abcSMaksim Panchenko }); 8701c2f4bbeSAlexander Yermolovich sort(AbbrevSetOffsets); 87145f94abcSMaksim Panchenko } 8721c2f4bbeSAlexander Yermolovich auto It = upper_bound(AbbrevSetOffsets, StartOffset); 87345f94abcSMaksim Panchenko const uint64_t EndOffset = 87445f94abcSMaksim Panchenko It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; 875a34c753fSRafael Auler AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); 87645f94abcSMaksim Panchenko } else { 87745f94abcSMaksim Panchenko // For DWO unit outside of DWP, we expect the entire section to hold 87845f94abcSMaksim Panchenko // abbreviations for this unit only. 87945f94abcSMaksim Panchenko AbbrevContents = AbbrevSectionContents; 880a34c753fSRafael Auler } 881a34c753fSRafael Auler 8829f3f9d19SAlexander Yermolovich if (!hashAndAddAbbrev(AbbrevContents)) { 883a34c753fSRafael Auler OS.reserveExtraSpace(AbbrevContents.size()); 884a34c753fSRafael Auler OS << AbbrevContents; 8859f3f9d19SAlexander Yermolovich } 886a34c753fSRafael Auler return; 887a34c753fSRafael Auler } 888a34c753fSRafael Auler 889a34c753fSRafael Auler for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { 890a34c753fSRafael Auler const DWARFAbbreviationDeclaration &Abbrev = *I; 891a34c753fSRafael Auler auto Patch = UnitPatches.find(&Abbrev); 892a34c753fSRafael Auler 893a34c753fSRafael Auler encodeULEB128(Abbrev.getCode(), OS); 894a34c753fSRafael Auler encodeULEB128(Abbrev.getTag(), OS); 895a34c753fSRafael Auler encodeULEB128(Abbrev.hasChildren(), OS); 896a34c753fSRafael Auler for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : 897a34c753fSRafael Auler Abbrev.attributes()) { 898a34c753fSRafael Auler if (Patch != UnitPatches.end()) { 899a34c753fSRafael Auler bool Patched = false; 900a34c753fSRafael Auler // Patches added later take a precedence over earlier ones. 901a34c753fSRafael Auler for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E; 902a34c753fSRafael Auler ++I) { 903a34c753fSRafael Auler if (I->OldAttr != AttrSpec.Attr) 904a34c753fSRafael Auler continue; 905a34c753fSRafael Auler 906a34c753fSRafael Auler encodeULEB128(I->NewAttr, OS); 907a34c753fSRafael Auler encodeULEB128(I->NewAttrForm, OS); 908a34c753fSRafael Auler Patched = true; 909a34c753fSRafael Auler break; 910a34c753fSRafael Auler } 911a34c753fSRafael Auler if (Patched) 912a34c753fSRafael Auler continue; 913a34c753fSRafael Auler } 914a34c753fSRafael Auler 915a34c753fSRafael Auler encodeULEB128(AttrSpec.Attr, OS); 916a34c753fSRafael Auler encodeULEB128(AttrSpec.Form, OS); 917a34c753fSRafael Auler if (AttrSpec.isImplicitConst()) 918a34c753fSRafael Auler encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); 919a34c753fSRafael Auler } 920bd1ebe9dSAlexander Yermolovich const auto Entries = AbbrevEntries.find(&Abbrev); 921bd1ebe9dSAlexander Yermolovich // Adding new Abbrevs for inserted entries. 922bd1ebe9dSAlexander Yermolovich if (Entries != AbbrevEntries.end()) { 923bd1ebe9dSAlexander Yermolovich for (const AbbrevEntry &Entry : Entries->second) { 924bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Attr, OS); 925bd1ebe9dSAlexander Yermolovich encodeULEB128(Entry.Form, OS); 926bd1ebe9dSAlexander Yermolovich } 927bd1ebe9dSAlexander Yermolovich } 928a34c753fSRafael Auler encodeULEB128(0, OS); 929a34c753fSRafael Auler encodeULEB128(0, OS); 930a34c753fSRafael Auler } 931a34c753fSRafael Auler encodeULEB128(0, OS); 9329f3f9d19SAlexander Yermolovich 9339f3f9d19SAlexander Yermolovich hashAndAddAbbrev(OS.str()); 934a34c753fSRafael Auler } 935a34c753fSRafael Auler 936a34c753fSRafael Auler std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() { 9379f3f9d19SAlexander Yermolovich // Used to create determinism for writing out abbrevs. 9389f3f9d19SAlexander Yermolovich std::vector<AbbrevData *> Abbrevs; 93945f94abcSMaksim Panchenko if (DWOId) { 94045f94abcSMaksim Panchenko // We expect abbrev_offset to always be zero for DWO units as there 94145f94abcSMaksim Panchenko // should be one CU per DWO, and TUs should share the same abbreviation 94245f94abcSMaksim Panchenko // set with the CU. 9431417f607SAlexander Yermolovich // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so 9441417f607SAlexander Yermolovich // can be none zero. Thus we are skipping the check for DWP. 94545f94abcSMaksim Panchenko bool IsDWP = !Context.getCUIndex().getRows().empty(); 9461417f607SAlexander Yermolovich if (!IsDWP) { 94745f94abcSMaksim Panchenko for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) { 94845f94abcSMaksim Panchenko if (Unit->getAbbreviationsOffset() != 0) { 94945f94abcSMaksim Panchenko errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " 95045f94abcSMaksim Panchenko "Unable to update debug info.\n"; 95145f94abcSMaksim Panchenko exit(1); 95245f94abcSMaksim Panchenko } 95345f94abcSMaksim Panchenko } 95445f94abcSMaksim Panchenko } 95545f94abcSMaksim Panchenko 9569f3f9d19SAlexander Yermolovich DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); 95745f94abcSMaksim Panchenko // Issue abbreviations for the DWO CU only. 95845f94abcSMaksim Panchenko addUnitAbbreviations(*Unit); 9599f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit]; 9609f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 9619f3f9d19SAlexander Yermolovich } else { 9629f3f9d19SAlexander Yermolovich Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); 9639f3f9d19SAlexander Yermolovich std::unordered_set<AbbrevData *> ProcessedAbbrevs; 9649f3f9d19SAlexander Yermolovich // Add abbreviations from compile and type non-DWO units. 9659f3f9d19SAlexander Yermolovich for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) { 9669f3f9d19SAlexander Yermolovich addUnitAbbreviations(*Unit); 9679f3f9d19SAlexander Yermolovich AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; 9689f3f9d19SAlexander Yermolovich if (!ProcessedAbbrevs.insert(Abbrev).second) 9699f3f9d19SAlexander Yermolovich continue; 9709f3f9d19SAlexander Yermolovich Abbrevs.push_back(Abbrev); 9719f3f9d19SAlexander Yermolovich } 97245f94abcSMaksim Panchenko } 97345f94abcSMaksim Panchenko 974a34c753fSRafael Auler DebugBufferVector ReturnBuffer; 975a34c753fSRafael Auler // Pre-calculate the total size of abbrev section. 976a34c753fSRafael Auler uint64_t Size = 0; 9779f3f9d19SAlexander Yermolovich for (const AbbrevData *UnitData : Abbrevs) 9789f3f9d19SAlexander Yermolovich Size += UnitData->Buffer->size(); 9799f3f9d19SAlexander Yermolovich 980a34c753fSRafael Auler ReturnBuffer.reserve(Size); 981a34c753fSRafael Auler 982a34c753fSRafael Auler uint64_t Pos = 0; 9839f3f9d19SAlexander Yermolovich for (AbbrevData *UnitData : Abbrevs) { 9849f3f9d19SAlexander Yermolovich ReturnBuffer.append(*UnitData->Buffer); 9859f3f9d19SAlexander Yermolovich UnitData->Offset = Pos; 9869f3f9d19SAlexander Yermolovich Pos += UnitData->Buffer->size(); 987a34c753fSRafael Auler 9889f3f9d19SAlexander Yermolovich UnitData->Buffer.reset(); 9899f3f9d19SAlexander Yermolovich UnitData->Stream.reset(); 990a34c753fSRafael Auler } 991a34c753fSRafael Auler 992a34c753fSRafael Auler return std::make_unique<DebugBufferVector>(ReturnBuffer); 993a34c753fSRafael Auler } 994a34c753fSRafael Auler 995a34c753fSRafael Auler static void emitDwarfSetLineAddrAbs(MCStreamer &OS, 996a34c753fSRafael Auler MCDwarfLineTableParams Params, 997a34c753fSRafael Auler int64_t LineDelta, uint64_t Address, 998a34c753fSRafael Auler int PointerSize) { 999a34c753fSRafael Auler // emit the sequence to set the address 1000a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNS_extended_op, 1); 1001a34c753fSRafael Auler OS.emitULEB128IntValue(PointerSize + 1); 1002a34c753fSRafael Auler OS.emitIntValue(dwarf::DW_LNE_set_address, 1); 1003a34c753fSRafael Auler OS.emitIntValue(Address, PointerSize); 1004a34c753fSRafael Auler 1005a34c753fSRafael Auler // emit the sequence for the LineDelta (from 1) and a zero address delta. 1006a34c753fSRafael Auler MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0); 1007a34c753fSRafael Auler } 1008a34c753fSRafael Auler 1009a34c753fSRafael Auler static inline void emitBinaryDwarfLineTable( 1010a34c753fSRafael Auler MCStreamer *MCOS, MCDwarfLineTableParams Params, 1011a34c753fSRafael Auler const DWARFDebugLine::LineTable *Table, 1012a34c753fSRafael Auler const std::vector<DwarfLineTable::RowSequence> &InputSequences) { 1013a34c753fSRafael Auler if (InputSequences.empty()) 1014a34c753fSRafael Auler return; 1015a34c753fSRafael Auler 1016a34c753fSRafael Auler constexpr uint64_t InvalidAddress = UINT64_MAX; 1017a34c753fSRafael Auler unsigned FileNum = 1; 1018a34c753fSRafael Auler unsigned LastLine = 1; 1019a34c753fSRafael Auler unsigned Column = 0; 1020a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1021a34c753fSRafael Auler unsigned Isa = 0; 1022a34c753fSRafael Auler unsigned Discriminator = 0; 1023a34c753fSRafael Auler uint64_t LastAddress = InvalidAddress; 1024a34c753fSRafael Auler uint64_t PrevEndOfSequence = InvalidAddress; 1025a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1026a34c753fSRafael Auler 1027a34c753fSRafael Auler auto emitEndOfSequence = [&](uint64_t Address) { 1028a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress); 1029a34c753fSRafael Auler FileNum = 1; 1030a34c753fSRafael Auler LastLine = 1; 1031a34c753fSRafael Auler Column = 0; 1032a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1033a34c753fSRafael Auler Isa = 0; 1034a34c753fSRafael Auler Discriminator = 0; 1035a34c753fSRafael Auler LastAddress = InvalidAddress; 1036a34c753fSRafael Auler }; 1037a34c753fSRafael Auler 1038a34c753fSRafael Auler for (const DwarfLineTable::RowSequence &Sequence : InputSequences) { 1039a34c753fSRafael Auler const uint64_t SequenceStart = 1040a34c753fSRafael Auler Table->Rows[Sequence.FirstIndex].Address.Address; 1041a34c753fSRafael Auler 1042a34c753fSRafael Auler // Check if we need to mark the end of the sequence. 1043a34c753fSRafael Auler if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress && 1044a34c753fSRafael Auler PrevEndOfSequence != SequenceStart) { 1045a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1046a34c753fSRafael Auler } 1047a34c753fSRafael Auler 1048a34c753fSRafael Auler for (uint32_t RowIndex = Sequence.FirstIndex; 1049a34c753fSRafael Auler RowIndex <= Sequence.LastIndex; ++RowIndex) { 1050a34c753fSRafael Auler const DWARFDebugLine::Row &Row = Table->Rows[RowIndex]; 1051a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine; 1052a34c753fSRafael Auler const uint64_t Address = Row.Address.Address; 1053a34c753fSRafael Auler 1054a34c753fSRafael Auler if (FileNum != Row.File) { 1055a34c753fSRafael Auler FileNum = Row.File; 1056a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1057a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1058a34c753fSRafael Auler } 1059a34c753fSRafael Auler if (Column != Row.Column) { 1060a34c753fSRafael Auler Column = Row.Column; 1061a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1062a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1063a34c753fSRafael Auler } 1064a34c753fSRafael Auler if (Discriminator != Row.Discriminator && 1065a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1066a34c753fSRafael Auler Discriminator = Row.Discriminator; 1067a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1068a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1069a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1070a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1071a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1072a34c753fSRafael Auler } 1073a34c753fSRafael Auler if (Isa != Row.Isa) { 1074a34c753fSRafael Auler Isa = Row.Isa; 1075a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1076a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1077a34c753fSRafael Auler } 1078a34c753fSRafael Auler if (Row.IsStmt != Flags) { 1079a34c753fSRafael Auler Flags = Row.IsStmt; 1080a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1081a34c753fSRafael Auler } 1082a34c753fSRafael Auler if (Row.BasicBlock) 1083a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1084a34c753fSRafael Auler if (Row.PrologueEnd) 1085a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1086a34c753fSRafael Auler if (Row.EpilogueBegin) 1087a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1088a34c753fSRafael Auler 1089a34c753fSRafael Auler // The end of the sequence is not normal in the middle of the input 1090a34c753fSRafael Auler // sequence, but could happen, e.g. for assembly code. 1091a34c753fSRafael Auler if (Row.EndSequence) { 1092a34c753fSRafael Auler emitEndOfSequence(Address); 1093a34c753fSRafael Auler } else { 1094a34c753fSRafael Auler if (LastAddress == InvalidAddress) 1095a34c753fSRafael Auler emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address, 1096a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1097a34c753fSRafael Auler else 1098a34c753fSRafael Auler MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress); 1099a34c753fSRafael Auler 1100a34c753fSRafael Auler LastAddress = Address; 1101a34c753fSRafael Auler LastLine = Row.Line; 1102a34c753fSRafael Auler } 1103a34c753fSRafael Auler 1104a34c753fSRafael Auler Discriminator = 0; 1105a34c753fSRafael Auler } 1106a34c753fSRafael Auler PrevEndOfSequence = Sequence.EndAddress; 1107a34c753fSRafael Auler } 1108a34c753fSRafael Auler 1109a34c753fSRafael Auler // Finish with the end of the sequence. 1110a34c753fSRafael Auler if (LastAddress != InvalidAddress) 1111a34c753fSRafael Auler emitEndOfSequence(PrevEndOfSequence); 1112a34c753fSRafael Auler } 1113a34c753fSRafael Auler 1114a34c753fSRafael Auler // This function is similar to the one from MCDwarfLineTable, except it handles 1115a34c753fSRafael Auler // end-of-sequence entries differently by utilizing line entries with 1116a34c753fSRafael Auler // DWARF2_FLAG_END_SEQUENCE flag. 1117a34c753fSRafael Auler static inline void emitDwarfLineTable( 1118a34c753fSRafael Auler MCStreamer *MCOS, MCSection *Section, 1119a34c753fSRafael Auler const MCLineSection::MCDwarfLineEntryCollection &LineEntries) { 1120a34c753fSRafael Auler unsigned FileNum = 1; 1121a34c753fSRafael Auler unsigned LastLine = 1; 1122a34c753fSRafael Auler unsigned Column = 0; 1123a34c753fSRafael Auler unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1124a34c753fSRafael Auler unsigned Isa = 0; 1125a34c753fSRafael Auler unsigned Discriminator = 0; 1126a34c753fSRafael Auler MCSymbol *LastLabel = nullptr; 1127a34c753fSRafael Auler const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo(); 1128a34c753fSRafael Auler 1129a34c753fSRafael Auler // Loop through each MCDwarfLineEntry and encode the dwarf line number table. 1130a34c753fSRafael Auler for (const MCDwarfLineEntry &LineEntry : LineEntries) { 1131a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) { 1132a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(), 1133a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1134a34c753fSRafael Auler FileNum = 1; 1135a34c753fSRafael Auler LastLine = 1; 1136a34c753fSRafael Auler Column = 0; 1137a34c753fSRafael Auler Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; 1138a34c753fSRafael Auler Isa = 0; 1139a34c753fSRafael Auler Discriminator = 0; 1140a34c753fSRafael Auler LastLabel = nullptr; 1141a34c753fSRafael Auler continue; 1142a34c753fSRafael Auler } 1143a34c753fSRafael Auler 1144a34c753fSRafael Auler int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine; 1145a34c753fSRafael Auler 1146a34c753fSRafael Auler if (FileNum != LineEntry.getFileNum()) { 1147a34c753fSRafael Auler FileNum = LineEntry.getFileNum(); 1148a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_file); 1149a34c753fSRafael Auler MCOS->emitULEB128IntValue(FileNum); 1150a34c753fSRafael Auler } 1151a34c753fSRafael Auler if (Column != LineEntry.getColumn()) { 1152a34c753fSRafael Auler Column = LineEntry.getColumn(); 1153a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_column); 1154a34c753fSRafael Auler MCOS->emitULEB128IntValue(Column); 1155a34c753fSRafael Auler } 1156a34c753fSRafael Auler if (Discriminator != LineEntry.getDiscriminator() && 1157a34c753fSRafael Auler MCOS->getContext().getDwarfVersion() >= 4) { 1158a34c753fSRafael Auler Discriminator = LineEntry.getDiscriminator(); 1159a34c753fSRafael Auler unsigned Size = getULEB128Size(Discriminator); 1160a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_extended_op); 1161a34c753fSRafael Auler MCOS->emitULEB128IntValue(Size + 1); 1162a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNE_set_discriminator); 1163a34c753fSRafael Auler MCOS->emitULEB128IntValue(Discriminator); 1164a34c753fSRafael Auler } 1165a34c753fSRafael Auler if (Isa != LineEntry.getIsa()) { 1166a34c753fSRafael Auler Isa = LineEntry.getIsa(); 1167a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_isa); 1168a34c753fSRafael Auler MCOS->emitULEB128IntValue(Isa); 1169a34c753fSRafael Auler } 1170a34c753fSRafael Auler if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) { 1171a34c753fSRafael Auler Flags = LineEntry.getFlags(); 1172a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_negate_stmt); 1173a34c753fSRafael Auler } 1174a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK) 1175a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_basic_block); 1176a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END) 1177a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end); 1178a34c753fSRafael Auler if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN) 1179a34c753fSRafael Auler MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin); 1180a34c753fSRafael Auler 1181a34c753fSRafael Auler MCSymbol *Label = LineEntry.getLabel(); 1182a34c753fSRafael Auler 1183a34c753fSRafael Auler // At this point we want to emit/create the sequence to encode the delta 1184a34c753fSRafael Auler // in line numbers and the increment of the address from the previous 1185a34c753fSRafael Auler // Label and the current Label. 1186a34c753fSRafael Auler MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label, 1187a34c753fSRafael Auler AsmInfo->getCodePointerSize()); 1188a34c753fSRafael Auler Discriminator = 0; 1189a34c753fSRafael Auler LastLine = LineEntry.getLine(); 1190a34c753fSRafael Auler LastLabel = Label; 1191a34c753fSRafael Auler } 1192a34c753fSRafael Auler 1193a34c753fSRafael Auler assert(LastLabel == nullptr && "end of sequence expected"); 1194a34c753fSRafael Auler } 1195a34c753fSRafael Auler 1196a34c753fSRafael Auler void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 1197b73c87bcSMaksim Panchenko Optional<MCDwarfLineStr> &LineStr, 1198b73c87bcSMaksim Panchenko BinaryContext &BC) const { 1199a34c753fSRafael Auler if (!RawData.empty()) { 1200a34c753fSRafael Auler assert(MCLineSections.getMCLineEntries().empty() && 1201a34c753fSRafael Auler InputSequences.empty() && 1202a34c753fSRafael Auler "cannot combine raw data with new line entries"); 1203a34c753fSRafael Auler MCOS->emitLabel(getLabel()); 1204a34c753fSRafael Auler MCOS->emitBytes(RawData); 1205a34c753fSRafael Auler 1206b73c87bcSMaksim Panchenko // Emit fake relocation for RuntimeDyld to always allocate the section. 1207b73c87bcSMaksim Panchenko // 1208b73c87bcSMaksim Panchenko // FIXME: remove this once RuntimeDyld stops skipping allocatable sections 1209b73c87bcSMaksim Panchenko // without relocations. 1210b73c87bcSMaksim Panchenko MCOS->emitRelocDirective( 1211b73c87bcSMaksim Panchenko *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE", 1212b73c87bcSMaksim Panchenko MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI); 1213b73c87bcSMaksim Panchenko 1214a34c753fSRafael Auler return; 1215a34c753fSRafael Auler } 1216a34c753fSRafael Auler 1217a34c753fSRafael Auler MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second; 1218a34c753fSRafael Auler 1219a34c753fSRafael Auler // Put out the line tables. 1220a34c753fSRafael Auler for (const auto &LineSec : MCLineSections.getMCLineEntries()) 1221a34c753fSRafael Auler emitDwarfLineTable(MCOS, LineSec.first, LineSec.second); 1222a34c753fSRafael Auler 1223a34c753fSRafael Auler // Emit line tables for the original code. 1224a34c753fSRafael Auler emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences); 1225a34c753fSRafael Auler 1226a34c753fSRafael Auler // This is the end of the section, so set the value of the symbol at the end 1227a34c753fSRafael Auler // of this section (that was used in a previous expression). 1228a34c753fSRafael Auler MCOS->emitLabel(LineEndSym); 1229a34c753fSRafael Auler } 1230a34c753fSRafael Auler 1231a34c753fSRafael Auler void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) { 1232a34c753fSRafael Auler MCAssembler &Assembler = 1233a34c753fSRafael Auler static_cast<MCObjectStreamer *>(&Streamer)->getAssembler(); 1234a34c753fSRafael Auler 1235a34c753fSRafael Auler MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams(); 1236a34c753fSRafael Auler 1237a34c753fSRafael Auler auto &LineTables = BC.getDwarfLineTables(); 1238a34c753fSRafael Auler 1239a34c753fSRafael Auler // Bail out early so we don't switch to the debug_line section needlessly and 1240a34c753fSRafael Auler // in doing so create an unnecessary (if empty) section. 1241a34c753fSRafael Auler if (LineTables.empty()) 1242a34c753fSRafael Auler return; 1243a34c753fSRafael Auler 1244a34c753fSRafael Auler // In a v5 non-split line table, put the strings in a separate section. 1245a34c753fSRafael Auler Optional<MCDwarfLineStr> LineStr(None); 1246a34c753fSRafael Auler if (BC.Ctx->getDwarfVersion() >= 5) 1247a34c753fSRafael Auler LineStr = MCDwarfLineStr(*BC.Ctx); 1248a34c753fSRafael Auler 1249a34c753fSRafael Auler // Switch to the section where the table will be emitted into. 1250a34c753fSRafael Auler Streamer.SwitchSection(BC.MOFI->getDwarfLineSection()); 1251a34c753fSRafael Auler 1252a34c753fSRafael Auler // Handle the rest of the Compile Units. 1253a34c753fSRafael Auler for (auto &CUIDTablePair : LineTables) { 1254b73c87bcSMaksim Panchenko CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC); 1255a34c753fSRafael Auler } 1256a34c753fSRafael Auler } 1257a34c753fSRafael Auler 1258a34c753fSRafael Auler } // namespace bolt 1259a34c753fSRafael Auler } // namespace llvm 1260