//===- DWARFGdbIndex.cpp --------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cinttypes>
#include <cstdint>
#include <utility>

using namespace llvm;

// .gdb_index section format reference:
// https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html

void DWARFGdbIndex::dumpCUList(raw_ostream &OS) const {
  OS << format("\n  CU list offset = 0x%x, has %" PRId64 " entries:",
               CuListOffset, (uint64_t)CuList.size())
     << '\n';
  uint32_t I = 0;
  for (const CompUnitEntry &CU : CuList)
    OS << format("    %d: Offset = 0x%llx, Length = 0x%llx\n", I++, CU.Offset,
                 CU.Length);
}

void DWARFGdbIndex::dumpTUList(raw_ostream &OS) const {
  OS << formatv("\n  Types CU list offset = {0:x}, has {1} entries:\n",
                TuListOffset, TuList.size());
  uint32_t I = 0;
  for (const TypeUnitEntry &TU : TuList)
    OS << formatv("    {0}: offset = {1:x8}, type_offset = {2:x8}, "
                  "type_signature = {3:x16}\n",
                  I++, TU.Offset, TU.TypeOffset, TU.TypeSignature);
}

void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const {
  OS << format("\n  Address area offset = 0x%x, has %" PRId64 " entries:",
               AddressAreaOffset, (uint64_t)AddressArea.size())
     << '\n';
  for (const AddressEntry &Addr : AddressArea)
    OS << format(
        "    Low/High address = [0x%llx, 0x%llx) (Size: 0x%llx), CU id = %d\n",
        Addr.LowAddress, Addr.HighAddress, Addr.HighAddress - Addr.LowAddress,
        Addr.CuIndex);
}

void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const {
  OS << format("\n  Symbol table offset = 0x%x, size = %" PRId64
               ", filled slots:",
               SymbolTableOffset, (uint64_t)SymbolTable.size())
     << '\n';
  uint32_t I = -1;
  for (const SymTableEntry &E : SymbolTable) {
    ++I;
    if (!E.NameOffset && !E.VecOffset)
      continue;

    OS << format("    %d: Name offset = 0x%x, CU vector offset = 0x%x\n", I,
                 E.NameOffset, E.VecOffset);

    StringRef Name = ConstantPoolStrings.substr(
        ConstantPoolOffset - StringPoolOffset + E.NameOffset);

    auto CuVector = std::find_if(
        ConstantPoolVectors.begin(), ConstantPoolVectors.end(),
        [&](const std::pair<uint32_t, SmallVector<uint32_t, 0>> &V) {
          return V.first == E.VecOffset;
        });
    assert(CuVector != ConstantPoolVectors.end() && "Invalid symbol table");
    uint32_t CuVectorId = CuVector - ConstantPoolVectors.begin();
    OS << format("      String name: %s, CU vector index: %d\n", Name.data(),
                 CuVectorId);
  }
}

void DWARFGdbIndex::dumpConstantPool(raw_ostream &OS) const {
  OS << format("\n  Constant pool offset = 0x%x, has %" PRId64 " CU vectors:",
               ConstantPoolOffset, (uint64_t)ConstantPoolVectors.size());
  uint32_t I = 0;
  for (const auto &V : ConstantPoolVectors) {
    OS << format("\n    %d(0x%x): ", I++, V.first);
    for (uint32_t Val : V.second)
      OS << format("0x%x ", Val);
  }
  OS << '\n';
}

void DWARFGdbIndex::dump(raw_ostream &OS) {
  if (HasError) {
    OS << "\n<error parsing>\n";
    return;
  }

  if (HasContent) {
    OS << "  Version = " << Version << '\n';
    dumpCUList(OS);
    dumpTUList(OS);
    dumpAddressArea(OS);
    dumpSymbolTable(OS);
    dumpConstantPool(OS);
  }
}

bool DWARFGdbIndex::parseImpl(DataExtractor Data) {
  uint32_t Offset = 0;

  // Only version 7 is supported at this moment.
  Version = Data.getU32(&Offset);
  if (Version != 7)
    return false;

  CuListOffset = Data.getU32(&Offset);
  uint32_t CuTypesOffset = Data.getU32(&Offset);
  AddressAreaOffset = Data.getU32(&Offset);
  SymbolTableOffset = Data.getU32(&Offset);
  ConstantPoolOffset = Data.getU32(&Offset);

  if (Offset != CuListOffset)
    return false;

  uint32_t CuListSize = (CuTypesOffset - CuListOffset) / 16;
  CuList.reserve(CuListSize);
  for (uint32_t i = 0; i < CuListSize; ++i) {
    uint64_t CuOffset = Data.getU64(&Offset);
    uint64_t CuLength = Data.getU64(&Offset);
    CuList.push_back({CuOffset, CuLength});
  }

  // CU Types are no longer needed as DWARF skeleton type units never made it
  // into the standard.
  uint32_t TuListSize = (AddressAreaOffset - CuTypesOffset) / 24;
  TuList.resize(TuListSize);
  for (uint32_t I = 0; I < TuListSize; ++I) {
    uint64_t CuOffset = Data.getU64(&Offset);
    uint64_t TypeOffset = Data.getU64(&Offset);
    uint64_t Signature = Data.getU64(&Offset);
    TuList[I] = {CuOffset, TypeOffset, Signature};
  }

  uint32_t AddressAreaSize = (SymbolTableOffset - AddressAreaOffset) / 20;
  AddressArea.reserve(AddressAreaSize);
  for (uint32_t i = 0; i < AddressAreaSize; ++i) {
    uint64_t LowAddress = Data.getU64(&Offset);
    uint64_t HighAddress = Data.getU64(&Offset);
    uint32_t CuIndex = Data.getU32(&Offset);
    AddressArea.push_back({LowAddress, HighAddress, CuIndex});
  }

  // The symbol table. This is an open addressed hash table. The size of the
  // hash table is always a power of 2.
  // Each slot in the hash table consists of a pair of offset_type values. The
  // first value is the offset of the symbol's name in the constant pool. The
  // second value is the offset of the CU vector in the constant pool.
  // If both values are 0, then this slot in the hash table is empty. This is ok
  // because while 0 is a valid constant pool index, it cannot be a valid index
  // for both a string and a CU vector.
  uint32_t SymTableSize = (ConstantPoolOffset - SymbolTableOffset) / 8;
  SymbolTable.reserve(SymTableSize);
  uint32_t CuVectorsTotal = 0;
  for (uint32_t i = 0; i < SymTableSize; ++i) {
    uint32_t NameOffset = Data.getU32(&Offset);
    uint32_t CuVecOffset = Data.getU32(&Offset);
    SymbolTable.push_back({NameOffset, CuVecOffset});
    if (NameOffset || CuVecOffset)
      ++CuVectorsTotal;
  }

  // The constant pool. CU vectors are stored first, followed by strings.
  // The first value is the number of CU indices in the vector. Each subsequent
  // value is the index and symbol attributes of a CU in the CU list.
  for (uint32_t i = 0; i < CuVectorsTotal; ++i) {
    ConstantPoolVectors.emplace_back(0, SmallVector<uint32_t, 0>());
    auto &Vec = ConstantPoolVectors.back();
    Vec.first = Offset - ConstantPoolOffset;

    uint32_t Num = Data.getU32(&Offset);
    for (uint32_t j = 0; j < Num; ++j)
      Vec.second.push_back(Data.getU32(&Offset));
  }

  ConstantPoolStrings = Data.getData().drop_front(Offset);
  StringPoolOffset = Offset;
  return true;
}

void DWARFGdbIndex::parse(DataExtractor Data) {
  HasContent = !Data.getData().empty();
  HasError = HasContent && !parseImpl(Data);
}
