//===- DWARFDebugLoc.cpp --------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cinttypes>
#include <cstdint>

using namespace llvm;
using object::SectionedAddress;

namespace {
class DWARFLocationInterpreter {
  Optional<object::SectionedAddress> Base;
  std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr;

public:
  DWARFLocationInterpreter(
      Optional<object::SectionedAddress> Base,
      std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr)
      : Base(Base), LookupAddr(std::move(LookupAddr)) {}

  Expected<Optional<DWARFLocationExpression>>
  Interpret(const DWARFLocationEntry &E);
};
} // namespace

static Error createResolverError(uint32_t Index, unsigned Kind) {
  return createStringError(errc::invalid_argument,
                           "Unable to resolve indirect address %u for: %s",
                           Index, dwarf::LocListEncodingString(Kind).data());
}

Expected<Optional<DWARFLocationExpression>>
DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) {
  switch (E.Kind) {
  case dwarf::DW_LLE_end_of_list:
    return None;
  case dwarf::DW_LLE_base_addressx: {
    Base = LookupAddr(E.Value0);
    if (!Base)
      return createResolverError(E.Value0, E.Kind);
    return None;
  }
  case dwarf::DW_LLE_startx_endx: {
    Optional<SectionedAddress> LowPC = LookupAddr(E.Value0);
    if (!LowPC)
      return createResolverError(E.Value0, E.Kind);
    Optional<SectionedAddress> HighPC = LookupAddr(E.Value1);
    if (!HighPC)
      return createResolverError(E.Value1, E.Kind);
    return DWARFLocationExpression{
        DWARFAddressRange{LowPC->Address, HighPC->Address, LowPC->SectionIndex},
        E.Loc};
  }
  case dwarf::DW_LLE_startx_length: {
    Optional<SectionedAddress> LowPC = LookupAddr(E.Value0);
    if (!LowPC)
      return createResolverError(E.Value0, E.Kind);
    return DWARFLocationExpression{DWARFAddressRange{LowPC->Address,
                                                     LowPC->Address + E.Value1,
                                                     LowPC->SectionIndex},
                                   E.Loc};
  }
  case dwarf::DW_LLE_offset_pair: {
    if (!Base) {
      return createStringError(inconvertibleErrorCode(),
                               "Unable to resolve location list offset pair: "
                               "Base address not defined");
    }
    DWARFAddressRange Range{Base->Address + E.Value0, Base->Address + E.Value1,
                            Base->SectionIndex};
    if (Range.SectionIndex == SectionedAddress::UndefSection)
      Range.SectionIndex = E.SectionIndex;
    return DWARFLocationExpression{Range, E.Loc};
  }
  case dwarf::DW_LLE_default_location:
    return DWARFLocationExpression{None, E.Loc};
  case dwarf::DW_LLE_base_address:
    Base = SectionedAddress{E.Value0, E.SectionIndex};
    return None;
  case dwarf::DW_LLE_start_end:
    return DWARFLocationExpression{
        DWARFAddressRange{E.Value0, E.Value1, E.SectionIndex}, E.Loc};
  case dwarf::DW_LLE_start_length:
    return DWARFLocationExpression{
        DWARFAddressRange{E.Value0, E.Value0 + E.Value1, E.SectionIndex},
        E.Loc};
  default:
    llvm_unreachable("unreachable locations list kind");
  }
}

// When directly dumping the .debug_loc without a compile unit, we have to guess
// at the DWARF version. This only affects DW_OP_call_ref, which is a rare
// expression that LLVM doesn't produce. Guessing the wrong version means we
// won't be able to pretty print expressions in DWARF2 binaries produced by
// non-LLVM tools.
static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data,
                           bool IsLittleEndian, unsigned AddressSize,
                           const MCRegisterInfo *MRI, DWARFUnit *U) {
  DWARFDataExtractor Extractor(toStringRef(Data), IsLittleEndian, AddressSize);
  DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
}

bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS,
                                          Optional<SectionedAddress> BaseAddr,
                                          const MCRegisterInfo *MRI,
                                          const DWARFObject &Obj, DWARFUnit *U,
                                          DIDumpOptions DumpOpts,
                                          unsigned Indent) const {
  DWARFLocationInterpreter Interp(
      BaseAddr, [U](uint32_t Index) -> Optional<SectionedAddress> {
        if (U)
          return U->getAddrOffsetSectionItem(Index);
        return None;
      });
  OS << format("0x%8.8" PRIx64 ": ", *Offset);
  Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) {
    Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
    if (!Loc || DumpOpts.DisplayRawContents)
      dumpRawEntry(E, OS, Indent, DumpOpts, Obj);
    if (Loc && *Loc) {
      OS << "\n";
      OS.indent(Indent);
      if (DumpOpts.DisplayRawContents)
        OS << "          => ";

      DIDumpOptions RangeDumpOpts(DumpOpts);
      RangeDumpOpts.DisplayRawContents = false;
      if (Loc.get()->Range)
        Loc.get()->Range->dump(OS, Data.getAddressSize(), RangeDumpOpts, &Obj);
      else
        OS << "<default>";
    }
    if (!Loc)
      consumeError(Loc.takeError());

    if (E.Kind != dwarf::DW_LLE_base_address &&
        E.Kind != dwarf::DW_LLE_base_addressx &&
        E.Kind != dwarf::DW_LLE_end_of_list) {
      OS << ": ";
      dumpExpression(OS, E.Loc, Data.isLittleEndian(), Data.getAddressSize(),
                     MRI, U);
    }
    return true;
  });
  if (E) {
    OS << "\n";
    OS.indent(Indent);
    OS << "error: " << toString(std::move(E));
    return false;
  }
  return true;
}

Error DWARFLocationTable::visitAbsoluteLocationList(
    uint64_t Offset, Optional<SectionedAddress> BaseAddr,
    std::function<Optional<SectionedAddress>(uint32_t)> LookupAddr,
    function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const {
  DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr));
  return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) {
    Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
    if (!Loc)
      return Callback(Loc.takeError());
    if (*Loc)
      return Callback(**Loc);
    return true;
  });
}

void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
                         const DWARFObject &Obj, DIDumpOptions DumpOpts,
                         Optional<uint64_t> DumpOffset) const {
  auto BaseAddr = None;
  unsigned Indent = 12;
  if (DumpOffset) {
    dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, Obj, nullptr, DumpOpts,
                     Indent);
  } else {
    uint64_t Offset = 0;
    StringRef Separator;
    bool CanContinue = true;
    while (CanContinue && Data.isValidOffset(Offset)) {
      OS << Separator;
      Separator = "\n";

      CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, Obj, nullptr,
                                     DumpOpts, Indent);
      OS << '\n';
    }
  }
}

Error DWARFDebugLoc::visitLocationList(
    uint64_t *Offset,
    function_ref<bool(const DWARFLocationEntry &)> Callback) const {
  DataExtractor::Cursor C(*Offset);
  while (true) {
    uint64_t SectionIndex;
    uint64_t Value0 = Data.getRelocatedAddress(C);
    uint64_t Value1 = Data.getRelocatedAddress(C, &SectionIndex);

    DWARFLocationEntry E;

    // The end of any given location list is marked by an end of list entry,
    // which consists of a 0 for the beginning address offset and a 0 for the
    // ending address offset. A beginning offset of 0xff...f marks the base
    // address selection entry.
    if (Value0 == 0 && Value1 == 0) {
      E.Kind = dwarf::DW_LLE_end_of_list;
    } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) {
      E.Kind = dwarf::DW_LLE_base_address;
      E.Value0 = Value1;
      E.SectionIndex = SectionIndex;
    } else {
      E.Kind = dwarf::DW_LLE_offset_pair;
      E.Value0 = Value0;
      E.Value1 = Value1;
      E.SectionIndex = SectionIndex;
      unsigned Bytes = Data.getU16(C);
      // A single location description describing the location of the object...
      Data.getU8(C, E.Loc, Bytes);
    }

    if (!C)
      return C.takeError();
    if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list)
      break;
  }
  *Offset = C.tell();
  return Error::success();
}

void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry,
                                 raw_ostream &OS, unsigned Indent,
                                 DIDumpOptions DumpOpts,
                                 const DWARFObject &Obj) const {
  uint64_t Value0, Value1;
  switch (Entry.Kind) {
  case dwarf::DW_LLE_base_address:
    Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL;
    Value1 = Entry.Value0;
    break;
  case dwarf::DW_LLE_offset_pair:
    Value0 = Entry.Value0;
    Value1 = Entry.Value1;
    break;
  case dwarf::DW_LLE_end_of_list:
    Value0 = Value1 = 0;
    return;
  default:
    llvm_unreachable("Not possible in DWARF4!");
  }
  OS << '\n';
  OS.indent(Indent);
  OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", "
     << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')';
  DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex);
}

Error DWARFDebugLoclists::visitLocationList(
    uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const {

  DataExtractor::Cursor C(*Offset);
  bool Continue = true;
  while (Continue) {
    DWARFLocationEntry E;
    E.Kind = Data.getU8(C);
    switch (E.Kind) {
    case dwarf::DW_LLE_end_of_list:
      break;
    case dwarf::DW_LLE_base_addressx:
      E.Value0 = Data.getULEB128(C);
      break;
    case dwarf::DW_LLE_startx_endx:
      E.Value0 = Data.getULEB128(C);
      E.Value1 = Data.getULEB128(C);
      break;
    case dwarf::DW_LLE_startx_length:
      E.Value0 = Data.getULEB128(C);
      // Pre-DWARF 5 has different interpretation of the length field. We have
      // to support both pre- and standartized styles for the compatibility.
      if (Version < 5)
        E.Value1 = Data.getU32(C);
      else
        E.Value1 = Data.getULEB128(C);
      break;
    case dwarf::DW_LLE_offset_pair:
      E.Value0 = Data.getULEB128(C);
      E.Value1 = Data.getULEB128(C);
      E.SectionIndex = SectionedAddress::UndefSection;
      break;
    case dwarf::DW_LLE_default_location:
      break;
    case dwarf::DW_LLE_base_address:
      E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);
      break;
    case dwarf::DW_LLE_start_end:
      E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);
      E.Value1 = Data.getRelocatedAddress(C);
      break;
    case dwarf::DW_LLE_start_length:
      E.Value0 = Data.getRelocatedAddress(C, &E.SectionIndex);
      E.Value1 = Data.getULEB128(C);
      break;
    default:
      cantFail(C.takeError());
      return createStringError(errc::illegal_byte_sequence,
                               "LLE of kind %x not supported", (int)E.Kind);
    }

    if (E.Kind != dwarf::DW_LLE_base_address &&
        E.Kind != dwarf::DW_LLE_base_addressx &&
        E.Kind != dwarf::DW_LLE_end_of_list) {
      unsigned Bytes = Version >= 5 ? Data.getULEB128(C) : Data.getU16(C);
      // A single location description describing the location of the object...
      Data.getU8(C, E.Loc, Bytes);
    }

    if (!C)
      return C.takeError();
    Continue = F(E) && E.Kind != dwarf::DW_LLE_end_of_list;
  }
  *Offset = C.tell();
  return Error::success();
}

void DWARFDebugLoclists::dumpRawEntry(const DWARFLocationEntry &Entry,
                                      raw_ostream &OS, unsigned Indent,
                                      DIDumpOptions DumpOpts,
                                      const DWARFObject &Obj) const {
  size_t MaxEncodingStringLength = 0;
#define HANDLE_DW_LLE(ID, NAME)                                                \
  MaxEncodingStringLength = std::max(MaxEncodingStringLength,                  \
                                     dwarf::LocListEncodingString(ID).size());
#include "llvm/BinaryFormat/Dwarf.def"

  OS << "\n";
  OS.indent(Indent);
  StringRef EncodingString = dwarf::LocListEncodingString(Entry.Kind);
  // Unsupported encodings should have been reported during parsing.
  assert(!EncodingString.empty() && "Unknown loclist entry encoding");
  OS << format("%-*s(", MaxEncodingStringLength, EncodingString.data());
  unsigned FieldSize = 2 + 2 * Data.getAddressSize();
  switch (Entry.Kind) {
  case dwarf::DW_LLE_end_of_list:
  case dwarf::DW_LLE_default_location:
    break;
  case dwarf::DW_LLE_startx_endx:
  case dwarf::DW_LLE_startx_length:
  case dwarf::DW_LLE_offset_pair:
  case dwarf::DW_LLE_start_end:
  case dwarf::DW_LLE_start_length:
    OS << format_hex(Entry.Value0, FieldSize) << ", "
       << format_hex(Entry.Value1, FieldSize);
    break;
  case dwarf::DW_LLE_base_addressx:
  case dwarf::DW_LLE_base_address:
    OS << format_hex(Entry.Value0, FieldSize);
    break;
  }
  OS << ')';
  switch (Entry.Kind) {
  case dwarf::DW_LLE_base_address:
  case dwarf::DW_LLE_start_end:
  case dwarf::DW_LLE_start_length:
    DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, Entry.SectionIndex);
    break;
  default:
    break;
  }
}

void DWARFDebugLoclists::dumpRange(uint64_t StartOffset, uint64_t Size,
                                   raw_ostream &OS, const MCRegisterInfo *MRI,
                                   const DWARFObject &Obj,
                                   DIDumpOptions DumpOpts) {
  if (!Data.isValidOffsetForDataOfSize(StartOffset, Size))  {
    OS << "Invalid dump range\n";
    return;
  }
  uint64_t Offset = StartOffset;
  StringRef Separator;
  bool CanContinue = true;
  while (CanContinue && Offset < StartOffset + Size) {
    OS << Separator;
    Separator = "\n";

    CanContinue = dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj,
                                   nullptr, DumpOpts, /*Indent=*/12);
    OS << '\n';
  }
}
