1241 lines · cpp
1//===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements functions and classes for handling debug info.10//11//===----------------------------------------------------------------------===//12 13#include "bolt/Core/DebugData.h"14#include "bolt/Core/BinaryContext.h"15#include "bolt/Core/DIEBuilder.h"16#include "bolt/Utils/Utils.h"17#include "llvm/BinaryFormat/Dwarf.h"18#include "llvm/CodeGen/DIE.h"19#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"20#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"21#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"22#include "llvm/MC/MCAssembler.h"23#include "llvm/MC/MCContext.h"24#include "llvm/MC/MCObjectStreamer.h"25#include "llvm/Support/CommandLine.h"26#include "llvm/Support/EndianStream.h"27#include "llvm/Support/LEB128.h"28#include "llvm/Support/SHA1.h"29#include <algorithm>30#include <cassert>31#include <cstdint>32#include <functional>33#include <memory>34#include <optional>35#include <unordered_map>36#include <vector>37 38#define DEBUG_TYPE "bolt-debug-info"39 40namespace opts {41extern llvm::cl::opt<unsigned> Verbosity;42} // namespace opts43 44namespace llvm {45class MCSymbol;46 47namespace bolt {48 49static void replaceLocValbyForm(DIEBuilder &DIEBldr, DIE &Die, DIEValue DIEVal,50 dwarf::Form Format, uint64_t NewVal) {51 if (Format == dwarf::DW_FORM_loclistx)52 DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,53 DIELocList(NewVal));54 else55 DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,56 DIEInteger(NewVal));57}58 59std::optional<AttrInfo>60findAttributeInfo(const DWARFDie DIE,61 const DWARFAbbreviationDeclaration *AbbrevDecl,62 uint32_t Index) {63 const DWARFUnit &U = *DIE.getDwarfUnit();64 uint64_t Offset =65 AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);66 std::optional<DWARFFormValue> Value =67 AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);68 if (!Value)69 return std::nullopt;70 // AttributeSpec71 const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =72 AbbrevDecl->attributes().begin() + Index;73 uint32_t ValSize = 0;74 std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);75 if (ValSizeOpt) {76 ValSize = static_cast<uint32_t>(*ValSizeOpt);77 } else {78 DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();79 uint64_t NewOffset = Offset;80 DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,81 U.getFormParams());82 // This includes entire size of the entry, which might not be just the83 // encoding part. For example for DW_AT_loc it will include expression84 // location.85 ValSize = NewOffset - Offset;86 }87 return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};88}89 90std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,91 dwarf::Attribute Attr) {92 if (!DIE.isValid())93 return std::nullopt;94 const DWARFAbbreviationDeclaration *AbbrevDecl =95 DIE.getAbbreviationDeclarationPtr();96 if (!AbbrevDecl)97 return std::nullopt;98 std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);99 if (!Index)100 return std::nullopt;101 return findAttributeInfo(DIE, AbbrevDecl, *Index);102}103 104[[maybe_unused]]105static void printLE64(const std::string &S) {106 for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {107 errs() << Twine::utohexstr(S[I]);108 errs() << Twine::utohexstr((int8_t)S[I]);109 }110 errs() << "\n";111}112 113// Writes address ranges to Writer as pairs of 64-bit (address, size).114// If RelativeRange is true, assumes the address range to be written must be of115// the form (begin address, range size), otherwise (begin address, end address).116// Terminates the list by writing a pair of two zeroes.117// Returns the number of written bytes.118static uint64_t119writeAddressRanges(raw_svector_ostream &Stream,120 const DebugAddressRangesVector &AddressRanges,121 const bool WriteRelativeRanges = false) {122 for (const DebugAddressRange &Range : AddressRanges) {123 support::endian::write(Stream, Range.LowPC, llvm::endianness::little);124 support::endian::write(125 Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,126 llvm::endianness::little);127 }128 // Finish with 0 entries.129 support::endian::write(Stream, 0ULL, llvm::endianness::little);130 support::endian::write(Stream, 0ULL, llvm::endianness::little);131 return AddressRanges.size() * 16 + 16;132}133 134DebugRangesSectionWriter::DebugRangesSectionWriter() {135 RangesBuffer = std::make_unique<DebugBufferVector>();136 RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);137 138 Kind = RangesWriterKind::DebugRangesWriter;139}140 141void DebugRangesSectionWriter::initSection() {142 // Adds an empty range to the buffer.143 writeAddressRanges(*RangesStream, DebugAddressRangesVector{});144}145 146uint64_t DebugRangesSectionWriter::addRanges(147 DebugAddressRangesVector &&Ranges,148 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {149 if (Ranges.empty())150 return getEmptyRangesOffset();151 152 const auto RI = CachedRanges.find(Ranges);153 if (RI != CachedRanges.end())154 return RI->second;155 156 const uint64_t EntryOffset = addRanges(Ranges);157 CachedRanges.emplace(std::move(Ranges), EntryOffset);158 159 return EntryOffset;160}161 162uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {163 if (Ranges.empty())164 return getEmptyRangesOffset();165 166 // Reading the SectionOffset and updating it should be atomic to guarantee167 // unique and correct offsets in patches.168 std::lock_guard<std::mutex> Lock(WriterMutex);169 const uint32_t EntryOffset = RangesBuffer->size();170 writeAddressRanges(*RangesStream, Ranges);171 172 return EntryOffset;173}174 175uint64_t DebugRangesSectionWriter::getSectionOffset() {176 std::lock_guard<std::mutex> Lock(WriterMutex);177 return RangesBuffer->size();178}179 180void DebugRangesSectionWriter::appendToRangeBuffer(181 const DebugBufferVector &CUBuffer) {182 *RangesStream << CUBuffer;183}184 185uint64_t DebugRangeListsSectionWriter::addRanges(186 DebugAddressRangesVector &&Ranges,187 std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {188 return addRanges(Ranges);189}190 191struct LocListsRangelistsHeader {192 UnitLengthType UnitLength; // Size of loclist entries section, not including193 // size of header.194 VersionType Version;195 AddressSizeType AddressSize;196 SegmentSelectorType SegmentSelector;197 OffsetEntryCountType OffsetEntryCount;198};199 200static std::unique_ptr<DebugBufferVector>201getDWARF5Header(const LocListsRangelistsHeader &Header) {202 std::unique_ptr<DebugBufferVector> HeaderBuffer =203 std::make_unique<DebugBufferVector>();204 std::unique_ptr<raw_svector_ostream> HeaderStream =205 std::make_unique<raw_svector_ostream>(*HeaderBuffer);206 207 // 7.29 length of the set of entries for this compilation unit, not including208 // the length field itself209 const uint32_t HeaderSize =210 getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);211 212 support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,213 llvm::endianness::little);214 support::endian::write(*HeaderStream, Header.Version,215 llvm::endianness::little);216 support::endian::write(*HeaderStream, Header.AddressSize,217 llvm::endianness::little);218 support::endian::write(*HeaderStream, Header.SegmentSelector,219 llvm::endianness::little);220 support::endian::write(*HeaderStream, Header.OffsetEntryCount,221 llvm::endianness::little);222 return HeaderBuffer;223}224 225struct OffsetEntry {226 uint32_t Index;227 uint32_t StartOffset;228 uint32_t EndOffset;229};230template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>231static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,232 DebugAddrWriter &AddrWriter, DWARFUnit &CU,233 uint32_t &Index, const ListEntry BaseAddressx,234 const ListEntry OffsetPair,235 const std::function<void(uint32_t)> &Func) {236 if (Entries.size() < 2)237 return false;238 uint64_t Base = Entries[Index].LowPC;239 std::vector<OffsetEntry> Offsets;240 uint8_t TempBuffer[64];241 while (Index < Entries.size()) {242 const DebugAddressEntry &Entry = Entries[Index];243 if (Entry.LowPC == 0)244 break;245 // In case rnglists or loclists are not sorted.246 if (Base > Entry.LowPC)247 break;248 uint32_t StartOffset = Entry.LowPC - Base;249 uint32_t EndOffset = Entry.HighPC - Base;250 if (encodeULEB128(EndOffset, TempBuffer) > 2)251 break;252 Offsets.push_back({Index, StartOffset, EndOffset});253 ++Index;254 }255 256 if (Offsets.size() < 2) {257 Index -= Offsets.size();258 return false;259 }260 261 support::endian::write(OS, static_cast<uint8_t>(BaseAddressx),262 llvm::endianness::little);263 uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU);264 encodeULEB128(BaseIndex, OS);265 for (auto &OffsetEntry : Offsets) {266 support::endian::write(OS, static_cast<uint8_t>(OffsetPair),267 llvm::endianness::little);268 encodeULEB128(OffsetEntry.StartOffset, OS);269 encodeULEB128(OffsetEntry.EndOffset, OS);270 Func(OffsetEntry.Index);271 }272 return true;273}274 275uint64_t276DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {277 std::lock_guard<std::mutex> Lock(WriterMutex);278 279 RangeEntries.push_back(CurrentOffset);280 std::sort(281 Ranges.begin(), Ranges.end(),282 [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {283 return R1.LowPC < R2.LowPC;284 });285 for (unsigned I = 0; I < Ranges.size();) {286 if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,287 DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU,288 I, dwarf::DW_RLE_base_addressx,289 dwarf::DW_RLE_offset_pair,290 [](uint32_t Index) -> void {}))291 continue;292 293 const DebugAddressRange &Range = Ranges[I];294 support::endian::write(*CUBodyStream,295 static_cast<uint8_t>(dwarf::DW_RLE_startx_length),296 llvm::endianness::little);297 uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU);298 encodeULEB128(Index, *CUBodyStream);299 encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);300 ++I;301 }302 303 support::endian::write(*CUBodyStream,304 static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),305 llvm::endianness::little);306 CurrentOffset = CUBodyBuffer->size();307 return RangeEntries.size() - 1;308}309 310void DebugRangeListsSectionWriter::finalizeSection() {311 std::unique_ptr<DebugBufferVector> CUArrayBuffer =312 std::make_unique<DebugBufferVector>();313 std::unique_ptr<raw_svector_ostream> CUArrayStream =314 std::make_unique<raw_svector_ostream>(*CUArrayBuffer);315 constexpr uint32_t SizeOfArrayEntry = 4;316 const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;317 for (uint32_t Offset : RangeEntries)318 support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,319 llvm::endianness::little);320 321 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(322 {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer->size()), 5, 8,323 0, static_cast<uint32_t>(RangeEntries.size())});324 *RangesStream << *Header;325 *RangesStream << *CUArrayBuffer;326 *RangesStream << *CUBodyBuffer;327}328 329void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {330 CUBodyBuffer = std::make_unique<DebugBufferVector>();331 CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);332 RangeEntries.clear();333 CurrentOffset = 0;334 CU = &Unit;335}336 337void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,338 DebugAddressRangesVector &&Ranges) {339 std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);340 CUAddressRanges.emplace(CUOffset, std::move(Ranges));341}342 343void DebugARangesSectionWriter::writeARangesSection(344 raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {345 // For reference on the format of the .debug_aranges section, see the DWARF4346 // specification, section 6.1.4 Lookup by Address347 // http://www.dwarfstd.org/doc/DWARF4.pdf348 for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {349 const uint64_t Offset = CUOffsetAddressRangesPair.first;350 const DebugAddressRangesVector &AddressRanges =351 CUOffsetAddressRangesPair.second;352 353 // Emit header.354 355 // Size of this set: 8 (size of the header) + 4 (padding after header)356 // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra357 // pair of uint64_t's for the terminating, zero-length range.358 // Does not include size field itself.359 uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);360 361 // Header field #1: set size.362 support::endian::write(RangesStream, Size, llvm::endianness::little);363 364 // Header field #2: version number, 2 as per the specification.365 support::endian::write(RangesStream, static_cast<uint16_t>(2),366 llvm::endianness::little);367 368 assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");369 // Header field #3: debug info offset of the correspondent compile unit.370 support::endian::write(371 RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),372 llvm::endianness::little);373 374 // Header field #4: address size.375 // 8 since we only write ELF64 binaries for now.376 RangesStream << char(8);377 378 // Header field #5: segment size of target architecture.379 RangesStream << char(0);380 381 // Padding before address table - 4 bytes in the 64-bit-pointer case.382 support::endian::write(RangesStream, static_cast<uint32_t>(0),383 llvm::endianness::little);384 385 writeAddressRanges(RangesStream, AddressRanges, true);386 }387}388 389DebugAddrWriter::DebugAddrWriter(BinaryContext *BC,390 const uint8_t AddressByteSize)391 : BC(BC), AddressByteSize(AddressByteSize) {392 Buffer = std::make_unique<AddressSectionBuffer>();393 AddressStream = std::make_unique<raw_svector_ostream>(*Buffer);394}395 396void DebugAddrWriter::AddressForDWOCU::dump() {397 std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),398 indexToAdddessEnd());399 // Sorting address in increasing order of indices.400 llvm::sort(SortedMap, llvm::less_first());401 for (auto &Pair : SortedMap)402 dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";403}404uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {405 std::lock_guard<std::mutex> Lock(WriterMutex);406 auto Entry = Map.find(Address);407 if (Entry == Map.end()) {408 auto Index = Map.getNextIndex();409 Entry = Map.insert(Address, Index).first;410 }411 return Entry->second;412}413 414static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter,415 DWARFUnit &CU, const uint64_t Offset) {416 DIE *Die = DIEBlder.getUnitDIEbyUnit(CU);417 DIEValue GnuAddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_GNU_addr_base);418 DIEValue AddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_addr_base);419 dwarf::Form BaseAttrForm;420 dwarf::Attribute BaseAttr;421 // For cases where Skeleton CU does not have DW_AT_GNU_addr_base422 if (!GnuAddrBaseAttrInfo && CU.getVersion() < 5)423 return;424 425 if (GnuAddrBaseAttrInfo) {426 BaseAttrForm = GnuAddrBaseAttrInfo.getForm();427 BaseAttr = GnuAddrBaseAttrInfo.getAttribute();428 }429 430 if (AddrBaseAttrInfo) {431 BaseAttrForm = AddrBaseAttrInfo.getForm();432 BaseAttr = AddrBaseAttrInfo.getAttribute();433 }434 435 if (GnuAddrBaseAttrInfo || AddrBaseAttrInfo) {436 DIEBlder.replaceValue(Die, BaseAttr, BaseAttrForm, DIEInteger(Offset));437 } else if (CU.getVersion() >= 5) {438 // A case where we were not using .debug_addr section, but after update439 // now using it.440 DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,441 DIEInteger(Offset));442 }443}444 445void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,446 const uint64_t Offset) {447 updateAddressBase(DIEBlder, *this, CU, Offset);448}449 450std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) {451 if (Map.begin() == Map.end())452 return std::nullopt;453 std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),454 Map.indexToAdddessEnd());455 // Sorting address in increasing order of indices.456 llvm::sort(SortedMap, llvm::less_first());457 458 uint32_t Counter = 0;459 auto WriteAddress = [&](uint64_t Address) -> void {460 ++Counter;461 switch (AddressByteSize) {462 default:463 assert(false && "Address Size is invalid.");464 break;465 case 4:466 support::endian::write(*AddressStream, static_cast<uint32_t>(Address),467 llvm::endianness::little);468 break;469 case 8:470 support::endian::write(*AddressStream, Address, llvm::endianness::little);471 break;472 }473 };474 475 for (const IndexAddressPair &Val : SortedMap) {476 while (Val.first > Counter)477 WriteAddress(0);478 WriteAddress(Val.second);479 }480 return std::nullopt;481}482 483void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,484 const uint64_t Offset) {485 /// Header for DWARF5 has size 8, so we add it to the offset.486 updateAddressBase(DIEBlder, *this, CU, Offset + HeaderSize);487}488 489DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets;490 491std::optional<uint64_t>492DebugAddrWriterDwarf5::finalize(const size_t BufferSize) {493 // Need to layout all sections within .debug_addr494 // Within each section sort Address by index.495 const endianness Endian = BC->DwCtx->isLittleEndian()496 ? llvm::endianness::little497 : llvm::endianness::big;498 const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();499 DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec,500 Endian == llvm::endianness::little, 0);501 DWARFDebugAddrTable AddrTable;502 DIDumpOptions DumpOpts;503 // A case where CU has entry in .debug_addr, but we don't modify addresses504 // for it.505 if (Map.begin() == Map.end()) {506 if (!AddrOffsetSectionBase)507 return std::nullopt;508 // Address base offset is to the first entry.509 // The size of header is 8 bytes.510 uint64_t Offset = *AddrOffsetSectionBase - HeaderSize;511 auto Iter = UnmodifiedAddressOffsets.find(Offset);512 if (Iter != UnmodifiedAddressOffsets.end())513 return Iter->second;514 UnmodifiedAddressOffsets[Offset] = BufferSize;515 if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize,516 DumpOpts.WarningHandler)) {517 DumpOpts.RecoverableErrorHandler(std::move(Err));518 return std::nullopt;519 }520 uint32_t Index = 0;521 for (uint64_t Addr : AddrTable.getAddressEntries())522 Map.insert(Addr, Index++);523 }524 525 std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),526 Map.indexToAdddessEnd());527 // Sorting address in increasing order of indices.528 llvm::sort(SortedMap, llvm::less_first());529 // Writing out Header530 const uint32_t Length = SortedMap.size() * AddressByteSize + 4;531 support::endian::write(*AddressStream, Length, Endian);532 support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);533 support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize),534 Endian);535 support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);536 537 uint32_t Counter = 0;538 auto writeAddress = [&](uint64_t Address) -> void {539 ++Counter;540 switch (AddressByteSize) {541 default:542 llvm_unreachable("Address Size is invalid.");543 break;544 case 4:545 support::endian::write(*AddressStream, static_cast<uint32_t>(Address),546 Endian);547 break;548 case 8:549 support::endian::write(*AddressStream, Address, Endian);550 break;551 }552 };553 554 for (const IndexAddressPair &Val : SortedMap) {555 while (Val.first > Counter)556 writeAddress(0);557 writeAddress(Val.second);558 }559 return std::nullopt;560}561 562void DebugLocWriter::init() {563 LocBuffer = std::make_unique<DebugBufferVector>();564 LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);565 // Writing out empty location list to which all references to empty location566 // lists will point.567 if (!LocSectionOffset && DwarfVersion < 5) {568 const char Zeroes[16] = {0};569 *LocStream << StringRef(Zeroes, 16);570 LocSectionOffset += 16;571 }572}573 574uint32_t DebugLocWriter::LocSectionOffset = 0;575void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,576 DebugLocationsVector &LocList) {577 if (LocList.empty()) {578 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),579 DebugLocWriter::EmptyListOffset);580 return;581 }582 // Since there is a separate DebugLocWriter for each thread,583 // we don't need a lock to read the SectionOffset and update it.584 const uint32_t EntryOffset = LocSectionOffset;585 586 for (const DebugLocationEntry &Entry : LocList) {587 support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),588 llvm::endianness::little);589 support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),590 llvm::endianness::little);591 support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),592 llvm::endianness::little);593 *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),594 Entry.Expr.size());595 LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();596 }597 LocStream->write_zeros(16);598 LocSectionOffset += 16;599 LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen600 // use601 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);602}603 604std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {605 return std::move(LocBuffer);606}607 608// DWARF 4: 2.6.2609void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}610 611static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {612 support::endian::write(Stream, static_cast<uint32_t>(4),613 llvm::endianness::little);614 support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),615 llvm::endianness::little);616 617 const char Zeroes[16] = {0};618 Stream << StringRef(Zeroes, 16);619 encodeULEB128(0, Stream);620 support::endian::write(Stream,621 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),622 llvm::endianness::little);623}624 625static void writeLegacyLocList(DIEValue &AttrInfo,626 DebugLocationsVector &LocList,627 DIEBuilder &DIEBldr, DIE &Die,628 DebugAddrWriter &AddrWriter,629 DebugBufferVector &LocBuffer, DWARFUnit &CU,630 raw_svector_ostream &LocStream) {631 if (LocList.empty()) {632 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),633 DebugLocWriter::EmptyListOffset);634 return;635 }636 637 const uint32_t EntryOffset = LocBuffer.size();638 for (const DebugLocationEntry &Entry : LocList) {639 support::endian::write(LocStream,640 static_cast<uint8_t>(dwarf::DW_LLE_startx_length),641 llvm::endianness::little);642 const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);643 encodeULEB128(Index, LocStream);644 645 support::endian::write(LocStream,646 static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),647 llvm::endianness::little);648 support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()),649 llvm::endianness::little);650 LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),651 Entry.Expr.size());652 }653 support::endian::write(LocStream,654 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),655 llvm::endianness::little);656 replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);657}658 659static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,660 DebugLocationsVector &LocList, DIE &Die,661 DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter,662 DebugBufferVector &LocBodyBuffer,663 std::vector<uint32_t> &RelativeLocListOffsets,664 DWARFUnit &CU,665 raw_svector_ostream &LocBodyStream) {666 667 replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,668 NumberOfEntries);669 670 RelativeLocListOffsets.push_back(LocBodyBuffer.size());671 ++NumberOfEntries;672 if (LocList.empty()) {673 writeEmptyListDwarf5(LocBodyStream);674 return;675 }676 677 auto writeExpression = [&](uint32_t Index) -> void {678 const DebugLocationEntry &Entry = LocList[Index];679 encodeULEB128(Entry.Expr.size(), LocBodyStream);680 LocBodyStream << StringRef(681 reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());682 };683 for (unsigned I = 0; I < LocList.size();) {684 if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,685 DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU,686 I, dwarf::DW_LLE_base_addressx,687 dwarf::DW_LLE_offset_pair,688 writeExpression))689 continue;690 691 const DebugLocationEntry &Entry = LocList[I];692 support::endian::write(LocBodyStream,693 static_cast<uint8_t>(dwarf::DW_LLE_startx_length),694 llvm::endianness::little);695 const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);696 encodeULEB128(Index, LocBodyStream);697 encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);698 writeExpression(I);699 ++I;700 }701 702 support::endian::write(LocBodyStream,703 static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),704 llvm::endianness::little);705}706 707void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,708 DIEValue &AttrInfo,709 DebugLocationsVector &LocList) {710 if (DwarfVersion < 5)711 writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer,712 CU, *LocStream);713 else714 writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,715 AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,716 *LocBodyStream);717}718 719uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;720void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) {721 if (LocBodyBuffer->empty()) {722 DIEValue LocListBaseAttrInfo =723 Die.findAttribute(dwarf::DW_AT_loclists_base);724 // Pointing to first one, because it doesn't matter. There are no uses of it725 // in this CU.726 if (!isSplitDwarf() && LocListBaseAttrInfo.getType())727 DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,728 LocListBaseAttrInfo.getForm(),729 DIEInteger(getDWARF5RngListLocListHeaderSize()));730 return;731 }732 733 std::unique_ptr<DebugBufferVector> LocArrayBuffer =734 std::make_unique<DebugBufferVector>();735 std::unique_ptr<raw_svector_ostream> LocArrayStream =736 std::make_unique<raw_svector_ostream>(*LocArrayBuffer);737 738 const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t);739 // Write out IndexArray740 for (uint32_t RelativeOffset : RelativeLocListOffsets)741 support::endian::write(742 *LocArrayStream,743 static_cast<uint32_t>(SizeOfArraySection + RelativeOffset),744 llvm::endianness::little);745 746 std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(747 {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer->size()), 5, 8,748 0, NumberOfEntries});749 *LocStream << *Header;750 *LocStream << *LocArrayBuffer;751 *LocStream << *LocBodyBuffer;752 753 if (!isSplitDwarf()) {754 DIEValue LocListBaseAttrInfo =755 Die.findAttribute(dwarf::DW_AT_loclists_base);756 if (LocListBaseAttrInfo.getType()) {757 DIEBldr.replaceValue(758 &Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(),759 DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize()));760 } else {761 DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,762 dwarf::DW_FORM_sec_offset,763 DIEInteger(LoclistBaseOffset + Header->size()));764 }765 LoclistBaseOffset += LocBuffer->size();766 }767 clearList(RelativeLocListOffsets);768 clearList(*LocArrayBuffer);769 clearList(*LocBodyBuffer);770}771 772void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {773 if (DwarfVersion >= 5)774 finalizeDWARF5(DIEBldr, Die);775}776 777static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {778 std::string LE64(ByteSize, 0);779 for (size_t I = 0; I < ByteSize; ++I) {780 LE64[I] = NewValue & 0xff;781 NewValue >>= 8;782 }783 return LE64;784}785 786void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,787 std::string &&NewValue,788 uint32_t OldValueSize) {789 Patches.emplace_back(Offset, std::move(NewValue));790}791 792void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {793 auto Str = std::string(1, Value);794 Patches.emplace_back(Offset, std::move(Str));795}796 797void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,798 size_t ByteSize) {799 Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));800}801 802void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,803 uint32_t OldValueSize) {804 std::string Buff;805 raw_string_ostream OS(Buff);806 encodeULEB128(Value, OS, OldValueSize);807 808 Patches.emplace_back(Offset, std::move(Buff));809}810 811void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {812 addLEPatch(Offset, NewValue, 8);813}814 815void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,816 uint32_t OldValueSize) {817 addLEPatch(Offset, NewValue, 4);818}819 820std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {821 std::string BinaryContentsStr = std::string(BinaryContents);822 for (const auto &Patch : Patches) {823 uint32_t Offset = Patch.first;824 const std::string &ByteSequence = Patch.second;825 assert(Offset + ByteSequence.size() <= BinaryContents.size() &&826 "Applied patch runs over binary size.");827 for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {828 BinaryContentsStr[Offset + I] = ByteSequence[I];829 }830 }831 return BinaryContentsStr;832}833 834void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) {835 if (Unit.getVersion() < 5)836 return;837 const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();838 const std::optional<StrOffsetsContributionDescriptor> &Contr =839 Unit.getStringOffsetsTableContribution();840 if (!Contr)841 return;842 const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();843 assert(DwarfOffsetByteSize == 4 &&844 "Dwarf String Offsets Byte Size is not supported.");845 StrOffsets.reserve(Contr->Size);846 for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)847 StrOffsets.push_back(support::endian::read32le(848 StrOffsetsSection.Data.data() + Contr->Base + Offset));849}850 851void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address,852 const DWARFUnit &Unit) {853 assert(DebugStrOffsetFinalized.count(Unit.getOffset()) == 0 &&854 "Cannot update address map since debug_str_offsets was already "855 "finalized for this CU.");856 IndexToAddressMap[Index] = Address;857 StrOffsetSectionWasModified = true;858}859 860void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,861 DIEBuilder &DIEBldr) {862 std::optional<AttrInfo> AttrVal =863 findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);864 if (!AttrVal && !Unit.isDWOUnit())865 return;866 std::optional<uint64_t> Val = std::nullopt;867 if (AttrVal) {868 Val = AttrVal->V.getAsSectionOffset();869 } else {870 if (!Unit.isDWOUnit())871 BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "872 "DW_AT_str_offsets_base Value not present\n";873 Val = 0;874 }875 DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);876 DIEValue StrListBaseAttrInfo =877 Die.findAttribute(dwarf::DW_AT_str_offsets_base);878 auto RetVal = ProcessedBaseOffsets.find(*Val);879 // Handling reuse of str-offsets section.880 if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {881 initialize(Unit);882 // Update String Offsets that were modified.883 for (const auto &Entry : IndexToAddressMap)884 StrOffsets[Entry.first] = Entry.second;885 // Writing out the header for each section.886 support::endian::write(*StrOffsetsStream,887 static_cast<uint32_t>(StrOffsets.size() * 4 + 4),888 llvm::endianness::little);889 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),890 llvm::endianness::little);891 support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),892 llvm::endianness::little);893 894 uint64_t BaseOffset = StrOffsetsBuffer->size();895 ProcessedBaseOffsets[*Val] = BaseOffset;896 if (StrListBaseAttrInfo.getType())897 DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,898 StrListBaseAttrInfo.getForm(),899 DIEInteger(BaseOffset));900 for (const uint32_t Offset : StrOffsets)901 support::endian::write(*StrOffsetsStream, Offset,902 llvm::endianness::little);903 } else {904 DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,905 StrListBaseAttrInfo.getForm(),906 DIEInteger(RetVal->second));907 }908 909 StrOffsetSectionWasModified = false;910 assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second &&911 "debug_str_offsets was already finalized for this CU.");912 clear();913}914 915void DebugStrWriter::create() {916 StrBuffer = std::make_unique<DebugStrBufferVector>();917 StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);918}919 920void DebugStrWriter::initialize() {921 StringRef StrSection;922 if (IsDWO)923 StrSection = DwCtx.getDWARFObj().getStrDWOSection();924 else925 StrSection = DwCtx.getDWARFObj().getStrSection();926 (*StrStream) << StrSection;927}928 929uint32_t DebugStrWriter::addString(StringRef Str) {930 std::lock_guard<std::mutex> Lock(WriterMutex);931 if (StrBuffer->empty())932 initialize();933 auto Offset = StrBuffer->size();934 (*StrStream) << Str;935 StrStream->write_zeros(1);936 return Offset;937}938 939static void emitDwarfSetLineAddrAbs(MCStreamer &OS,940 MCDwarfLineTableParams Params,941 int64_t LineDelta, uint64_t Address,942 int PointerSize) {943 // emit the sequence to set the address944 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);945 OS.emitULEB128IntValue(PointerSize + 1);946 OS.emitIntValue(dwarf::DW_LNE_set_address, 1);947 OS.emitIntValue(Address, PointerSize);948 949 // emit the sequence for the LineDelta (from 1) and a zero address delta.950 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);951}952 953static inline void emitBinaryDwarfLineTable(954 MCStreamer *MCOS, MCDwarfLineTableParams Params,955 const DWARFDebugLine::LineTable *Table,956 const std::vector<DwarfLineTable::RowSequence> &InputSequences) {957 if (InputSequences.empty())958 return;959 960 constexpr uint64_t InvalidAddress = UINT64_MAX;961 unsigned FileNum = 1;962 unsigned LastLine = 1;963 unsigned Column = 0;964 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;965 unsigned Isa = 0;966 unsigned Discriminator = 0;967 uint64_t LastAddress = InvalidAddress;968 uint64_t PrevEndOfSequence = InvalidAddress;969 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();970 971 auto emitEndOfSequence = [&](uint64_t Address) {972 MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);973 FileNum = 1;974 LastLine = 1;975 Column = 0;976 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;977 Isa = 0;978 Discriminator = 0;979 LastAddress = InvalidAddress;980 };981 982 for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {983 const uint64_t SequenceStart =984 Table->Rows[Sequence.FirstIndex].Address.Address;985 986 // Check if we need to mark the end of the sequence.987 if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&988 PrevEndOfSequence != SequenceStart) {989 emitEndOfSequence(PrevEndOfSequence);990 }991 992 for (uint32_t RowIndex = Sequence.FirstIndex;993 RowIndex <= Sequence.LastIndex; ++RowIndex) {994 const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];995 int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;996 const uint64_t Address = Row.Address.Address;997 998 if (FileNum != Row.File) {999 FileNum = Row.File;1000 MCOS->emitInt8(dwarf::DW_LNS_set_file);1001 MCOS->emitULEB128IntValue(FileNum);1002 }1003 if (Column != Row.Column) {1004 Column = Row.Column;1005 MCOS->emitInt8(dwarf::DW_LNS_set_column);1006 MCOS->emitULEB128IntValue(Column);1007 }1008 if (Discriminator != Row.Discriminator &&1009 MCOS->getContext().getDwarfVersion() >= 4) {1010 Discriminator = Row.Discriminator;1011 unsigned Size = getULEB128Size(Discriminator);1012 MCOS->emitInt8(dwarf::DW_LNS_extended_op);1013 MCOS->emitULEB128IntValue(Size + 1);1014 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);1015 MCOS->emitULEB128IntValue(Discriminator);1016 }1017 if (Isa != Row.Isa) {1018 Isa = Row.Isa;1019 MCOS->emitInt8(dwarf::DW_LNS_set_isa);1020 MCOS->emitULEB128IntValue(Isa);1021 }1022 if (Row.IsStmt != Flags) {1023 Flags = Row.IsStmt;1024 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);1025 }1026 if (Row.BasicBlock)1027 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);1028 if (Row.PrologueEnd)1029 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);1030 if (Row.EpilogueBegin)1031 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);1032 1033 // The end of the sequence is not normal in the middle of the input1034 // sequence, but could happen, e.g. for assembly code.1035 if (Row.EndSequence) {1036 emitEndOfSequence(Address);1037 } else {1038 if (LastAddress == InvalidAddress)1039 emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,1040 AsmInfo->getCodePointerSize());1041 else1042 MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);1043 1044 LastAddress = Address;1045 LastLine = Row.Line;1046 }1047 1048 Discriminator = 0;1049 }1050 PrevEndOfSequence = Sequence.EndAddress;1051 }1052 1053 // Finish with the end of the sequence.1054 if (LastAddress != InvalidAddress)1055 emitEndOfSequence(PrevEndOfSequence);1056}1057 1058// This function is similar to the one from MCDwarfLineTable, except it handles1059// end-of-sequence entries differently by utilizing line entries with1060// DWARF2_FLAG_END_SEQUENCE flag.1061static inline void emitDwarfLineTable(1062 MCStreamer *MCOS, MCSection *Section,1063 const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {1064 unsigned FileNum = 1;1065 unsigned LastLine = 1;1066 unsigned Column = 0;1067 unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;1068 unsigned Isa = 0;1069 unsigned Discriminator = 0;1070 MCSymbol *LastLabel = nullptr;1071 const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();1072 1073 // Loop through each MCDwarfLineEntry and encode the dwarf line number table.1074 for (const MCDwarfLineEntry &LineEntry : LineEntries) {1075 if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {1076 MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),1077 AsmInfo->getCodePointerSize());1078 FileNum = 1;1079 LastLine = 1;1080 Column = 0;1081 Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;1082 Isa = 0;1083 Discriminator = 0;1084 LastLabel = nullptr;1085 continue;1086 }1087 1088 int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;1089 1090 if (FileNum != LineEntry.getFileNum()) {1091 FileNum = LineEntry.getFileNum();1092 MCOS->emitInt8(dwarf::DW_LNS_set_file);1093 MCOS->emitULEB128IntValue(FileNum);1094 }1095 if (Column != LineEntry.getColumn()) {1096 Column = LineEntry.getColumn();1097 MCOS->emitInt8(dwarf::DW_LNS_set_column);1098 MCOS->emitULEB128IntValue(Column);1099 }1100 if (Discriminator != LineEntry.getDiscriminator() &&1101 MCOS->getContext().getDwarfVersion() >= 2) {1102 Discriminator = LineEntry.getDiscriminator();1103 unsigned Size = getULEB128Size(Discriminator);1104 MCOS->emitInt8(dwarf::DW_LNS_extended_op);1105 MCOS->emitULEB128IntValue(Size + 1);1106 MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);1107 MCOS->emitULEB128IntValue(Discriminator);1108 }1109 if (Isa != LineEntry.getIsa()) {1110 Isa = LineEntry.getIsa();1111 MCOS->emitInt8(dwarf::DW_LNS_set_isa);1112 MCOS->emitULEB128IntValue(Isa);1113 }1114 if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {1115 Flags = LineEntry.getFlags();1116 MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);1117 }1118 if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)1119 MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);1120 if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)1121 MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);1122 if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)1123 MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);1124 1125 MCSymbol *Label = LineEntry.getLabel();1126 1127 // At this point we want to emit/create the sequence to encode the delta1128 // in line numbers and the increment of the address from the previous1129 // Label and the current Label.1130 MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,1131 AsmInfo->getCodePointerSize());1132 Discriminator = 0;1133 LastLine = LineEntry.getLine();1134 LastLabel = Label;1135 }1136 1137 assert(LastLabel == nullptr && "end of sequence expected");1138}1139 1140void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,1141 std::optional<MCDwarfLineStr> &LineStr,1142 BinaryContext &BC) const {1143 if (!RawData.empty()) {1144 assert(MCLineSections.getMCLineEntries().empty() &&1145 InputSequences.empty() &&1146 "cannot combine raw data with new line entries");1147 MCOS->emitLabel(getLabel());1148 MCOS->emitBytes(RawData);1149 return;1150 }1151 1152 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;1153 1154 // Put out the line tables.1155 for (const auto &LineSec : MCLineSections.getMCLineEntries())1156 emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);1157 1158 // Emit line tables for the original code.1159 emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);1160 1161 // This is the end of the section, so set the value of the symbol at the end1162 // of this section (that was used in a previous expression).1163 MCOS->emitLabel(LineEndSym);1164}1165 1166// Helper function to parse .debug_line_str, and populate one we are using.1167// For functions that we do not modify we output them as raw data.1168// Re-constructing .debug_line_str so that offsets are correct for those1169// debug line tables.1170// Bonus is that when we output a final binary we can reuse .debug_line_str1171// section. So we don't have to do the SHF_ALLOC trick we did with1172// .debug_line.1173static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,1174 MCDwarfLineStr &LineStr,1175 BinaryContext &BC) {1176 DataExtractor StrData(LineStrSection.getContents(),1177 BC.DwCtx->isLittleEndian(), 0);1178 uint64_t Offset = 0;1179 while (StrData.isValidOffset(Offset)) {1180 const uint64_t StrOffset = Offset;1181 Error Err = Error::success();1182 const char *CStr = StrData.getCStr(&Offset, &Err);1183 if (Err) {1184 BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";1185 continue;1186 }1187 const size_t NewOffset = LineStr.addString(CStr);1188 assert(StrOffset == NewOffset &&1189 "New offset in .debug_line_str doesn't match original offset");1190 (void)StrOffset;1191 (void)NewOffset;1192 }1193}1194 1195void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {1196 MCAssembler &Assembler =1197 static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();1198 1199 MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();1200 1201 auto &LineTables = BC.getDwarfLineTables();1202 1203 // Bail out early so we don't switch to the debug_line section needlessly and1204 // in doing so create an unnecessary (if empty) section.1205 if (LineTables.empty())1206 return;1207 // In a v5 non-split line table, put the strings in a separate section.1208 std::optional<MCDwarfLineStr> LineStr;1209 ErrorOr<BinarySection &> LineStrSection =1210 BC.getUniqueSectionByName(".debug_line_str");1211 1212 // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower1213 // .debug_line, so need to check if section exists.1214 if (LineStrSection) {1215 LineStr.emplace(*BC.Ctx);1216 parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC);1217 }1218 1219 // Switch to the section where the table will be emitted into.1220 Streamer.switchSection(BC.MOFI->getDwarfLineSection());1221 1222 const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();1223 // Handle the rest of the Compile Units.1224 for (auto &CUIDTablePair : LineTables) {1225 Streamer.getContext().setDwarfVersion(1226 CUIDTablePair.second.getDwarfVersion());1227 CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);1228 }1229 1230 // Resetting DWARF version for rest of the flow.1231 BC.Ctx->setDwarfVersion(DwarfVersion);1232 1233 // Still need to write the section out for the ExecutionEngine, and temp in1234 // memory object we are constructing.1235 if (LineStr)1236 LineStr->emitSection(&Streamer);1237}1238 1239} // namespace bolt1240} // namespace llvm1241