//===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements functions and classes for handling debug info.
//
//===----------------------------------------------------------------------===//

#include "bolt/Core/DebugData.h"
#include "bolt/Core/BinaryContext.h"
#include "bolt/Utils/Utils.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/SHA1.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <limits>
#include <unordered_map>

#define DEBUG_TYPE "bolt-debug-info"

namespace opts {
extern llvm::cl::opt<unsigned> Verbosity;
} // namespace opts

namespace llvm {
class MCSymbol;

namespace bolt {

const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};

namespace {

LLVM_ATTRIBUTE_UNUSED
static void printLE64(const std::string &S) {
  for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
    errs() << Twine::utohexstr(S[I]);
    errs() << Twine::utohexstr((int8_t)S[I]);
  }
  errs() << "\n";
}

// Writes address ranges to Writer as pairs of 64-bit (address, size).
// If RelativeRange is true, assumes the address range to be written must be of
// the form (begin address, range size), otherwise (begin address, end address).
// Terminates the list by writing a pair of two zeroes.
// Returns the number of written bytes.
uint64_t writeAddressRanges(raw_svector_ostream &Stream,
                            const DebugAddressRangesVector &AddressRanges,
                            const bool WriteRelativeRanges = false) {
  for (const DebugAddressRange &Range : AddressRanges) {
    support::endian::write(Stream, Range.LowPC, support::little);
    support::endian::write(
        Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
        support::little);
  }
  // Finish with 0 entries.
  support::endian::write(Stream, 0ULL, support::little);
  support::endian::write(Stream, 0ULL, support::little);
  return AddressRanges.size() * 16 + 16;
}

} // namespace

DebugRangesSectionWriter::DebugRangesSectionWriter() {
  RangesBuffer = std::make_unique<DebugBufferVector>();
  RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);

  // Add an empty range as the first entry;
  SectionOffset +=
      writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
}

uint64_t DebugRangesSectionWriter::addRanges(
    DebugAddressRangesVector &&Ranges,
    std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
  if (Ranges.empty())
    return getEmptyRangesOffset();

  const auto RI = CachedRanges.find(Ranges);
  if (RI != CachedRanges.end())
    return RI->second;

  const uint64_t EntryOffset = addRanges(Ranges);
  CachedRanges.emplace(std::move(Ranges), EntryOffset);

  return EntryOffset;
}

uint64_t
DebugRangesSectionWriter::addRanges(const DebugAddressRangesVector &Ranges) {
  if (Ranges.empty())
    return getEmptyRangesOffset();

  // Reading the SectionOffset and updating it should be atomic to guarantee
  // unique and correct offsets in patches.
  std::lock_guard<std::mutex> Lock(WriterMutex);
  const uint32_t EntryOffset = SectionOffset;
  SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);

  return EntryOffset;
}

uint64_t DebugRangesSectionWriter::getSectionOffset() {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  return SectionOffset;
}

void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
                                            DebugAddressRangesVector &&Ranges) {
  std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
  CUAddressRanges.emplace(CUOffset, std::move(Ranges));
}

void DebugARangesSectionWriter::writeARangesSection(
    raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
  // For reference on the format of the .debug_aranges section, see the DWARF4
  // specification, section 6.1.4 Lookup by Address
  // http://www.dwarfstd.org/doc/DWARF4.pdf
  for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
    const uint64_t Offset = CUOffsetAddressRangesPair.first;
    const DebugAddressRangesVector &AddressRanges =
        CUOffsetAddressRangesPair.second;

    // Emit header.

    // Size of this set: 8 (size of the header) + 4 (padding after header)
    // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
    // pair of uint64_t's for the terminating, zero-length range.
    // Does not include size field itself.
    uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);

    // Header field #1: set size.
    support::endian::write(RangesStream, Size, support::little);

    // Header field #2: version number, 2 as per the specification.
    support::endian::write(RangesStream, static_cast<uint16_t>(2),
                           support::little);

    assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
    // Header field #3: debug info offset of the correspondent compile unit.
    support::endian::write(
        RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
        support::little);

    // Header field #4: address size.
    // 8 since we only write ELF64 binaries for now.
    RangesStream << char(8);

    // Header field #5: segment size of target architecture.
    RangesStream << char(0);

    // Padding before address table - 4 bytes in the 64-bit-pointer case.
    support::endian::write(RangesStream, static_cast<uint32_t>(0),
                           support::little);

    writeAddressRanges(RangesStream, AddressRanges, true);
  }
}

DebugAddrWriter::DebugAddrWriter(BinaryContext *Bc) { BC = Bc; }

void DebugAddrWriter::AddressForDWOCU::dump() {
  std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
                                          indexToAdddessEnd());
  // Sorting address in increasing order of indices.
  std::sort(SortedMap.begin(), SortedMap.end(),
            [](const IndexAddressPair &A, const IndexAddressPair &B) {
              return A.first < B.first;
            });
  for (auto &Pair : SortedMap)
    dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
}
uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address,
                                              uint64_t DWOId) {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  if (!AddressMaps.count(DWOId))
    AddressMaps[DWOId] = AddressForDWOCU();

  AddressForDWOCU &Map = AddressMaps[DWOId];
  auto Entry = Map.find(Address);
  if (Entry == Map.end()) {
    auto Index = Map.getNextIndex();
    Entry = Map.insert(Address, Index).first;
  }
  return Entry->second;
}

// Case1) Address is not in map insert in to AddresToIndex and IndexToAddres
// Case2) Address is in the map but Index is higher or equal. Need to update
// IndexToAddrss. Case3) Address is in the map but Index is lower. Need to
// update AddressToIndex and IndexToAddress
void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index,
                                      uint64_t DWOId) {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  AddressForDWOCU &Map = AddressMaps[DWOId];
  auto Entry = Map.find(Address);
  if (Entry != Map.end()) {
    if (Entry->second > Index)
      Map.updateAddressToIndex(Address, Index);
    Map.updateIndexToAddrss(Address, Index);
  } else {
    Map.insert(Address, Index);
  }
}

AddressSectionBuffer DebugAddrWriter::finalize() {
  // Need to layout all sections within .debug_addr
  // Within each section sort Address by index.
  AddressSectionBuffer Buffer;
  raw_svector_ostream AddressStream(Buffer);
  for (std::unique_ptr<DWARFUnit> &CU : BC->DwCtx->compile_units()) {
    Optional<uint64_t> DWOId = CU->getDWOId();
    // Handling the case wehre debug information is a mix of Debug fission and
    // monolitic.
    if (!DWOId)
      continue;
    auto AM = AddressMaps.find(*DWOId);
    // Adding to map even if it did not contribute to .debug_addr.
    // The Skeleton CU will still have DW_AT_GNU_addr_base.
    DWOIdToOffsetMap[*DWOId] = Buffer.size();
    // If does not exist this CUs DWO section didn't contribute to .debug_addr.
    if (AM == AddressMaps.end())
      continue;
    std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
                                            AM->second.indexToAdddessEnd());
    // Sorting address in increasing order of indices.
    std::sort(SortedMap.begin(), SortedMap.end(),
              [](const IndexAddressPair &A, const IndexAddressPair &B) {
                return A.first < B.first;
              });

    uint8_t AddrSize = CU->getAddressByteSize();
    uint32_t Counter = 0;
    auto WriteAddress = [&](uint64_t Address) -> void {
      ++Counter;
      switch (AddrSize) {
      default:
        assert(false && "Address Size is invalid.");
        break;
      case 4:
        support::endian::write(AddressStream, static_cast<uint32_t>(Address),
                               support::little);
        break;
      case 8:
        support::endian::write(AddressStream, Address, support::little);
        break;
      }
    };

    for (const IndexAddressPair &Val : SortedMap) {
      while (Val.first > Counter)
        WriteAddress(0);
      WriteAddress(Val.second);
    }
  }

  return Buffer;
}

uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
  auto Iter = DWOIdToOffsetMap.find(DWOId);
  assert(Iter != DWOIdToOffsetMap.end() &&
         "Offset in to.debug_addr was not found for DWO ID.");
  return Iter->second;
}

DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
  LocBuffer = std::make_unique<DebugBufferVector>();
  LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
}

void DebugLocWriter::addList(uint64_t AttrOffset,
                             DebugLocationsVector &&LocList) {
  if (LocList.empty()) {
    EmptyAttrLists.push_back(AttrOffset);
    return;
  }
  // Since there is a separate DebugLocWriter for each thread,
  // we don't need a lock to read the SectionOffset and update it.
  const uint32_t EntryOffset = SectionOffset;

  for (const DebugLocationEntry &Entry : LocList) {
    support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
                           support::little);
    support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
                           support::little);
    support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
                           support::little);
    *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
                            Entry.Expr.size());
    SectionOffset += 2 * 8 + 2 + Entry.Expr.size();
  }
  LocStream->write_zeros(16);
  SectionOffset += 16;
  LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
}

void DebugLoclistWriter::addList(uint64_t AttrOffset,
                                 DebugLocationsVector &&LocList) {
  Patches.push_back({AttrOffset, std::move(LocList)});
}

std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
  return std::move(LocBuffer);
}

// DWARF 4: 2.6.2
void DebugLocWriter::finalize(uint64_t SectionOffset,
                              SimpleBinaryPatcher &DebugInfoPatcher) {
  for (const auto LocListDebugInfoPatchType : LocListDebugInfoPatches) {
    uint64_t Offset = SectionOffset + LocListDebugInfoPatchType.LocListOffset;
    DebugInfoPatcher.addLE32Patch(LocListDebugInfoPatchType.DebugInfoAttrOffset,
                                  Offset);
  }

  for (uint64_t DebugInfoAttrOffset : EmptyAttrLists)
    DebugInfoPatcher.addLE32Patch(DebugInfoAttrOffset,
                                  DebugLocWriter::EmptyListOffset);
}

void DebugLoclistWriter::finalize(uint64_t SectionOffset,
                                  SimpleBinaryPatcher &DebugInfoPatcher) {
  for (LocPatch &Patch : Patches) {
    if (Patch.LocList.empty()) {
      DebugInfoPatcher.addLE32Patch(Patch.AttrOffset,
                                    DebugLocWriter::EmptyListOffset);
      continue;
    }
    const uint32_t EntryOffset = LocBuffer->size();
    for (const DebugLocationEntry &Entry : Patch.LocList) {
      support::endian::write(*LocStream,
                             static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
                             support::little);
      uint32_t Index = AddrWriter->getIndexFromAddress(Entry.LowPC, DWOId);
      encodeULEB128(Index, *LocStream);

      // TODO: Support DWARF5
      support::endian::write(*LocStream,
                             static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
                             support::little);
      support::endian::write(*LocStream,
                             static_cast<uint16_t>(Entry.Expr.size()),
                             support::little);
      *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
                              Entry.Expr.size());
    }
    support::endian::write(*LocStream,
                           static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
                           support::little);
    DebugInfoPatcher.addLE32Patch(Patch.AttrOffset, EntryOffset);
    clearList(Patch.LocList);
  }
  clearList(Patches);
}

DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;

void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) {
  Offset -= DWPUnitOffset;
  std::lock_guard<std::mutex> Lock(WriterMutex);
  DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset));
}

void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) {
  Offset -= DWPUnitOffset;
  std::lock_guard<std::mutex> Lock(WriterMutex);
  auto RetVal = DestinationLabels.insert(Offset);
  if (!RetVal.second)
    return;

  DebugPatches.emplace_back(new DestinationReferenceLabel(Offset));
}

void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset,
                                                 uint32_t DestinationOffset,
                                                 uint32_t OldValueSize,
                                                 dwarf::Form Form) {
  Offset -= DWPUnitOffset;
  DestinationOffset -= DWPUnitOffset;
  std::lock_guard<std::mutex> Lock(WriterMutex);
  DebugPatches.emplace_back(
      new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form));
}

void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue,
                                           uint32_t OldValueSize) {
  Offset -= DWPUnitOffset;
  std::lock_guard<std::mutex> Lock(WriterMutex);
  DebugPatches.emplace_back(
      new DebugPatchVariableSize(Offset, OldValueSize, NewValue));
}

void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
  Offset -= DWPUnitOffset;
  std::lock_guard<std::mutex> Lock(WriterMutex);
  DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue));
}

void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
                                          uint32_t OldValueSize) {
  Offset -= DWPUnitOffset;
  std::lock_guard<std::mutex> Lock(WriterMutex);
  if (OldValueSize == 4)
    DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue));
  else
    DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue));
}

void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
                                         std::string &&NewValue,
                                         uint32_t OldValueSize) {
  Patches.emplace_back(Offset, std::move(NewValue));
}

void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
  auto Str = std::string(1, Value);
  Patches.emplace_back(Offset, std::move(Str));
}

static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
  std::string LE64(ByteSize, 0);
  for (size_t I = 0; I < ByteSize; ++I) {
    LE64[I] = NewValue & 0xff;
    NewValue >>= 8;
  }
  return LE64;
}

void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
                                     size_t ByteSize) {
  Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
}

void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
                                        uint32_t OldValueSize) {
  std::string Buff;
  raw_string_ostream OS(Buff);
  encodeULEB128(Value, OS, OldValueSize);

  Patches.emplace_back(Offset, std::move(Buff));
}

void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
  addLEPatch(Offset, NewValue, 8);
}

void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
                                       uint32_t OldValueSize) {
  addLEPatch(Offset, NewValue, 4);
}

std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
  std::string BinaryContentsStr = std::string(BinaryContents);
  for (const auto &Patch : Patches) {
    uint32_t Offset = Patch.first;
    const std::string &ByteSequence = Patch.second;
    assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
           "Applied patch runs over binary size.");
    for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
      BinaryContentsStr[Offset + I] = ByteSequence[I];
    }
  }
  return BinaryContentsStr;
}

CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx,
                                                      bool IsDWOContext) {
  CUOffsetMap CUMap;
  std::sort(DebugPatches.begin(), DebugPatches.end(),
            [](const UniquePatchPtrType &V1, const UniquePatchPtrType &V2) {
              return V1.get()->Offset < V2.get()->Offset;
            });

  DWARFUnitVector::compile_unit_range CompileUnits =
      IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units();

  for (const std::unique_ptr<DWARFUnit> &CU : CompileUnits)
    CUMap[CU->getOffset()] = {static_cast<uint32_t>(CU->getOffset()),
                              static_cast<uint32_t>(CU->getLength())};

  // Calculating changes in .debug_info size from Patches to build a map of old
  // to updated reference destination offsets.
  uint32_t PreviousOffset = 0;
  int32_t PreviousChangeInSize = 0;
  for (UniquePatchPtrType &PatchBase : DebugPatches) {
    Patch *P = PatchBase.get();
    switch (P->Kind) {
    default:
      continue;
    case DebugPatchKind::PatchValue64to32: {
      PreviousChangeInSize -= 4;
      break;
    }
    case DebugPatchKind::PatchValueVariable: {
      DebugPatchVariableSize *DPV =
          reinterpret_cast<DebugPatchVariableSize *>(P);
      std::string Temp;
      raw_string_ostream OS(Temp);
      encodeULEB128(DPV->Value, OS);
      PreviousChangeInSize += Temp.size() - DPV->OldValueSize;
      break;
    }
    case DebugPatchKind::DestinationReferenceLabel: {
      DestinationReferenceLabel *DRL =
          reinterpret_cast<DestinationReferenceLabel *>(P);
      OldToNewOffset[DRL->Offset] =
          DRL->Offset + ChangeInSize + PreviousChangeInSize;
      break;
    }
    case DebugPatchKind::ReferencePatchValue: {
      // This doesn't look to be a common case, so will always encode as 4 bytes
      // to reduce algorithmic complexity.
      DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
      if (RDP->PatchInfo.IndirectRelative) {
        PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize;
        assert(RDP->PatchInfo.OldValueSize <= 4 &&
               "Variable encoding reference greater than 4 bytes.");
      }
      break;
    }
    case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
      DWARFUnitOffsetBaseLabel *BaseLabel =
          reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
      uint32_t CUOffset = BaseLabel->Offset;
      ChangeInSize += PreviousChangeInSize;
      uint32_t CUOffsetUpdate = CUOffset + ChangeInSize;
      CUMap[CUOffset].Offset = CUOffsetUpdate;
      CUMap[PreviousOffset].Length += PreviousChangeInSize;
      PreviousChangeInSize = 0;
      PreviousOffset = CUOffset;
    }
    }
  }
  CUMap[PreviousOffset].Length += PreviousChangeInSize;
  return CUMap;
}

std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) {
  std::string NewBinaryContents;
  NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize);
  uint32_t StartOffset = 0;
  uint32_t DwarfUnitBaseOffset = 0;
  uint32_t OldValueSize = 0;
  uint32_t Offset = 0;
  std::string ByteSequence;
  std::vector<std::pair<uint32_t, uint32_t>> LengthPatches;
  // Wasting one entry to avoid checks for first.
  LengthPatches.push_back({0, 0});

  // Applying all the patches replacing current entry.
  // This might change the size of .debug_info section.
  for (const UniquePatchPtrType &PatchBase : DebugPatches) {
    Patch *P = PatchBase.get();
    switch (P->Kind) {
    default:
      continue;
    case DebugPatchKind::ReferencePatchValue: {
      DebugPatchReference *RDP = reinterpret_cast<DebugPatchReference *>(P);
      uint32_t DestinationOffset = RDP->DestinationOffset;
      assert(OldToNewOffset.count(DestinationOffset) &&
             "Destination Offset for reference not updated.");
      uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset];
      Offset = RDP->Offset;
      OldValueSize = RDP->PatchInfo.OldValueSize;
      if (RDP->PatchInfo.DirectRelative) {
        UpdatedOffset -= DwarfUnitBaseOffset;
        ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
        // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge
        // and overflow if later debug information grows.
        if (ByteSequence.size() > OldValueSize)
          errs() << "BOLT-ERROR: Relative reference of size "
                 << Twine::utohexstr(OldValueSize)
                 << " overflows with the new encoding.\n";
      } else if (RDP->PatchInfo.DirectAbsolute) {
        ByteSequence = encodeLE(OldValueSize, UpdatedOffset);
      } else if (RDP->PatchInfo.IndirectRelative) {
        UpdatedOffset -= DwarfUnitBaseOffset;
        ByteSequence.clear();
        raw_string_ostream OS(ByteSequence);
        encodeULEB128(UpdatedOffset, OS, 4);
      } else {
        llvm_unreachable("Invalid Reference form.");
      }
      break;
    }
    case DebugPatchKind::PatchValue32: {
      DebugPatch32 *P32 = reinterpret_cast<DebugPatch32 *>(P);
      Offset = P32->Offset;
      OldValueSize = 4;
      ByteSequence = encodeLE(4, P32->Value);
      break;
    }
    case DebugPatchKind::PatchValue64to32: {
      DebugPatch64to32 *P64to32 = reinterpret_cast<DebugPatch64to32 *>(P);
      Offset = P64to32->Offset;
      OldValueSize = 8;
      ByteSequence = encodeLE(4, P64to32->Value);
      break;
    }
    case DebugPatchKind::PatchValueVariable: {
      DebugPatchVariableSize *PV =
          reinterpret_cast<DebugPatchVariableSize *>(P);
      Offset = PV->Offset;
      OldValueSize = PV->OldValueSize;
      ByteSequence.clear();
      raw_string_ostream OS(ByteSequence);
      encodeULEB128(PV->Value, OS);
      break;
    }
    case DebugPatchKind::PatchValue64: {
      DebugPatch64 *P64 = reinterpret_cast<DebugPatch64 *>(P);
      Offset = P64->Offset;
      OldValueSize = 8;
      ByteSequence = encodeLE(8, P64->Value);
      break;
    }
    case DebugPatchKind::DWARFUnitOffsetBaseLabel: {
      DWARFUnitOffsetBaseLabel *BaseLabel =
          reinterpret_cast<DWARFUnitOffsetBaseLabel *>(P);
      Offset = BaseLabel->Offset;
      OldValueSize = 0;
      ByteSequence.clear();
      auto &Patch = LengthPatches.back();
      // Length to copy between last patch entry and next compile unit.
      uint32_t RemainingLength = Offset - StartOffset;
      uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength;
      DwarfUnitBaseOffset = NewCUOffset;
      // Length of previous CU = This CU Offset - sizeof(length) - last CU
      // Offset.
      Patch.second = NewCUOffset - 4 - Patch.first;
      LengthPatches.push_back({NewCUOffset, 0});
      break;
    }
    }

    assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
           "Applied patch runs over binary size.");
    uint32_t Length = Offset - StartOffset;
    NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
                             Length);
    NewBinaryContents.append(ByteSequence.data(), ByteSequence.size());
    StartOffset = Offset + OldValueSize;
  }
  uint32_t Length = BinaryContents.size() - StartOffset;
  NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(),
                           Length);
  DebugPatches.clear();

  // Patching lengths of CUs
  auto &Patch = LengthPatches.back();
  Patch.second = NewBinaryContents.size() - 4 - Patch.first;
  for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) {
    const auto &Patch = LengthPatches[J];
    ByteSequence = encodeLE(4, Patch.second);
    Offset = Patch.first;
    for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I)
      NewBinaryContents[Offset + I] = ByteSequence[I];
  }

  return NewBinaryContents;
}

void DebugStrWriter::create() {
  StrBuffer = std::make_unique<DebugStrBufferVector>();
  StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
}

void DebugStrWriter::initialize() {
  auto StrSection = BC->DwCtx->getDWARFObj().getStrSection();
  (*StrStream) << StrSection;
}

uint32_t DebugStrWriter::addString(StringRef Str) {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  if (StrBuffer->empty())
    initialize();
  auto Offset = StrBuffer->size();
  (*StrStream) << Str;
  StrStream->write_zeros(1);
  return Offset;
}

void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
  const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
  if (!Abbrevs)
    return;

  const PatchesTy &UnitPatches = Patches[&Unit];

  // We are duplicating abbrev sections, to handle the case where for one CU we
  // modify it, but for another we don't.
  auto UnitDataPtr = std::make_unique<AbbrevData>();
  AbbrevData &UnitData = *UnitDataPtr.get();
  UnitData.Buffer = std::make_unique<DebugBufferVector>();
  UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
  raw_svector_ostream &OS = *UnitData.Stream.get();

  // Returns true if AbbrevData is re-used, false otherwise.
  auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool {
    llvm::SHA1 Hasher;
    Hasher.update(AbbrevData);
    StringRef Key = Hasher.final();
    auto Iter = AbbrevDataCache.find(Key);
    if (Iter != AbbrevDataCache.end()) {
      UnitsAbbrevData[&Unit] = Iter->second.get();
      return true;
    }
    AbbrevDataCache[Key] = std::move(UnitDataPtr);
    UnitsAbbrevData[&Unit] = &UnitData;
    return false;
  };
  // Take a fast path if there are no patches to apply. Simply copy the original
  // contents.
  if (UnitPatches.empty()) {
    StringRef AbbrevSectionContents =
        Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
                         : Unit.getContext().getDWARFObj().getAbbrevSection();
    StringRef AbbrevContents;

    const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
    if (!CUIndex.getRows().empty()) {
      // Handle DWP section contribution.
      const DWARFUnitIndex::Entry *DWOEntry =
          CUIndex.getFromHash(*Unit.getDWOId());
      if (!DWOEntry)
        return;

      const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
          DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
      AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
                                                    DWOContrubution->Length);
    } else if (!Unit.isDWOUnit()) {
      const uint64_t StartOffset = Unit.getAbbreviationsOffset();

      // We know where the unit's abbreviation set starts, but not where it ends
      // as such data is not readily available. Hence, we have to build a sorted
      // list of start addresses and find the next starting address to determine
      // the set boundaries.
      //
      // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets
      // we wouldn't have to build our own sorted list for the quick lookup.
      if (AbbrevSetOffsets.empty()) {
        for_each(
            *Unit.getContext().getDebugAbbrev(),
            [&](const std::pair<uint64_t, DWARFAbbreviationDeclarationSet> &P) {
              AbbrevSetOffsets.push_back(P.first);
            });
        sort(AbbrevSetOffsets);
      }
      auto It = upper_bound(AbbrevSetOffsets, StartOffset);
      const uint64_t EndOffset =
          It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It;
      AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
    } else {
      // For DWO unit outside of DWP, we expect the entire section to hold
      // abbreviations for this unit only.
      AbbrevContents = AbbrevSectionContents;
    }

    if (!hashAndAddAbbrev(AbbrevContents)) {
      OS.reserveExtraSpace(AbbrevContents.size());
      OS << AbbrevContents;
    }
    return;
  }

  for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
    const DWARFAbbreviationDeclaration &Abbrev = *I;
    auto Patch = UnitPatches.find(&Abbrev);

    encodeULEB128(Abbrev.getCode(), OS);
    encodeULEB128(Abbrev.getTag(), OS);
    encodeULEB128(Abbrev.hasChildren(), OS);
    for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
         Abbrev.attributes()) {
      if (Patch != UnitPatches.end()) {
        bool Patched = false;
        // Patches added later take a precedence over earlier ones.
        for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
             ++I) {
          if (I->OldAttr != AttrSpec.Attr)
            continue;

          encodeULEB128(I->NewAttr, OS);
          encodeULEB128(I->NewAttrForm, OS);
          Patched = true;
          break;
        }
        if (Patched)
          continue;
      }

      encodeULEB128(AttrSpec.Attr, OS);
      encodeULEB128(AttrSpec.Form, OS);
      if (AttrSpec.isImplicitConst())
        encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
    }

    encodeULEB128(0, OS);
    encodeULEB128(0, OS);
  }
  encodeULEB128(0, OS);

  hashAndAddAbbrev(OS.str());
}

std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
  // Used to create determinism for writing out abbrevs.
  std::vector<AbbrevData *> Abbrevs;
  if (DWOId) {
    // We expect abbrev_offset to always be zero for DWO units as there
    // should be one CU per DWO, and TUs should share the same abbreviation
    // set with the CU.
    // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so
    // can be none zero. Thus we are skipping the check for DWP.
    bool IsDWP = !Context.getCUIndex().getRows().empty();
    if (!IsDWP) {
      for (const std::unique_ptr<DWARFUnit> &Unit : Context.dwo_units()) {
        if (Unit->getAbbreviationsOffset() != 0) {
          errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. "
                    "Unable to update debug info.\n";
          exit(1);
        }
      }
    }

    DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId);
    // Issue abbreviations for the DWO CU only.
    addUnitAbbreviations(*Unit);
    AbbrevData *Abbrev = UnitsAbbrevData[Unit];
    Abbrevs.push_back(Abbrev);
  } else {
    Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits());
    std::unordered_set<AbbrevData *> ProcessedAbbrevs;
    // Add abbreviations from compile and type non-DWO units.
    for (const std::unique_ptr<DWARFUnit> &Unit : Context.normal_units()) {
      addUnitAbbreviations(*Unit);
      AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()];
      if (!ProcessedAbbrevs.insert(Abbrev).second)
        continue;
      Abbrevs.push_back(Abbrev);
    }
  }

  DebugBufferVector ReturnBuffer;
  // Pre-calculate the total size of abbrev section.
  uint64_t Size = 0;
  for (const AbbrevData *UnitData : Abbrevs)
    Size += UnitData->Buffer->size();

  ReturnBuffer.reserve(Size);

  uint64_t Pos = 0;
  for (AbbrevData *UnitData : Abbrevs) {
    ReturnBuffer.append(*UnitData->Buffer);
    UnitData->Offset = Pos;
    Pos += UnitData->Buffer->size();

    UnitData->Buffer.reset();
    UnitData->Stream.reset();
  }

  return std::make_unique<DebugBufferVector>(ReturnBuffer);
}

static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
                                    MCDwarfLineTableParams Params,
                                    int64_t LineDelta, uint64_t Address,
                                    int PointerSize) {
  // emit the sequence to set the address
  OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
  OS.emitULEB128IntValue(PointerSize + 1);
  OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
  OS.emitIntValue(Address, PointerSize);

  // emit the sequence for the LineDelta (from 1) and a zero address delta.
  MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
}

static inline void emitBinaryDwarfLineTable(
    MCStreamer *MCOS, MCDwarfLineTableParams Params,
    const DWARFDebugLine::LineTable *Table,
    const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
  if (InputSequences.empty())
    return;

  constexpr uint64_t InvalidAddress = UINT64_MAX;
  unsigned FileNum = 1;
  unsigned LastLine = 1;
  unsigned Column = 0;
  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  unsigned Isa = 0;
  unsigned Discriminator = 0;
  uint64_t LastAddress = InvalidAddress;
  uint64_t PrevEndOfSequence = InvalidAddress;
  const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();

  auto emitEndOfSequence = [&](uint64_t Address) {
    MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
    FileNum = 1;
    LastLine = 1;
    Column = 0;
    Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
    Isa = 0;
    Discriminator = 0;
    LastAddress = InvalidAddress;
  };

  for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
    const uint64_t SequenceStart =
        Table->Rows[Sequence.FirstIndex].Address.Address;

    // Check if we need to mark the end of the sequence.
    if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
        PrevEndOfSequence != SequenceStart) {
      emitEndOfSequence(PrevEndOfSequence);
    }

    for (uint32_t RowIndex = Sequence.FirstIndex;
         RowIndex <= Sequence.LastIndex; ++RowIndex) {
      const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
      int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
      const uint64_t Address = Row.Address.Address;

      if (FileNum != Row.File) {
        FileNum = Row.File;
        MCOS->emitInt8(dwarf::DW_LNS_set_file);
        MCOS->emitULEB128IntValue(FileNum);
      }
      if (Column != Row.Column) {
        Column = Row.Column;
        MCOS->emitInt8(dwarf::DW_LNS_set_column);
        MCOS->emitULEB128IntValue(Column);
      }
      if (Discriminator != Row.Discriminator &&
          MCOS->getContext().getDwarfVersion() >= 4) {
        Discriminator = Row.Discriminator;
        unsigned Size = getULEB128Size(Discriminator);
        MCOS->emitInt8(dwarf::DW_LNS_extended_op);
        MCOS->emitULEB128IntValue(Size + 1);
        MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
        MCOS->emitULEB128IntValue(Discriminator);
      }
      if (Isa != Row.Isa) {
        Isa = Row.Isa;
        MCOS->emitInt8(dwarf::DW_LNS_set_isa);
        MCOS->emitULEB128IntValue(Isa);
      }
      if (Row.IsStmt != Flags) {
        Flags = Row.IsStmt;
        MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
      }
      if (Row.BasicBlock)
        MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
      if (Row.PrologueEnd)
        MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
      if (Row.EpilogueBegin)
        MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);

      // The end of the sequence is not normal in the middle of the input
      // sequence, but could happen, e.g. for assembly code.
      if (Row.EndSequence) {
        emitEndOfSequence(Address);
      } else {
        if (LastAddress == InvalidAddress)
          emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
                                  AsmInfo->getCodePointerSize());
        else
          MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);

        LastAddress = Address;
        LastLine = Row.Line;
      }

      Discriminator = 0;
    }
    PrevEndOfSequence = Sequence.EndAddress;
  }

  // Finish with the end of the sequence.
  if (LastAddress != InvalidAddress)
    emitEndOfSequence(PrevEndOfSequence);
}

// This function is similar to the one from MCDwarfLineTable, except it handles
// end-of-sequence entries differently by utilizing line entries with
// DWARF2_FLAG_END_SEQUENCE flag.
static inline void emitDwarfLineTable(
    MCStreamer *MCOS, MCSection *Section,
    const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
  unsigned FileNum = 1;
  unsigned LastLine = 1;
  unsigned Column = 0;
  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  unsigned Isa = 0;
  unsigned Discriminator = 0;
  MCSymbol *LastLabel = nullptr;
  const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();

  // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
  for (const MCDwarfLineEntry &LineEntry : LineEntries) {
    if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
      MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
                                     AsmInfo->getCodePointerSize());
      FileNum = 1;
      LastLine = 1;
      Column = 0;
      Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
      Isa = 0;
      Discriminator = 0;
      LastLabel = nullptr;
      continue;
    }

    int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;

    if (FileNum != LineEntry.getFileNum()) {
      FileNum = LineEntry.getFileNum();
      MCOS->emitInt8(dwarf::DW_LNS_set_file);
      MCOS->emitULEB128IntValue(FileNum);
    }
    if (Column != LineEntry.getColumn()) {
      Column = LineEntry.getColumn();
      MCOS->emitInt8(dwarf::DW_LNS_set_column);
      MCOS->emitULEB128IntValue(Column);
    }
    if (Discriminator != LineEntry.getDiscriminator() &&
        MCOS->getContext().getDwarfVersion() >= 4) {
      Discriminator = LineEntry.getDiscriminator();
      unsigned Size = getULEB128Size(Discriminator);
      MCOS->emitInt8(dwarf::DW_LNS_extended_op);
      MCOS->emitULEB128IntValue(Size + 1);
      MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
      MCOS->emitULEB128IntValue(Discriminator);
    }
    if (Isa != LineEntry.getIsa()) {
      Isa = LineEntry.getIsa();
      MCOS->emitInt8(dwarf::DW_LNS_set_isa);
      MCOS->emitULEB128IntValue(Isa);
    }
    if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
      Flags = LineEntry.getFlags();
      MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
    }
    if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
      MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
    if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
      MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
    if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
      MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);

    MCSymbol *Label = LineEntry.getLabel();

    // At this point we want to emit/create the sequence to encode the delta
    // in line numbers and the increment of the address from the previous
    // Label and the current Label.
    MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
                                   AsmInfo->getCodePointerSize());
    Discriminator = 0;
    LastLine = LineEntry.getLine();
    LastLabel = Label;
  }

  assert(LastLabel == nullptr && "end of sequence expected");
}

void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                            Optional<MCDwarfLineStr> &LineStr,
                            BinaryContext &BC) const {
  if (!RawData.empty()) {
    assert(MCLineSections.getMCLineEntries().empty() &&
           InputSequences.empty() &&
           "cannot combine raw data with new line entries");
    MCOS->emitLabel(getLabel());
    MCOS->emitBytes(RawData);

    // Emit fake relocation for RuntimeDyld to always allocate the section.
    //
    // FIXME: remove this once RuntimeDyld stops skipping allocatable sections
    //        without relocations.
    MCOS->emitRelocDirective(
        *MCConstantExpr::create(0, *BC.Ctx), "BFD_RELOC_NONE",
        MCSymbolRefExpr::create(getLabel(), *BC.Ctx), SMLoc(), *BC.STI);

    return;
  }

  MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;

  // Put out the line tables.
  for (const auto &LineSec : MCLineSections.getMCLineEntries())
    emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);

  // Emit line tables for the original code.
  emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);

  // This is the end of the section, so set the value of the symbol at the end
  // of this section (that was used in a previous expression).
  MCOS->emitLabel(LineEndSym);
}

void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
  MCAssembler &Assembler =
      static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();

  MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();

  auto &LineTables = BC.getDwarfLineTables();

  // Bail out early so we don't switch to the debug_line section needlessly and
  // in doing so create an unnecessary (if empty) section.
  if (LineTables.empty())
    return;

  // In a v5 non-split line table, put the strings in a separate section.
  Optional<MCDwarfLineStr> LineStr(None);
  if (BC.Ctx->getDwarfVersion() >= 5)
    LineStr = MCDwarfLineStr(*BC.Ctx);

  // Switch to the section where the table will be emitted into.
  Streamer.SwitchSection(BC.MOFI->getDwarfLineSection());

  // Handle the rest of the Compile Units.
  for (auto &CUIDTablePair : LineTables) {
    CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
  }
}

} // namespace bolt
} // namespace llvm
