//===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===//
//
// 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 "HashedNameToDIE.h"
#include "llvm/ADT/StringRef.h"

void DWARFMappedHash::ExtractDIEArray(const DIEInfoArray &die_info_array,
                                      DIEArray &die_offsets) {
  const size_t count = die_info_array.size();
  for (size_t i = 0; i < count; ++i)
    die_offsets.emplace_back(die_info_array[i]);
}

void DWARFMappedHash::ExtractDIEArray(const DIEInfoArray &die_info_array,
                                      const dw_tag_t tag,
                                      DIEArray &die_offsets) {
  if (tag == 0) {
    ExtractDIEArray(die_info_array, die_offsets);
  } else {
    const size_t count = die_info_array.size();
    for (size_t i = 0; i < count; ++i) {
      const dw_tag_t die_tag = die_info_array[i].tag;
      bool tag_matches = die_tag == 0 || tag == die_tag;
      if (!tag_matches) {
        if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
          tag_matches =
              tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
      }
      if (tag_matches)
        die_offsets.emplace_back(die_info_array[i]);
    }
  }
}

void DWARFMappedHash::ExtractDIEArray(const DIEInfoArray &die_info_array,
                                      const dw_tag_t tag,
                                      const uint32_t qualified_name_hash,
                                      DIEArray &die_offsets) {
  if (tag == 0) {
    ExtractDIEArray(die_info_array, die_offsets);
  } else {
    const size_t count = die_info_array.size();
    for (size_t i = 0; i < count; ++i) {
      if (qualified_name_hash != die_info_array[i].qualified_name_hash)
        continue;
      const dw_tag_t die_tag = die_info_array[i].tag;
      bool tag_matches = die_tag == 0 || tag == die_tag;
      if (!tag_matches) {
        if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
          tag_matches =
              tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
      }
      if (tag_matches)
        die_offsets.emplace_back(die_info_array[i]);
    }
  }
}

void DWARFMappedHash::ExtractClassOrStructDIEArray(
    const DIEInfoArray &die_info_array,
    bool return_implementation_only_if_available, DIEArray &die_offsets) {
  const size_t count = die_info_array.size();
  for (size_t i = 0; i < count; ++i) {
    const dw_tag_t die_tag = die_info_array[i].tag;
    if (die_tag == 0 || die_tag == DW_TAG_class_type ||
        die_tag == DW_TAG_structure_type) {
      if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) {
        if (return_implementation_only_if_available) {
          // We found the one true definition for this class, so only return
          // that
          die_offsets.clear();
          die_offsets.emplace_back(die_info_array[i]);
          return;
        } else {
          // Put the one true definition as the first entry so it matches first
          die_offsets.emplace(die_offsets.begin(), die_info_array[i]);
        }
      } else {
        die_offsets.emplace_back(die_info_array[i]);
      }
    }
  }
}

void DWARFMappedHash::ExtractTypesFromDIEArray(
    const DIEInfoArray &die_info_array, uint32_t type_flag_mask,
    uint32_t type_flag_value, DIEArray &die_offsets) {
  const size_t count = die_info_array.size();
  for (size_t i = 0; i < count; ++i) {
    if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
      die_offsets.emplace_back(die_info_array[i]);
  }
}

const char *DWARFMappedHash::GetAtomTypeName(uint16_t atom) {
  switch (atom) {
  case eAtomTypeNULL:
    return "NULL";
  case eAtomTypeDIEOffset:
    return "die-offset";
  case eAtomTypeCUOffset:
    return "cu-offset";
  case eAtomTypeTag:
    return "die-tag";
  case eAtomTypeNameFlags:
    return "name-flags";
  case eAtomTypeTypeFlags:
    return "type-flags";
  case eAtomTypeQualNameHash:
    return "qualified-name-hash";
  }
  return "<invalid>";
}

DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t o, dw_tag_t t, uint32_t f,
                                  uint32_t h)
    : die_offset(o), tag(t), type_flags(f), qualified_name_hash(h) {}

DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset)
    : die_base_offset(_die_base_offset), atoms(), atom_mask(0),
      min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) {
  // Define an array of DIE offsets by first defining an array, and then define
  // the atom type for the array, in this case we have an array of DIE offsets.
  AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4);
}

void DWARFMappedHash::Prologue::ClearAtoms() {
  hash_data_has_fixed_byte_size = true;
  min_hash_data_byte_size = 0;
  atom_mask = 0;
  atoms.clear();
}

bool DWARFMappedHash::Prologue::ContainsAtom(AtomType atom_type) const {
  return (atom_mask & (1u << atom_type)) != 0;
}

void DWARFMappedHash::Prologue::Clear() {
  die_base_offset = 0;
  ClearAtoms();
}

void DWARFMappedHash::Prologue::AppendAtom(AtomType type, dw_form_t form) {
  atoms.push_back({type, form});
  atom_mask |= 1u << type;
  switch (form) {
  case DW_FORM_indirect:
  case DW_FORM_exprloc:
  case DW_FORM_flag_present:
  case DW_FORM_ref_sig8:
    llvm_unreachable("Unhandled atom form");

  case DW_FORM_addrx:
  case DW_FORM_string:
  case DW_FORM_block:
  case DW_FORM_block1:
  case DW_FORM_sdata:
  case DW_FORM_udata:
  case DW_FORM_ref_udata:
  case DW_FORM_GNU_addr_index:
  case DW_FORM_GNU_str_index:
    hash_data_has_fixed_byte_size = false;
    LLVM_FALLTHROUGH;
  case DW_FORM_flag:
  case DW_FORM_data1:
  case DW_FORM_ref1:
  case DW_FORM_sec_offset:
    min_hash_data_byte_size += 1;
    break;

  case DW_FORM_block2:
    hash_data_has_fixed_byte_size = false;
    LLVM_FALLTHROUGH;
  case DW_FORM_data2:
  case DW_FORM_ref2:
    min_hash_data_byte_size += 2;
    break;

  case DW_FORM_block4:
    hash_data_has_fixed_byte_size = false;
    LLVM_FALLTHROUGH;
  case DW_FORM_data4:
  case DW_FORM_ref4:
  case DW_FORM_addr:
  case DW_FORM_ref_addr:
  case DW_FORM_strp:
    min_hash_data_byte_size += 4;
    break;

  case DW_FORM_data8:
  case DW_FORM_ref8:
    min_hash_data_byte_size += 8;
    break;
  }
}

lldb::offset_t
DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data,
                                lldb::offset_t offset) {
  ClearAtoms();

  die_base_offset = data.GetU32(&offset);

  const uint32_t atom_count = data.GetU32(&offset);
  if (atom_count == 0x00060003u) {
    // Old format, deal with contents of old pre-release format.
    while (data.GetU32(&offset)) {
      /* do nothing */;
    }

    // Hardcode to the only known value for now.
    AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4);
  } else {
    for (uint32_t i = 0; i < atom_count; ++i) {
      AtomType type = (AtomType)data.GetU16(&offset);
      dw_form_t form = (dw_form_t)data.GetU16(&offset);
      AppendAtom(type, form);
    }
  }
  return offset;
}

size_t DWARFMappedHash::Prologue::GetByteSize() const {
  // Add an extra count to the atoms size for the zero termination Atom that
  // gets written to disk.
  return sizeof(die_base_offset) + sizeof(uint32_t) +
         atoms.size() * sizeof(Atom);
}

size_t DWARFMappedHash::Prologue::GetMinimumHashDataByteSize() const {
  return min_hash_data_byte_size;
}

bool DWARFMappedHash::Prologue::HashDataHasFixedByteSize() const {
  return hash_data_has_fixed_byte_size;
}

size_t DWARFMappedHash::Header::GetByteSize(const HeaderData &header_data) {
  return header_data.GetByteSize();
}

lldb::offset_t DWARFMappedHash::Header::Read(lldb_private::DataExtractor &data,
                                             lldb::offset_t offset) {
  offset = MappedHash::Header<Prologue>::Read(data, offset);
  if (offset != UINT32_MAX) {
    offset = header_data.Read(data, offset);
  }
  return offset;
}

bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data,
                                   lldb::offset_t *offset_ptr,
                                   DIEInfo &hash_data) const {
  const size_t num_atoms = header_data.atoms.size();
  if (num_atoms == 0)
    return false;

  for (size_t i = 0; i < num_atoms; ++i) {
    DWARFFormValue form_value(nullptr, header_data.atoms[i].form);

    if (!form_value.ExtractValue(data, offset_ptr))
      return false;

    switch (header_data.atoms[i].type) {
    case eAtomTypeDIEOffset: // DIE offset, check form for encoding
      hash_data.die_offset =
          DWARFFormValue::IsDataForm(form_value.Form())
              ? form_value.Unsigned()
              : form_value.Reference(header_data.die_base_offset);
      break;

    case eAtomTypeTag: // DW_TAG value for the DIE
      hash_data.tag = (dw_tag_t)form_value.Unsigned();
      break;

    case eAtomTypeTypeFlags: // Flags from enum TypeFlags
      hash_data.type_flags = (uint32_t)form_value.Unsigned();
      break;

    case eAtomTypeQualNameHash: // Flags from enum TypeFlags
      hash_data.qualified_name_hash = form_value.Unsigned();
      break;

    default:
      // We can always skip atoms we don't know about.
      break;
    }
  }
  return hash_data.die_offset != DW_INVALID_OFFSET;
}

DWARFMappedHash::MemoryTable::MemoryTable(
    lldb_private::DWARFDataExtractor &table_data,
    const lldb_private::DWARFDataExtractor &string_table, const char *name)
    : MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray>(table_data),
      m_data(table_data), m_string_table(string_table), m_name(name) {}

const char *
DWARFMappedHash::MemoryTable::GetStringForKeyType(KeyType key) const {
  // The key in the DWARF table is the .debug_str offset for the string
  return m_string_table.PeekCStr(key);
}

bool DWARFMappedHash::MemoryTable::ReadHashData(uint32_t hash_data_offset,
                                                HashData &hash_data) const {
  lldb::offset_t offset = hash_data_offset;
  // Skip string table offset that contains offset of hash name in .debug_str.
  offset += 4;
  const uint32_t count = m_data.GetU32(&offset);
  if (count > 0) {
    hash_data.resize(count);
    for (uint32_t i = 0; i < count; ++i) {
      if (!m_header.Read(m_data, &offset, hash_data[i]))
        return false;
    }
  } else
    hash_data.clear();
  return true;
}

DWARFMappedHash::MemoryTable::Result
DWARFMappedHash::MemoryTable::GetHashDataForName(
    llvm::StringRef name, lldb::offset_t *hash_data_offset_ptr,
    Pair &pair) const {
  pair.key = m_data.GetU32(hash_data_offset_ptr);
  pair.value.clear();

  // If the key is zero, this terminates our chain of HashData objects for this
  // hash value.
  if (pair.key == 0)
    return eResultEndOfHashData;

  // There definitely should be a string for this string offset, if there
  // isn't, there is something wrong, return and error.
  const char *strp_cstr = m_string_table.PeekCStr(pair.key);
  if (strp_cstr == nullptr) {
    *hash_data_offset_ptr = UINT32_MAX;
    return eResultError;
  }

  const uint32_t count = m_data.GetU32(hash_data_offset_ptr);
  const size_t min_total_hash_data_size =
      count * m_header.header_data.GetMinimumHashDataByteSize();
  if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr,
                                                   min_total_hash_data_size)) {
    // We have at least one HashData entry, and we have enough data to parse at
    // least "count" HashData entries.

    // First make sure the entire C string matches...
    const bool match = name == strp_cstr;

    if (!match && m_header.header_data.HashDataHasFixedByteSize()) {
      // If the string doesn't match and we have fixed size data, we can just
      // add the total byte size of all HashData objects to the hash data
      // offset and be done...
      *hash_data_offset_ptr += min_total_hash_data_size;
    } else {
      // If the string does match, or we don't have fixed size data then we
      // need to read the hash data as a stream. If the string matches we also
      // append all HashData objects to the value array.
      for (uint32_t i = 0; i < count; ++i) {
        DIEInfo die_info;
        if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) {
          // Only happened if the HashData of the string matched...
          if (match)
            pair.value.push_back(die_info);
        } else {
          // Something went wrong while reading the data.
          *hash_data_offset_ptr = UINT32_MAX;
          return eResultError;
        }
      }
    }
    // Return the correct response depending on if the string matched or not...
    if (match) {
      // The key (cstring) matches and we have lookup results!
      return eResultKeyMatch;
    } else {
      // The key doesn't match, this function will get called again for the
      // next key/value or the key terminator which in our case is a zero
      // .debug_str offset.
      return eResultKeyMismatch;
    }
  } else {
    *hash_data_offset_ptr = UINT32_MAX;
    return eResultError;
  }
}

DWARFMappedHash::MemoryTable::Result
DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
    const lldb_private::RegularExpression &regex,
    lldb::offset_t *hash_data_offset_ptr, Pair &pair) const {
  pair.key = m_data.GetU32(hash_data_offset_ptr);
  // If the key is zero, this terminates our chain of HashData objects for this
  // hash value.
  if (pair.key == 0)
    return eResultEndOfHashData;

  // There definitely should be a string for this string offset, if there
  // isn't, there is something wrong, return and error.
  const char *strp_cstr = m_string_table.PeekCStr(pair.key);
  if (strp_cstr == nullptr)
    return eResultError;

  const uint32_t count = m_data.GetU32(hash_data_offset_ptr);
  const size_t min_total_hash_data_size =
      count * m_header.header_data.GetMinimumHashDataByteSize();
  if (count > 0 && m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr,
                                                   min_total_hash_data_size)) {
    const bool match = regex.Execute(llvm::StringRef(strp_cstr));

    if (!match && m_header.header_data.HashDataHasFixedByteSize()) {
      // If the regex doesn't match and we have fixed size data, we can just
      // add the total byte size of all HashData objects to the hash data
      // offset and be done...
      *hash_data_offset_ptr += min_total_hash_data_size;
    } else {
      // If the string does match, or we don't have fixed size data then we
      // need to read the hash data as a stream. If the string matches we also
      // append all HashData objects to the value array.
      for (uint32_t i = 0; i < count; ++i) {
        DIEInfo die_info;
        if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) {
          // Only happened if the HashData of the string matched...
          if (match)
            pair.value.push_back(die_info);
        } else {
          // Something went wrong while reading the data
          *hash_data_offset_ptr = UINT32_MAX;
          return eResultError;
        }
      }
    }
    // Return the correct response depending on if the string matched or not...
    if (match) {
      // The key (cstring) matches and we have lookup results!
      return eResultKeyMatch;
    } else {
      // The key doesn't match, this function will get called again for the
      // next key/value or the key terminator which in our case is a zero
      // .debug_str offset.
      return eResultKeyMismatch;
    }
  } else {
    *hash_data_offset_ptr = UINT32_MAX;
    return eResultError;
  }
}

size_t DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex(
    const lldb_private::RegularExpression &regex,
    DIEInfoArray &die_info_array) const {
  const uint32_t hash_count = m_header.hashes_count;
  Pair pair;
  for (uint32_t offset_idx = 0; offset_idx < hash_count; ++offset_idx) {
    lldb::offset_t hash_data_offset = GetHashDataOffset(offset_idx);
    while (hash_data_offset != UINT32_MAX) {
      const lldb::offset_t prev_hash_data_offset = hash_data_offset;
      Result hash_result =
          AppendHashDataForRegularExpression(regex, &hash_data_offset, pair);
      if (prev_hash_data_offset == hash_data_offset)
        break;

      // Check the result of getting our hash data.
      switch (hash_result) {
      case eResultKeyMatch:
      case eResultKeyMismatch:
        // Whether we matches or not, it doesn't matter, we keep looking.
        break;

      case eResultEndOfHashData:
      case eResultError:
        hash_data_offset = UINT32_MAX;
        break;
      }
    }
  }
  die_info_array.swap(pair.value);
  return die_info_array.size();
}

size_t DWARFMappedHash::MemoryTable::AppendAllDIEsInRange(
    const uint32_t die_offset_start, const uint32_t die_offset_end,
    DIEInfoArray &die_info_array) const {
  const uint32_t hash_count = m_header.hashes_count;
  for (uint32_t offset_idx = 0; offset_idx < hash_count; ++offset_idx) {
    bool done = false;
    lldb::offset_t hash_data_offset = GetHashDataOffset(offset_idx);
    while (!done && hash_data_offset != UINT32_MAX) {
      KeyType key = m_data.GetU32(&hash_data_offset);
      // If the key is zero, this terminates our chain of HashData objects for
      // this hash value.
      if (key == 0)
        break;

      const uint32_t count = m_data.GetU32(&hash_data_offset);
      for (uint32_t i = 0; i < count; ++i) {
        DIEInfo die_info;
        if (m_header.Read(m_data, &hash_data_offset, die_info)) {
          if (die_info.die_offset == 0)
            done = true;
          if (die_offset_start <= die_info.die_offset &&
              die_info.die_offset < die_offset_end)
            die_info_array.push_back(die_info);
        }
      }
    }
  }
  return die_info_array.size();
}

size_t DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name,
                                                DIEArray &die_offsets) {
  if (name.empty())
    return 0;

  DIEInfoArray die_info_array;
  if (FindByName(name, die_info_array))
    DWARFMappedHash::ExtractDIEArray(die_info_array, die_offsets);
  return die_info_array.size();
}

size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(llvm::StringRef name,
                                                      const dw_tag_t tag,
                                                      DIEArray &die_offsets) {
  DIEInfoArray die_info_array;
  if (FindByName(name, die_info_array))
    DWARFMappedHash::ExtractDIEArray(die_info_array, tag, die_offsets);
  return die_info_array.size();
}

size_t DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash(
    llvm::StringRef name, const dw_tag_t tag,
    const uint32_t qualified_name_hash, DIEArray &die_offsets) {
  DIEInfoArray die_info_array;
  if (FindByName(name, die_info_array))
    DWARFMappedHash::ExtractDIEArray(die_info_array, tag, qualified_name_hash,
                                     die_offsets);
  return die_info_array.size();
}

size_t DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName(
    llvm::StringRef name, DIEArray &die_offsets, bool must_be_implementation) {
  DIEInfoArray die_info_array;
  if (FindByName(name, die_info_array)) {
    if (must_be_implementation &&
        GetHeader().header_data.ContainsAtom(eAtomTypeTypeFlags)) {
      // If we have two atoms, then we have the DIE offset and the type flags
      // so we can find the objective C class efficiently.
      DWARFMappedHash::ExtractTypesFromDIEArray(die_info_array, UINT32_MAX,
                                                eTypeFlagClassIsImplementation,
                                                die_offsets);
    } else {
      // We don't only want the one true definition, so try and see what we can
      // find, and only return class or struct DIEs. If we do have the full
      // implementation, then return it alone, else return all possible
      // matches.
      const bool return_implementation_only_if_available = true;
      DWARFMappedHash::ExtractClassOrStructDIEArray(
          die_info_array, return_implementation_only_if_available, die_offsets);
    }
  }
  return die_offsets.size();
}

size_t DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name,
                                                DIEInfoArray &die_info_array) {
  if (name.empty())
    return 0;

  Pair kv_pair;
  size_t old_size = die_info_array.size();
  if (Find(name, kv_pair)) {
    die_info_array.swap(kv_pair.value);
    return die_info_array.size() - old_size;
  }
  return 0;
}
