//===-- SymbolFileCTF.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 "SymbolFileCTF.h"

#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Config.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symtab.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StreamBuffer.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_ZLIB
#include "llvm/Support/MemoryBuffer.h"

#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"

#include <memory>
#include <optional>

#if LLVM_ENABLE_ZLIB
#include <zlib.h>
#endif

using namespace llvm;
using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(SymbolFileCTF)

char SymbolFileCTF::ID;

SymbolFileCTF::SymbolFileCTF(lldb::ObjectFileSP objfile_sp)
    : SymbolFileCommon(std::move(objfile_sp)) {}

void SymbolFileCTF::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance);
}

void SymbolFileCTF::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

llvm::StringRef SymbolFileCTF::GetPluginDescriptionStatic() {
  return "Compact C Type Format Symbol Reader";
}

SymbolFile *SymbolFileCTF::CreateInstance(ObjectFileSP objfile_sp) {
  return new SymbolFileCTF(std::move(objfile_sp));
}

bool SymbolFileCTF::ParseHeader() {
  if (m_header)
    return true;

  Log *log = GetLog(LLDBLog::Symbols);

  ModuleSP module_sp(m_objfile_sp->GetModule());
  const SectionList *section_list = module_sp->GetSectionList();
  if (!section_list)
    return false;

  SectionSP section_sp(
      section_list->FindSectionByType(lldb::eSectionTypeCTF, true));
  if (!section_sp)
    return false;

  m_objfile_sp->ReadSectionData(section_sp.get(), m_data);

  if (m_data.GetByteSize() == 0)
    return false;

  StreamString module_desc;
  GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
                                               lldb::eDescriptionLevelBrief);
  LLDB_LOG(log, "Parsing Compact C Type format for {0}", module_desc.GetData());

  lldb::offset_t offset = 0;

  // Parse CTF header.
  constexpr size_t ctf_header_size = sizeof(ctf_header_t);
  if (!m_data.ValidOffsetForDataOfSize(offset, ctf_header_size)) {
    LLDB_LOG(log, "CTF parsing failed: insufficient data for CTF header");
    return false;
  }

  m_header.emplace();

  ctf_header_t &ctf_header = *m_header;
  ctf_header.preamble.magic = m_data.GetU16(&offset);
  ctf_header.preamble.version = m_data.GetU8(&offset);
  ctf_header.preamble.flags = m_data.GetU8(&offset);
  ctf_header.parlabel = m_data.GetU32(&offset);
  ctf_header.parname = m_data.GetU32(&offset);
  ctf_header.lbloff = m_data.GetU32(&offset);
  ctf_header.objtoff = m_data.GetU32(&offset);
  ctf_header.funcoff = m_data.GetU32(&offset);
  ctf_header.typeoff = m_data.GetU32(&offset);
  ctf_header.stroff = m_data.GetU32(&offset);
  ctf_header.strlen = m_data.GetU32(&offset);

  // Validate the preamble.
  if (ctf_header.preamble.magic != g_ctf_magic) {
    LLDB_LOG(log, "CTF parsing failed: invalid magic: {0:x}",
             ctf_header.preamble.magic);
    return false;
  }

  if (ctf_header.preamble.version != g_ctf_version) {
    LLDB_LOG(log, "CTF parsing failed: unsupported version: {0}",
             ctf_header.preamble.version);
    return false;
  }

  LLDB_LOG(log, "Parsed valid CTF preamble: version {0}, flags {1:x}",
           ctf_header.preamble.version, ctf_header.preamble.flags);

  m_body_offset = offset;

  if (ctf_header.preamble.flags & eFlagCompress) {
    // The body has been compressed with zlib deflate. Header offsets point into
    // the decompressed data.
#if LLVM_ENABLE_ZLIB
    const std::size_t decompressed_size = ctf_header.stroff + ctf_header.strlen;
    DataBufferSP decompressed_data =
        std::make_shared<DataBufferHeap>(decompressed_size, 0x0);

    z_stream zstr;
    memset(&zstr, 0, sizeof(zstr));
    zstr.next_in = (Bytef *)const_cast<uint8_t *>(m_data.GetDataStart() +
                                                  sizeof(ctf_header_t));
    zstr.avail_in = m_data.BytesLeft(offset);
    zstr.next_out =
        (Bytef *)const_cast<uint8_t *>(decompressed_data->GetBytes());
    zstr.avail_out = decompressed_size;

    int rc = inflateInit(&zstr);
    if (rc != Z_OK) {
      LLDB_LOG(log, "CTF parsing failed: inflate initialization error: {0}",
               zError(rc));
      return false;
    }

    rc = inflate(&zstr, Z_FINISH);
    if (rc != Z_STREAM_END) {
      LLDB_LOG(log, "CTF parsing failed: inflate error: {0}", zError(rc));
      return false;
    }

    rc = inflateEnd(&zstr);
    if (rc != Z_OK) {
      LLDB_LOG(log, "CTF parsing failed: inflate end error: {0}", zError(rc));
      return false;
    }

    if (zstr.total_out != decompressed_size) {
      LLDB_LOG(log,
               "CTF parsing failed: decompressed size ({0}) doesn't match "
               "expected size ([1})",
               zstr.total_out, decompressed_size);
      return false;
    }

    m_data = DataExtractor(decompressed_data, m_data.GetByteOrder(),
                           m_data.GetAddressByteSize());
    m_body_offset = 0;
#else
    LLDB_LOG(
        log,
        "CTF parsing failed: data is compressed but no zlib inflate support");
    return false;
#endif
  }

  // Validate the header.
  if (!m_data.ValidOffset(m_body_offset + ctf_header.lbloff)) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid label section offset in header: {0}",
             ctf_header.lbloff);
    return false;
  }

  if (!m_data.ValidOffset(m_body_offset + ctf_header.objtoff)) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid object section offset in header: {0}",
             ctf_header.objtoff);
    return false;
  }

  if (!m_data.ValidOffset(m_body_offset + ctf_header.funcoff)) {
    LLDB_LOG(
        log,
        "CTF parsing failed: invalid function section offset in header: {0}",
        ctf_header.funcoff);
    return false;
  }

  if (!m_data.ValidOffset(m_body_offset + ctf_header.typeoff)) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid type section offset in header: {0}",
             ctf_header.typeoff);
    return false;
  }

  if (!m_data.ValidOffset(m_body_offset + ctf_header.stroff)) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid string section offset in header: {0}",
             ctf_header.stroff);
    return false;
  }

  const lldb::offset_t str_end_offset =
      m_body_offset + ctf_header.stroff + ctf_header.strlen;
  if (!m_data.ValidOffset(str_end_offset - 1)) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid string section length in header: {0}",
             ctf_header.strlen);
    return false;
  }

  if (m_body_offset + ctf_header.stroff + ctf_header.parlabel >
      str_end_offset) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid parent label offset: {0} exceeds end "
             "of string section ({1})",
             ctf_header.parlabel, str_end_offset);
    return false;
  }

  if (m_body_offset + ctf_header.stroff + ctf_header.parname > str_end_offset) {
    LLDB_LOG(log,
             "CTF parsing failed: invalid parent name offset: {0} exceeds end "
             "of string section ({1})",
             ctf_header.parname, str_end_offset);
    return false;
  }

  LLDB_LOG(log,
           "Parsed valid CTF header: lbloff  = {0}, objtoff = {1}, funcoff = "
           "{2}, typeoff = {3}, stroff = {4}, strlen = {5}",
           ctf_header.lbloff, ctf_header.objtoff, ctf_header.funcoff,
           ctf_header.typeoff, ctf_header.stroff, ctf_header.strlen);

  return true;
}

void SymbolFileCTF::InitializeObject() {
  Log *log = GetLog(LLDBLog::Symbols);

  auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC);
  if (auto err = type_system_or_err.takeError()) {
    LLDB_LOG_ERROR(log, std::move(err), "Unable to get type system: {0}");
    return;
  }

  auto ts = *type_system_or_err;
  m_ast = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
  LazyBool optimized = eLazyBoolNo;
  m_comp_unit_sp = std::make_shared<CompileUnit>(
      m_objfile_sp->GetModule(), nullptr, "", 0, eLanguageTypeC, optimized);

  ParseTypes(*m_comp_unit_sp);
}

llvm::StringRef SymbolFileCTF::ReadString(lldb::offset_t str_offset) const {
  lldb::offset_t offset = m_body_offset + m_header->stroff + str_offset;
  if (!m_data.ValidOffset(offset))
    return "(invalid)";
  const char *str = m_data.GetCStr(&offset);
  if (str && !*str)
    return "(anon)";
  return llvm::StringRef(str);
}

/// Return the integer display representation encoded in the given data.
static uint32_t GetEncoding(uint32_t data) {
  // Mask bits 24–31.
  return ((data)&0xff000000) >> 24;
}

/// Return the integral width in bits encoded in the given data.
static uint32_t GetBits(uint32_t data) {
  // Mask bits 0-15.
  return (data)&0x0000ffff;
}

/// Return the type kind encoded in the given data.
uint32_t GetKind(uint32_t data) {
  // Mask bits 26–31.
  return ((data)&0xf800) >> 11;
}

/// Return the variable length encoded in the given data.
uint32_t GetVLen(uint32_t data) {
  // Mask bits 0–24.
  return (data)&0x3ff;
}

static uint32_t GetBytes(uint32_t bits) { return bits / sizeof(unsigned); }

static clang::TagTypeKind TranslateRecordKind(CTFType::Kind type) {
  switch (type) {
  case CTFType::Kind::eStruct:
    return clang::TagTypeKind::Struct;
  case CTFType::Kind::eUnion:
    return clang::TagTypeKind::Union;
  default:
    lldbassert(false && "Invalid record kind!");
    return clang::TagTypeKind::Struct;
  }
}

llvm::Expected<TypeSP>
SymbolFileCTF::CreateInteger(const CTFInteger &ctf_integer) {
  lldb::BasicType basic_type =
      TypeSystemClang::GetBasicTypeEnumeration(ctf_integer.name);
  if (basic_type == eBasicTypeInvalid)
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("unsupported integer type: no corresponding basic clang "
                      "type for '{0}'",
                      ctf_integer.name),
        llvm::inconvertibleErrorCode());

  CompilerType compiler_type = m_ast->GetBasicType(basic_type);

  if (basic_type != eBasicTypeVoid && basic_type != eBasicTypeBool) {
    // Make sure the type we got is an integer type.
    bool compiler_type_is_signed = false;
    if (!compiler_type.IsIntegerType(compiler_type_is_signed))
      return llvm::make_error<llvm::StringError>(
          llvm::formatv(
              "Found compiler type for '{0}' but it's not an integer type: {1}",
              ctf_integer.name,
              compiler_type.GetDisplayTypeName().GetStringRef()),
          llvm::inconvertibleErrorCode());

    // Make sure the signing matches between the CTF and the compiler type.
    const bool type_is_signed = (ctf_integer.encoding & IntEncoding::eSigned);
    if (compiler_type_is_signed != type_is_signed)
      return llvm::make_error<llvm::StringError>(
          llvm::formatv("Found integer compiler type for {0} but compiler type "
                        "is {1} and {0} is {2}",
                        ctf_integer.name,
                        compiler_type_is_signed ? "signed" : "unsigned",
                        type_is_signed ? "signed" : "unsigned"),
          llvm::inconvertibleErrorCode());
  }

  Declaration decl;
  return MakeType(ctf_integer.uid, ConstString(ctf_integer.name),
                  GetBytes(ctf_integer.bits), nullptr, LLDB_INVALID_UID,
                  lldb_private::Type::eEncodingIsUID, decl, compiler_type,
                  lldb_private::Type::ResolveState::Full);
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateModifier(const CTFModifier &ctf_modifier) {
  Type *ref_type = ResolveTypeUID(ctf_modifier.type);
  if (!ref_type)
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("Could not find modified type: {0}", ctf_modifier.type),
        llvm::inconvertibleErrorCode());

  CompilerType compiler_type;

  switch (ctf_modifier.kind) {
  case CTFType::ePointer:
    compiler_type = ref_type->GetFullCompilerType().GetPointerType();
    break;
  case CTFType::eConst:
    compiler_type = ref_type->GetFullCompilerType().AddConstModifier();
    break;
  case CTFType::eVolatile:
    compiler_type = ref_type->GetFullCompilerType().AddVolatileModifier();
    break;
  case CTFType::eRestrict:
    compiler_type = ref_type->GetFullCompilerType().AddRestrictModifier();
    break;
  default:
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("ParseModifier called with unsupported kind: {0}",
                      ctf_modifier.kind),
        llvm::inconvertibleErrorCode());
  }

  Declaration decl;
  return MakeType(ctf_modifier.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,
                  Type::eEncodingIsUID, decl, compiler_type,
                  lldb_private::Type::ResolveState::Full);
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateTypedef(const CTFTypedef &ctf_typedef) {
  Type *underlying_type = ResolveTypeUID(ctf_typedef.type);
  if (!underlying_type)
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("Could not find typedef underlying type: {0}",
                      ctf_typedef.type),
        llvm::inconvertibleErrorCode());

  CompilerType target_ast_type = underlying_type->GetFullCompilerType();
  clang::DeclContext *decl_ctx = m_ast->GetTranslationUnitDecl();
  CompilerType ast_typedef = target_ast_type.CreateTypedef(
      ctf_typedef.name.data(), m_ast->CreateDeclContext(decl_ctx), 0);

  Declaration decl;
  return MakeType(ctf_typedef.uid, ConstString(ctf_typedef.name), 0, nullptr,
                  LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
                  ast_typedef, lldb_private::Type::ResolveState::Full);
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateArray(const CTFArray &ctf_array) {
  Type *element_type = ResolveTypeUID(ctf_array.type);
  if (!element_type)
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("Could not find array element type: {0}", ctf_array.type),
        llvm::inconvertibleErrorCode());

  auto element_size_or_err = element_type->GetByteSize(nullptr);
  if (!element_size_or_err)
    return element_size_or_err.takeError();

  uint64_t size = ctf_array.nelems * *element_size_or_err;

  CompilerType compiler_type = m_ast->CreateArrayType(
      element_type->GetFullCompilerType(), ctf_array.nelems,
      /*is_gnu_vector*/ false);

  Declaration decl;
  return MakeType(ctf_array.uid, ConstString(), size, nullptr, LLDB_INVALID_UID,
                  Type::eEncodingIsUID, decl, compiler_type,
                  lldb_private::Type::ResolveState::Full);
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateEnum(const CTFEnum &ctf_enum) {
  Declaration decl;
  CompilerType enum_type = m_ast->CreateEnumerationType(
      ctf_enum.name, m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(),
      decl, m_ast->GetBasicType(eBasicTypeInt),
      /*is_scoped=*/false);

  for (const CTFEnum::Value &value : ctf_enum.values) {
    Declaration value_decl;
    m_ast->AddEnumerationValueToEnumerationType(
        enum_type, value_decl, value.name.data(), value.value, ctf_enum.size);
  }
  TypeSystemClang::CompleteTagDeclarationDefinition(enum_type);

  return MakeType(ctf_enum.uid, ConstString(), 0, nullptr, LLDB_INVALID_UID,
                  Type::eEncodingIsUID, decl, enum_type,
                  lldb_private::Type::ResolveState::Full);
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateFunction(const CTFFunction &ctf_function) {
  std::vector<CompilerType> arg_types;
  for (uint32_t arg : ctf_function.args) {
    if (Type *arg_type = ResolveTypeUID(arg))
      arg_types.push_back(arg_type->GetFullCompilerType());
  }

  Type *ret_type = ResolveTypeUID(ctf_function.return_type);
  if (!ret_type)
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("Could not find function return type: {0}",
                      ctf_function.return_type),
        llvm::inconvertibleErrorCode());

  CompilerType func_type = m_ast->CreateFunctionType(
      ret_type->GetFullCompilerType(), arg_types, ctf_function.variadic, 0,
      clang::CallingConv::CC_C);

  Declaration decl;
  return MakeType(ctf_function.uid, ConstString(ctf_function.name), 0, nullptr,
                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,
                  lldb_private::Type::ResolveState::Full);
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateRecord(const CTFRecord &ctf_record) {
  const clang::TagTypeKind tag_kind = TranslateRecordKind(ctf_record.kind);
  CompilerType record_type = m_ast->CreateRecordType(
      nullptr, OptionalClangModuleID(), eAccessPublic, ctf_record.name.data(),
      llvm::to_underlying(tag_kind), eLanguageTypeC);
  m_compiler_types[record_type.GetOpaqueQualType()] = &ctf_record;
  Declaration decl;
  return MakeType(ctf_record.uid, ConstString(ctf_record.name), ctf_record.size,
                  nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
                  decl, record_type, lldb_private::Type::ResolveState::Forward);
}

bool SymbolFileCTF::CompleteType(CompilerType &compiler_type) {
  // Check if we have a CTF type for the given incomplete compiler type.
  auto it = m_compiler_types.find(compiler_type.GetOpaqueQualType());
  if (it == m_compiler_types.end())
    return false;

  const CTFType *ctf_type = it->second;
  assert(ctf_type && "m_compiler_types should only contain valid CTF types");

  // We only support resolving record types.
  assert(llvm::isa<CTFRecord>(ctf_type));

  // Cast to the appropriate CTF type.
  const CTFRecord *ctf_record = static_cast<const CTFRecord *>(ctf_type);

  // If any of the fields are incomplete, we cannot complete the type.
  for (const CTFRecord::Field &field : ctf_record->fields) {
    if (!ResolveTypeUID(field.type)) {
      LLDB_LOG(GetLog(LLDBLog::Symbols),
               "Cannot complete type {0} because field {1} is incomplete",
               ctf_type->uid, field.type);
      return false;
    }
  }

  // Complete the record type.
  m_ast->StartTagDeclarationDefinition(compiler_type);
  for (const CTFRecord::Field &field : ctf_record->fields) {
    Type *field_type = ResolveTypeUID(field.type);
    assert(field_type && "field must be complete");
    const uint32_t field_size =
        llvm::expectedToOptional(field_type->GetByteSize(nullptr)).value_or(0);
    TypeSystemClang::AddFieldToRecordType(compiler_type, field.name,
                                          field_type->GetFullCompilerType(),
                                          eAccessPublic, field_size);
  }
  m_ast->CompleteTagDeclarationDefinition(compiler_type);

  // Now that the compiler type is complete, we don't need to remember it
  // anymore and can remove the CTF record type.
  m_compiler_types.erase(compiler_type.GetOpaqueQualType());
  m_ctf_types.erase(ctf_type->uid);

  return true;
}

llvm::Expected<lldb::TypeSP>
SymbolFileCTF::CreateForward(const CTFForward &ctf_forward) {
  CompilerType forward_compiler_type = m_ast->CreateRecordType(
      nullptr, OptionalClangModuleID(), eAccessPublic, ctf_forward.name,
      llvm::to_underlying(clang::TagTypeKind::Struct), eLanguageTypeC);
  Declaration decl;
  return MakeType(ctf_forward.uid, ConstString(ctf_forward.name), 0, nullptr,
                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
                  forward_compiler_type, Type::ResolveState::Forward);
}

llvm::Expected<TypeSP> SymbolFileCTF::CreateType(CTFType *ctf_type) {
  if (!ctf_type)
    return llvm::make_error<llvm::StringError>(
        "cannot create type for unparsed type", llvm::inconvertibleErrorCode());

  switch (ctf_type->kind) {
  case CTFType::Kind::eInteger:
    return CreateInteger(*static_cast<CTFInteger *>(ctf_type));
  case CTFType::Kind::eConst:
  case CTFType::Kind::ePointer:
  case CTFType::Kind::eRestrict:
  case CTFType::Kind::eVolatile:
    return CreateModifier(*static_cast<CTFModifier *>(ctf_type));
  case CTFType::Kind::eTypedef:
    return CreateTypedef(*static_cast<CTFTypedef *>(ctf_type));
  case CTFType::Kind::eArray:
    return CreateArray(*static_cast<CTFArray *>(ctf_type));
  case CTFType::Kind::eEnum:
    return CreateEnum(*static_cast<CTFEnum *>(ctf_type));
  case CTFType::Kind::eFunction:
    return CreateFunction(*static_cast<CTFFunction *>(ctf_type));
  case CTFType::Kind::eStruct:
  case CTFType::Kind::eUnion:
    return CreateRecord(*static_cast<CTFRecord *>(ctf_type));
  case CTFType::Kind::eForward:
    return CreateForward(*static_cast<CTFForward *>(ctf_type));
  case CTFType::Kind::eUnknown:
  case CTFType::Kind::eFloat:
  case CTFType::Kind::eSlice:
    return llvm::make_error<llvm::StringError>(
        llvm::formatv("unsupported type (uid = {0}, name = {1}, kind = {2})",
                      ctf_type->uid, ctf_type->name, ctf_type->kind),
        llvm::inconvertibleErrorCode());
  }
  llvm_unreachable("Unexpected CTF type kind");
}

llvm::Expected<std::unique_ptr<CTFType>>
SymbolFileCTF::ParseType(lldb::offset_t &offset, lldb::user_id_t uid) {
  ctf_stype_t ctf_stype;
  ctf_stype.name = m_data.GetU32(&offset);
  ctf_stype.info = m_data.GetU32(&offset);
  ctf_stype.size = m_data.GetU32(&offset);

  llvm::StringRef name = ReadString(ctf_stype.name);
  const uint32_t kind = GetKind(ctf_stype.info);
  const uint32_t variable_length = GetVLen(ctf_stype.info);
  const uint32_t type = ctf_stype.GetType();
  const uint32_t size = ctf_stype.GetSize();

  switch (kind) {
  case TypeKind::eInteger: {
    const uint32_t vdata = m_data.GetU32(&offset);
    const uint32_t bits = GetBits(vdata);
    const uint32_t encoding = GetEncoding(vdata);
    return std::make_unique<CTFInteger>(uid, name, bits, encoding);
  }
  case TypeKind::eConst:
    return std::make_unique<CTFConst>(uid, type);
  case TypeKind::ePointer:
    return std::make_unique<CTFPointer>(uid, type);
  case TypeKind::eRestrict:
    return std::make_unique<CTFRestrict>(uid, type);
  case TypeKind::eVolatile:
    return std::make_unique<CTFVolatile>(uid, type);
  case TypeKind::eTypedef:
    return std::make_unique<CTFTypedef>(uid, name, type);
  case TypeKind::eArray: {
    const uint32_t type = m_data.GetU32(&offset);
    const uint32_t index = m_data.GetU32(&offset);
    const uint32_t nelems = m_data.GetU32(&offset);
    return std::make_unique<CTFArray>(uid, name, type, index, nelems);
  }
  case TypeKind::eEnum: {
    std::vector<CTFEnum::Value> values;
    for (uint32_t i = 0; i < variable_length; ++i) {
      const uint32_t value_name = m_data.GetU32(&offset);
      const uint32_t value = m_data.GetU32(&offset);
      values.emplace_back(ReadString(value_name), value);
    }
    return std::make_unique<CTFEnum>(uid, name, variable_length, size, values);
  }
  case TypeKind::eFunction: {
    std::vector<uint32_t> args;
    bool variadic = false;
    for (uint32_t i = 0; i < variable_length; ++i) {
      const uint32_t arg_uid = m_data.GetU32(&offset);
      // If the last argument is 0, this is a variadic function.
      if (arg_uid == 0) {
        variadic = true;
        break;
      }
      args.push_back(arg_uid);
    }
    // If the number of arguments is odd, a single uint32_t of padding is
    // inserted to maintain alignment.
    if (variable_length % 2 == 1)
      m_data.GetU32(&offset);
    return std::make_unique<CTFFunction>(uid, name, variable_length, type, args,
                                         variadic);
  }
  case TypeKind::eStruct:
  case TypeKind::eUnion: {
    std::vector<CTFRecord::Field> fields;
    for (uint32_t i = 0; i < variable_length; ++i) {
      const uint32_t field_name = m_data.GetU32(&offset);
      const uint32_t type = m_data.GetU32(&offset);
      uint64_t field_offset = 0;
      if (size < g_ctf_field_threshold) {
        field_offset = m_data.GetU16(&offset);
        m_data.GetU16(&offset); // Padding
      } else {
        const uint32_t offset_hi = m_data.GetU32(&offset);
        const uint32_t offset_lo = m_data.GetU32(&offset);
        field_offset = (((uint64_t)offset_hi) << 32) | ((uint64_t)offset_lo);
      }
      fields.emplace_back(ReadString(field_name), type, field_offset);
    }
    return std::make_unique<CTFRecord>(static_cast<CTFType::Kind>(kind), uid,
                                       name, variable_length, size, fields);
  }
  case TypeKind::eForward:
    return std::make_unique<CTFForward>(uid, name);
  case TypeKind::eUnknown:
    return std::make_unique<CTFType>(static_cast<CTFType::Kind>(kind), uid,
                                     name);
  case TypeKind::eFloat:
  case TypeKind::eSlice:
    offset += (variable_length * sizeof(uint32_t));
    break;
  }

  return llvm::make_error<llvm::StringError>(
      llvm::formatv("unsupported type (name = {0}, kind = {1}, vlength = {2})",
                    name, kind, variable_length),
      llvm::inconvertibleErrorCode());
}

size_t SymbolFileCTF::ParseTypes(CompileUnit &cu) {
  if (!ParseHeader())
    return 0;

  if (!m_types.empty())
    return 0;

  if (!m_ast)
    return 0;

  Log *log = GetLog(LLDBLog::Symbols);
  LLDB_LOG(log, "Parsing CTF types");

  lldb::offset_t type_offset = m_body_offset + m_header->typeoff;
  const lldb::offset_t type_offset_end = m_body_offset + m_header->stroff;

  lldb::user_id_t type_uid = 1;
  while (type_offset < type_offset_end) {
    llvm::Expected<std::unique_ptr<CTFType>> type_or_error =
        ParseType(type_offset, type_uid);
    if (type_or_error) {
      m_ctf_types[(*type_or_error)->uid] = std::move(*type_or_error);
    } else {
      LLDB_LOG_ERROR(log, type_or_error.takeError(),
                     "Failed to parse type {1} at offset {2}: {0}", type_uid,
                     type_offset);
    }
    type_uid++;
  }

  LLDB_LOG(log, "Parsed {0} CTF types", m_ctf_types.size());

  for (lldb::user_id_t uid = 1; uid < type_uid; ++uid) {
    ResolveTypeUID(uid);

    // Remove the CTF type because we don't need it anymore, except for record
    // types which we may need to complete later.
    auto ctf_type_it = m_ctf_types.find(uid);
    if (ctf_type_it != m_ctf_types.end()) {
      CTFType *ctf_type = ctf_type_it->second.get();
      if (!llvm::isa<CTFRecord>(ctf_type))
        m_ctf_types.erase(uid);
    }
  }

#ifndef NDEBUG
  // Verify that the only CTF types left at this point are record types.
  for (auto &t : m_ctf_types) {
    CTFType *ctf_type = t.second.get();
    assert(ctf_type && "invalid type in m_ctf_types");
    assert(llvm::isa<CTFRecord>(ctf_type) && "leaking non record type");
  }

#endif

  LLDB_LOG(log, "Created {0} CTF types", m_types.size());

  return m_types.size();
}

size_t SymbolFileCTF::ParseFunctions(CompileUnit &cu) {
  if (!ParseHeader())
    return 0;

  if (!m_functions.empty())
    return 0;

  if (!m_ast)
    return 0;

  Symtab *symtab = GetObjectFile()->GetModule()->GetSymtab();
  if (!symtab)
    return 0;

  Log *log = GetLog(LLDBLog::Symbols);
  LLDB_LOG(log, "Parsing CTF functions");

  lldb::offset_t function_offset = m_body_offset + m_header->funcoff;
  const lldb::offset_t function_offset_end = m_body_offset + m_header->typeoff;

  uint32_t symbol_idx = 0;
  Declaration decl;
  while (function_offset < function_offset_end) {
    const uint32_t info = m_data.GetU32(&function_offset);
    const uint16_t kind = GetKind(info);
    const uint16_t variable_length = GetVLen(info);

    Symbol *symbol = symtab->FindSymbolWithType(
        eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, symbol_idx);

    // Skip padding.
    if (kind == TypeKind::eUnknown && variable_length == 0)
      continue;

    // Skip unexpected kinds.
    if (kind != TypeKind::eFunction)
      continue;

    const uint32_t ret_uid = m_data.GetU32(&function_offset);
    const uint32_t num_args = variable_length;

    std::vector<CompilerType> arg_types;
    arg_types.reserve(num_args);

    bool is_variadic = false;
    for (uint32_t i = 0; i < variable_length; i++) {
      const uint32_t arg_uid = m_data.GetU32(&function_offset);

      // If the last argument is 0, this is a variadic function.
      if (arg_uid == 0) {
        is_variadic = true;
        break;
      }

      Type *arg_type = ResolveTypeUID(arg_uid);
      arg_types.push_back(arg_type ? arg_type->GetFullCompilerType()
                                   : CompilerType());
    }

    if (symbol) {
      Type *ret_type = ResolveTypeUID(ret_uid);
      AddressRange func_range =
          AddressRange(symbol->GetFileAddress(), symbol->GetByteSize(),
                       GetObjectFile()->GetModule()->GetSectionList());

      // Create function type.
      CompilerType func_type = m_ast->CreateFunctionType(
          ret_type ? ret_type->GetFullCompilerType() : CompilerType(),
          arg_types, is_variadic, 0, clang::CallingConv::CC_C);
      lldb::user_id_t function_type_uid = m_types.size() + 1;
      TypeSP type_sp =
          MakeType(function_type_uid, symbol->GetName(), 0, nullptr,
                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_type,
                   lldb_private::Type::ResolveState::Full);
      m_types[function_type_uid] = type_sp;

      // Create function.
      lldb::user_id_t func_uid = m_functions.size();
      FunctionSP function_sp = std::make_shared<Function>(
          &cu, func_uid, function_type_uid, symbol->GetMangled(), type_sp.get(),
          symbol->GetAddress(), AddressRanges{func_range});
      m_functions.emplace_back(function_sp);
      cu.AddFunction(function_sp);
    }
  }

  LLDB_LOG(log, "CTF parsed {0} functions", m_functions.size());

  return m_functions.size();
}

static DWARFExpression CreateDWARFExpression(ModuleSP module_sp,
                                             const Symbol &symbol) {
  if (!module_sp)
    return DWARFExpression();

  const ArchSpec &architecture = module_sp->GetArchitecture();
  ByteOrder byte_order = architecture.GetByteOrder();
  uint32_t address_size = architecture.GetAddressByteSize();
  uint32_t byte_size = architecture.GetDataByteSize();

  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
  stream.PutHex8(llvm::dwarf::DW_OP_addr);
  stream.PutMaxHex64(symbol.GetFileAddress(), address_size, byte_order);

  DataBufferSP buffer =
      std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
  lldb_private::DataExtractor extractor(buffer, byte_order, address_size,
                                        byte_size);
  DWARFExpression result(extractor);
  result.SetRegisterKind(eRegisterKindDWARF);

  return result;
}

size_t SymbolFileCTF::ParseObjects(CompileUnit &comp_unit) {
  if (!ParseHeader())
    return 0;

  if (!m_variables.empty())
    return 0;

  if (!m_ast)
    return 0;

  ModuleSP module_sp = GetObjectFile()->GetModule();
  Symtab *symtab = module_sp->GetSymtab();
  if (!symtab)
    return 0;

  Log *log = GetLog(LLDBLog::Symbols);
  LLDB_LOG(log, "Parsing CTF objects");

  lldb::offset_t object_offset = m_body_offset + m_header->objtoff;
  const lldb::offset_t object_offset_end = m_body_offset + m_header->funcoff;

  uint32_t symbol_idx = 0;
  Declaration decl;
  while (object_offset < object_offset_end) {
    const uint32_t type_uid = m_data.GetU32(&object_offset);

    if (Symbol *symbol =
            symtab->FindSymbolWithType(eSymbolTypeData, Symtab::eDebugYes,
                                       Symtab::eVisibilityAny, symbol_idx)) {
      Variable::RangeList ranges;
      ranges.Append(symbol->GetFileAddress(), symbol->GetByteSize());

      auto type_sp = std::make_shared<SymbolFileType>(*this, type_uid);

      DWARFExpressionList location(
          module_sp, CreateDWARFExpression(module_sp, *symbol), nullptr);

      lldb::user_id_t variable_type_uid = m_variables.size();
      m_variables.emplace_back(std::make_shared<Variable>(
          variable_type_uid, symbol->GetName().AsCString(),
          symbol->GetName().AsCString(), type_sp, eValueTypeVariableGlobal,
          m_comp_unit_sp.get(), ranges, &decl, location, symbol->IsExternal(),
          /*artificial=*/false,
          /*location_is_constant_data*/ false));
    }
  }

  LLDB_LOG(log, "Parsed {0} CTF objects", m_variables.size());

  return m_variables.size();
}

uint32_t SymbolFileCTF::CalculateAbilities() {
  if (!m_objfile_sp)
    return 0;

  if (!ParseHeader())
    return 0;

  return VariableTypes | Functions | GlobalVariables;
}

uint32_t SymbolFileCTF::ResolveSymbolContext(const Address &so_addr,
                                             SymbolContextItem resolve_scope,
                                             SymbolContext &sc) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  if (m_objfile_sp->GetSymtab() == nullptr)
    return 0;

  uint32_t resolved_flags = 0;

  // Resolve symbols.
  if (resolve_scope & eSymbolContextSymbol) {
    sc.symbol = m_objfile_sp->GetSymtab()->FindSymbolContainingFileAddress(
        so_addr.GetFileAddress());
    if (sc.symbol)
      resolved_flags |= eSymbolContextSymbol;
  }

  // Resolve functions.
  if (resolve_scope & eSymbolContextFunction) {
    for (FunctionSP function_sp : m_functions) {
      if (llvm::any_of(
              function_sp->GetAddressRanges(), [&](const AddressRange range) {
                return range.ContainsFileAddress(so_addr.GetFileAddress());
              })) {
        sc.function = function_sp.get();
        resolved_flags |= eSymbolContextFunction;
        break;
      }
    }
  }

  // Resolve variables.
  if (resolve_scope & eSymbolContextVariable) {
    for (VariableSP variable_sp : m_variables) {
      if (variable_sp->LocationIsValidForAddress(so_addr.GetFileAddress())) {
        sc.variable = variable_sp.get();
        break;
      }
    }
  }

  return resolved_flags;
}

CompUnitSP SymbolFileCTF::ParseCompileUnitAtIndex(uint32_t idx) {
  if (idx == 0)
    return m_comp_unit_sp;
  return {};
}

size_t
SymbolFileCTF::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
  return ParseObjects(*m_comp_unit_sp);
}

void SymbolFileCTF::AddSymbols(Symtab &symtab) {
  // CTF does not encode symbols.
  // We rely on the existing symbol table to map symbols to type.
}

lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
  auto type_it = m_types.find(type_uid);
  if (type_it != m_types.end())
    return type_it->second.get();

  auto ctf_type_it = m_ctf_types.find(type_uid);
  if (ctf_type_it == m_ctf_types.end())
    return nullptr;

  CTFType *ctf_type = ctf_type_it->second.get();
  assert(ctf_type && "m_ctf_types should only contain valid CTF types");
  assert(ctf_type->uid == type_uid &&
         "CTF type UID doesn't match UID in m_ctf_types");

  Log *log = GetLog(LLDBLog::Symbols);

  llvm::Expected<TypeSP> type_or_error = CreateType(ctf_type);
  if (!type_or_error) {
    LLDB_LOG_ERROR(log, type_or_error.takeError(),
                   "Failed to create type for {1}: {0}", ctf_type->uid);
    return {};
  }

  TypeSP type_sp = *type_or_error;

  if (log) {
    StreamString ss;
    type_sp->Dump(&ss, true);
    LLDB_LOGV(log, "Adding type {0}: {1}", type_sp->GetID(),
              llvm::StringRef(ss.GetString()).rtrim());
  }

  m_types[type_uid] = type_sp;

  return type_sp.get();
}

void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match,
                              lldb_private::TypeResults &results) {
  // Make sure we haven't already searched this SymbolFile before.
  if (results.AlreadySearched(this))
    return;

  ConstString name = match.GetTypeBasename();
  for (TypeSP type_sp : GetTypeList().Types()) {
    if (type_sp && type_sp->GetName() == name) {
      results.InsertUnique(type_sp);
      if (results.Done(match))
        return;
    }
  }
}

void SymbolFileCTF::FindTypesByRegex(
    const lldb_private::RegularExpression &regex, uint32_t max_matches,
    lldb_private::TypeMap &types) {
  ParseTypes(*m_comp_unit_sp);

  size_t matches = 0;
  for (TypeSP type_sp : GetTypeList().Types()) {
    if (matches == max_matches)
      break;
    if (type_sp && regex.Execute(type_sp->GetName()))
      types.Insert(type_sp);
    matches++;
  }
}

void SymbolFileCTF::FindFunctions(
    const lldb_private::Module::LookupInfo &lookup_info,
    const lldb_private::CompilerDeclContext &parent_decl_ctx,
    bool include_inlines, lldb_private::SymbolContextList &sc_list) {
  ParseFunctions(*m_comp_unit_sp);

  ConstString name = lookup_info.GetLookupName();
  for (FunctionSP function_sp : m_functions) {
    if (function_sp && function_sp->GetName() == name) {
      lldb_private::SymbolContext sc;
      sc.comp_unit = m_comp_unit_sp.get();
      sc.function = function_sp.get();
      sc_list.Append(sc);
    }
  }
}

void SymbolFileCTF::FindFunctions(const lldb_private::RegularExpression &regex,
                                  bool include_inlines,
                                  lldb_private::SymbolContextList &sc_list) {
  for (FunctionSP function_sp : m_functions) {
    if (function_sp && regex.Execute(function_sp->GetName())) {
      lldb_private::SymbolContext sc;
      sc.comp_unit = m_comp_unit_sp.get();
      sc.function = function_sp.get();
      sc_list.Append(sc);
    }
  }
}

void SymbolFileCTF::FindGlobalVariables(
    lldb_private::ConstString name,
    const lldb_private::CompilerDeclContext &parent_decl_ctx,
    uint32_t max_matches, lldb_private::VariableList &variables) {
  ParseObjects(*m_comp_unit_sp);

  size_t matches = 0;
  for (VariableSP variable_sp : m_variables) {
    if (matches == max_matches)
      break;
    if (variable_sp && variable_sp->GetName() == name) {
      variables.AddVariable(variable_sp);
      matches++;
    }
  }
}

void SymbolFileCTF::FindGlobalVariables(
    const lldb_private::RegularExpression &regex, uint32_t max_matches,
    lldb_private::VariableList &variables) {
  ParseObjects(*m_comp_unit_sp);

  size_t matches = 0;
  for (VariableSP variable_sp : m_variables) {
    if (matches == max_matches)
      break;
    if (variable_sp && regex.Execute(variable_sp->GetName())) {
      variables.AddVariable(variable_sp);
      matches++;
    }
  }
}
