//===- DWARFDebugAddr.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/DWARFDebugAddr.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"

using namespace llvm;

Error DWARFDebugAddrTable::extractAddresses(const DWARFDataExtractor &Data,
                                            uint64_t *OffsetPtr,
                                            uint64_t EndOffset) {
  assert(EndOffset >= *OffsetPtr);
  uint64_t DataSize = EndOffset - *OffsetPtr;
  assert(Data.isValidOffsetForDataOfSize(*OffsetPtr, DataSize));
  if (AddrSize != 4 && AddrSize != 8)
    return createStringError(errc::not_supported,
                             "address table at offset 0x%" PRIx64
                             " has unsupported address size %" PRIu8
                             " (4 and 8 are supported)",
                             Offset, AddrSize);
  if (DataSize % AddrSize != 0) {
    invalidateLength();
    return createStringError(errc::invalid_argument,
                             "address table at offset 0x%" PRIx64
                             " contains data of size 0x%" PRIx64
                             " which is not a multiple of addr size %" PRIu8,
                             Offset, DataSize, AddrSize);
  }
  Addrs.clear();
  size_t Count = DataSize / AddrSize;
  Addrs.reserve(Count);
  while (Count--)
    Addrs.push_back(Data.getRelocatedValue(AddrSize, OffsetPtr));
  return Error::success();
}

Error DWARFDebugAddrTable::extractV5(const DWARFDataExtractor &Data,
                                     uint64_t *OffsetPtr, uint8_t CUAddrSize,
                                     std::function<void(Error)> WarnCallback) {
  Offset = *OffsetPtr;
  llvm::Error Err = Error::success();
  std::tie(Length, Format) = Data.getInitialLength(OffsetPtr, &Err);
  if (Err) {
    invalidateLength();
    return createStringError(errc::invalid_argument,
                             "parsing address table at offset 0x%" PRIx64
                             ": %s",
                             Offset, toString(std::move(Err)).c_str());
  }

  if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, Length)) {
    uint64_t DiagnosticLength = Length;
    invalidateLength();
    return createStringError(
        errc::invalid_argument,
        "section is not large enough to contain an address table "
        "at offset 0x%" PRIx64 " with a unit_length value of 0x%" PRIx64,
        Offset, DiagnosticLength);
  }
  uint64_t EndOffset = *OffsetPtr + Length;
  // Ensure that we can read the remaining header fields.
  if (Length < 4) {
    uint64_t DiagnosticLength = Length;
    invalidateLength();
    return createStringError(
        errc::invalid_argument,
        "address table at offset 0x%" PRIx64
        " has a unit_length value of 0x%" PRIx64
        ", which is too small to contain a complete header",
        Offset, DiagnosticLength);
  }

  Version = Data.getU16(OffsetPtr);
  AddrSize = Data.getU8(OffsetPtr);
  SegSize = Data.getU8(OffsetPtr);

  // Perform a basic validation of the header fields.
  if (Version != 5)
    return createStringError(errc::not_supported,
                             "address table at offset 0x%" PRIx64
                             " has unsupported version %" PRIu16,
                             Offset, Version);
  // TODO: add support for non-zero segment selector size.
  if (SegSize != 0)
    return createStringError(errc::not_supported,
                             "address table at offset 0x%" PRIx64
                             " has unsupported segment selector size %" PRIu8,
                             Offset, SegSize);

  if (Error Err = extractAddresses(Data, OffsetPtr, EndOffset))
    return Err;
  if (CUAddrSize && AddrSize != CUAddrSize) {
    WarnCallback(createStringError(
        errc::invalid_argument,
        "address table at offset 0x%" PRIx64 " has address size %" PRIu8
        " which is different from CU address size %" PRIu8,
        Offset, AddrSize, CUAddrSize));
  }
  return Error::success();
}

Error DWARFDebugAddrTable::extractPreStandard(const DWARFDataExtractor &Data,
                                              uint64_t *OffsetPtr,
                                              uint16_t CUVersion,
                                              uint8_t CUAddrSize) {
  assert(CUVersion > 0 && CUVersion < 5);

  Offset = *OffsetPtr;
  Length = 0;
  Version = CUVersion;
  AddrSize = CUAddrSize;
  SegSize = 0;

  return extractAddresses(Data, OffsetPtr, Data.size());
}

Error DWARFDebugAddrTable::extract(const DWARFDataExtractor &Data,
                                   uint64_t *OffsetPtr,
                                   uint16_t CUVersion,
                                   uint8_t CUAddrSize,
                                   std::function<void(Error)> WarnCallback) {
  if (CUVersion > 0 && CUVersion < 5)
    return extractPreStandard(Data, OffsetPtr, CUVersion, CUAddrSize);
  if (CUVersion == 0)
    WarnCallback(createStringError(errc::invalid_argument,
                                   "DWARF version is not defined in CU,"
                                   " assuming version 5"));
  return extractV5(Data, OffsetPtr, CUAddrSize, WarnCallback);
}

void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {
  if (DumpOpts.Verbose)
    OS << format("0x%8.8" PRIx64 ": ", Offset);
  if (Length) {
    int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);
    OS << "Address table header: "
       << format("length = 0x%0*" PRIx64, OffsetDumpWidth, Length)
       << ", format = " << dwarf::FormatString(Format)
       << format(", version = 0x%4.4" PRIx16, Version)
       << format(", addr_size = 0x%2.2" PRIx8, AddrSize)
       << format(", seg_size = 0x%2.2" PRIx8, SegSize) << "\n";
  }

  if (Addrs.size() > 0) {
    const char *AddrFmt =
        (AddrSize == 4) ? "0x%8.8" PRIx64 "\n" : "0x%16.16" PRIx64 "\n";
    OS << "Addrs: [\n";
    for (uint64_t Addr : Addrs)
      OS << format(AddrFmt, Addr);
    OS << "]\n";
  }
}

Expected<uint64_t> DWARFDebugAddrTable::getAddrEntry(uint32_t Index) const {
  if (Index < Addrs.size())
    return Addrs[Index];
  return createStringError(errc::invalid_argument,
                           "Index %" PRIu32 " is out of range of the "
                           "address table at offset 0x%" PRIx64,
                           Index, Offset);
}

Optional<uint64_t> DWARFDebugAddrTable::getFullLength() const {
  if (Length == 0)
    return None;
  return Length + dwarf::getUnitLengthFieldByteSize(Format);
}

