//===-- 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/ErrorExtras.h"
#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 ({}) doesn't match "
               "expected size ({})",
               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::createStringErrorV(
        "unsupported integer type: no corresponding basic clang "
        "type for '{0}'",
        ctf_integer.name);

  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::createStringErrorV(
          "Found compiler type for '{0}' but it's not an integer type: {1}",
          ctf_integer.name, compiler_type.GetDisplayTypeName().GetStringRef());

    // 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::createStringErrorV(
          "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");
  }

  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::createStringErrorV("could not find modified type: {0}",
                                    ctf_modifier.type);

  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::createStringErrorV(
        "ParseModifier called with unsupported kind: {0}", ctf_modifier.kind);
  }

  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::createStringErrorV(
        "could not find typedef underlying type: {0}", ctf_typedef.type);

  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::createStringErrorV("could not find array element type: {0}",
                                    ctf_array.type);

  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::createStringErrorV("could not find function return type: {0}",
                                    ctf_function.return_type);

  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(), 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(),
                                          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(), 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::createStringError("cannot create type for unparsed type");

  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::createStringErrorV(
        "unsupported type (uid = {0}, name = {1}, kind = {2})", ctf_type->uid,
        ctf_type->name, ctf_type->kind);
  }
  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::createStringErrorV(
      "unsupported type (name = {0}, kind = {1}, vlength = {2})", name, kind,
      variable_length);
}

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);

    const 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();

  StreamBuffer<32> stream(Stream::eBinary, 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);
  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 (const 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(nullptr),
          symbol->GetName().AsCString(nullptr), 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(
              Address(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_LOG_VERBOSE(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++;
    }
  }
}
