//===-- ObjectFileXCOFF.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 "ObjectFileXCOFF.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/FileSpecList.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/Support/MemoryBuffer.h"
#include <algorithm>
#include <cassert>
#include <cstring>
#include <unordered_map>

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

LLDB_PLUGIN_DEFINE(ObjectFileXCOFF)
// FIXME: target 64bit at this moment.

// Static methods.
void ObjectFileXCOFF::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                CreateMemoryInstance, GetModuleSpecifications);
}

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

ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp,
                                            DataExtractorSP extractor_sp,
                                            lldb::offset_t data_offset,
                                            const lldb_private::FileSpec *file,
                                            lldb::offset_t file_offset,
                                            lldb::offset_t length) {
  if (!extractor_sp || !extractor_sp->HasData()) {
    DataBufferSP data_sp = MapFileData(*file, length, file_offset);
    if (!data_sp)
      return nullptr;
    data_offset = 0;
    extractor_sp = std::make_shared<lldb_private::DataExtractor>(data_sp);
  }
  if (!ObjectFileXCOFF::GetMagicBytes(extractor_sp, data_offset, length))
    return nullptr;
  // Update the data to contain the entire file if it doesn't already
  if (extractor_sp->GetByteSize() < length) {
    DataBufferSP data_sp = MapFileData(*file, length, file_offset);
    if (!data_sp)
      return nullptr;
    data_offset = 0;
    extractor_sp = std::make_shared<lldb_private::DataExtractor>(data_sp);
  }
  auto objfile_up = std::make_unique<ObjectFileXCOFF>(
      module_sp, extractor_sp, data_offset, file, file_offset, length);
  if (!objfile_up)
    return nullptr;

  // Cache xcoff binary.
  if (!objfile_up->CreateBinary())
    return nullptr;

  if (!objfile_up->ParseHeader())
    return nullptr;

  return objfile_up.release();
}

bool ObjectFileXCOFF::CreateBinary() {
  if (m_binary)
    return true;

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

  auto memory_ref = llvm::MemoryBufferRef(toStringRef(m_data_nsp->GetData()),
                                          m_file.GetFilename());
  llvm::file_magic magic = llvm::identify_magic(memory_ref.getBuffer());

  auto binary = llvm::object::ObjectFile::createObjectFile(memory_ref, magic);
  if (!binary) {
    LLDB_LOG_ERROR(log, binary.takeError(),
                   "Failed to create binary for file ({1}): {0}", m_file);
    return false;
  }
  // Make sure we only handle XCOFF format.
  m_binary =
      llvm::unique_dyn_cast<llvm::object::XCOFFObjectFile>(std::move(*binary));
  if (!m_binary)
    return false;

  LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
           this, GetModule().get(), GetModule()->GetSpecificationDescription(),
           m_file.GetPath(), m_binary.get());

  return true;
}

ObjectFile *ObjectFileXCOFF::CreateMemoryInstance(
    const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
    const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
  return nullptr;
}

ModuleSpecList ObjectFileXCOFF::GetModuleSpecifications(
    const lldb_private::FileSpec &file, lldb::DataExtractorSP &extractor_sp,
    lldb::offset_t file_offset, lldb::offset_t length) {
  if (!extractor_sp || !extractor_sp->HasData())
    return {};

  ModuleSpecList specs;
  if (auto magic = ObjectFileXCOFF::GetMagicBytes(
          extractor_sp, 0, extractor_sp->GetByteSize())) {
    const uint32_t cpu_type =
        (*magic == XCOFF::XCOFF64) ? XCOFF::TCPU_PPC64 : XCOFF::TCPU_PPC;
    ArchSpec arch_spec =
        ArchSpec(eArchTypeXCOFF, cpu_type, LLDB_INVALID_CPUTYPE);
    ModuleSpec spec(file, arch_spec);
    spec.GetArchitecture().SetArchitecture(
        eArchTypeXCOFF, cpu_type, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);
    specs.Append(spec);
  }
  return specs;
}

std::optional<XCOFF::MagicNumber>
ObjectFileXCOFF::GetMagicBytes(DataExtractorSP &extractor_sp,
                               lldb::addr_t data_offset,
                               lldb::addr_t data_length) {
  DataExtractorSP magic_extractor_sp =
      extractor_sp->GetSubsetExtractorSP(data_offset);
  // Need to set this as XCOFF is only compatible with Big Endian
  magic_extractor_sp->SetByteOrder(eByteOrderBig);
  lldb::offset_t offset = 0;
  uint16_t magic = magic_extractor_sp->GetU16(&offset);
  // Validating magic
  if (magic == XCOFF::XCOFF64 || magic == XCOFF::XCOFF32)
    return static_cast<llvm::XCOFF::MagicNumber>(magic);

  return std::nullopt;
}

bool ObjectFileXCOFF::ParseHeader() {
  if (m_binary->is64Bit())
    return m_binary->fileHeader64()->Magic == XCOFF::XCOFF64;
  return m_binary->fileHeader32()->Magic == XCOFF::XCOFF32;
}

ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; }

bool ObjectFileXCOFF::IsExecutable() const { return true; }

uint32_t ObjectFileXCOFF::GetAddressByteSize() const {
  if (m_binary->is64Bit())
    return 8;
  return 4;
}

AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) {
  return AddressClass::eUnknown;
}

static lldb::SymbolType MapSymbolType(llvm::object::SymbolRef::Type sym_type) {
  switch (sym_type) {
  case llvm::object::SymbolRef::ST_Function:
    return lldb::eSymbolTypeCode;
  case llvm::object::SymbolRef::ST_Data:
    return lldb::eSymbolTypeData;
  case llvm::object::SymbolRef::ST_File:
    return lldb::eSymbolTypeSourceFile;
  default:
    return lldb::eSymbolTypeInvalid;
  }
}

void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) {
  Log *log = GetLog(LLDBLog::Object);
  SectionList *sectionList = GetSectionList();

  for (const auto &symbol_ref : m_binary->symbols()) {
    llvm::object::XCOFFSymbolRef xcoff_sym_ref(symbol_ref);

    llvm::Expected<llvm::StringRef> name_or_err = xcoff_sym_ref.getName();
    if (!name_or_err) {
      LLDB_LOG_ERROR(
          log, name_or_err.takeError(),
          "Unable to extract name from the xcoff symbol ref object: {0}");
      continue;
    }

    llvm::StringRef symbolName = name_or_err.get();
    // Remove the . prefix added during compilation. This prefix is usually
    // added to differentiate between reference to the code and function
    // descriptor. For instance, Adding .func will only allow user to put bp on
    // .func, which is not known to the user, instead of func.
    llvm::StringRef name_no_dot =
        symbolName.starts_with(".") ? symbolName.drop_front() : symbolName;
    auto storageClass = xcoff_sym_ref.getStorageClass();
    // C_HIDEXT symbols are not needed to be exposed, with the exception of TOC
    // which is responsible for storing references to global data
    if (storageClass == XCOFF::C_HIDEXT && symbolName != "TOC") {

      // Zero or muliple aux entries may suggest ambiguous data
      if (xcoff_sym_ref.getNumberOfAuxEntries() != 1)
        continue;

      auto aux_csect_or_err = xcoff_sym_ref.getXCOFFCsectAuxRef();
      if (!aux_csect_or_err) {
        LLDB_LOG_ERROR(log, aux_csect_or_err.takeError(),
                       "Unable to access xcoff csect aux ref object: {0}");
        continue;
      }

      const llvm::object::XCOFFCsectAuxRef csect_aux = aux_csect_or_err.get();

      // Only add hidden ext entries which come under Program Code, skip others
      // as they are not useful as debugging data.
      if (csect_aux.getStorageMappingClass() != XCOFF::XMC_PR)
        continue;

      // This does not apply to 32-bit,
      // Only add csect symbols identified by the aux entry, as they are
      // needed to reference section information. Skip others
      if (m_binary->is64Bit())
        if (csect_aux.getAuxType64() != XCOFF::AUX_CSECT)
          continue;
    }

    Symbol symbol;
    symbol.GetMangled().SetValue(ConstString(name_no_dot));

    int16_t sectionNumber = xcoff_sym_ref.getSectionNumber();
    // Note that XCOFF section headers are numbered from 1 and not 0.
    size_t sectionIndex = static_cast<size_t>(sectionNumber - 1);
    if (sectionNumber > 0) {
      if (sectionIndex < sectionList->GetSize()) {

        lldb::SectionSP section_sp =
            sectionList->GetSectionAtIndex(sectionIndex);
        if (!section_sp || section_sp->GetFileAddress() == LLDB_INVALID_ADDRESS)
          continue;

        lldb::addr_t file_addr = section_sp->GetFileAddress();
        lldb::addr_t symbolValue = xcoff_sym_ref.getValue();
        if (symbolValue < file_addr)
          continue;

        symbol.GetAddressRef() = Address(section_sp, symbolValue - file_addr);
      }
    }

    Expected<llvm::object::SymbolRef::Type> sym_type_or_err =
        symbol_ref.getType();
    if (!sym_type_or_err) {
      LLDB_LOG_ERROR(log, sym_type_or_err.takeError(),
                     "Unable to access xcoff symbol type: {0}");
      continue;
    }

    symbol.SetType(MapSymbolType(sym_type_or_err.get()));

    lldb_symtab.AddSymbol(symbol);
  }
}

bool ObjectFileXCOFF::IsStripped() { return false; }

void ObjectFileXCOFF::CreateSections(SectionList &unified_section_list) {

  if (m_sections_up)
    return;

  m_sections_up = std::make_unique<SectionList>();
  if (m_binary->is64Bit())
    CreateSectionsWithBitness<XCOFF64>(unified_section_list);
  else
    CreateSectionsWithBitness<XCOFF32>(unified_section_list);
}

template <typename T>
static auto GetSections(llvm::object::XCOFFObjectFile *binary) {
  if constexpr (T::Is64Bit)
    return binary->sections64();
  else
    return binary->sections32();
}

template <typename T>
void ObjectFileXCOFF::CreateSectionsWithBitness(
    SectionList &unified_section_list) {
  ModuleSP module_sp(GetModule());
  if (!module_sp)
    return;

  std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

  int idx = 0;
  for (const typename T::SectionHeader &section :
       GetSections<T>(m_binary.get())) {

    SectionType section_type = lldb::eSectionTypeOther;
    if (section.Flags & XCOFF::STYP_TEXT)
      section_type = eSectionTypeCode;
    else if (section.Flags & XCOFF::STYP_DATA)
      section_type = eSectionTypeData;
    else if (section.Flags & XCOFF::STYP_BSS)
      section_type = eSectionTypeZeroFill;
    else if (section.Flags & XCOFF::STYP_DWARF) {
      section_type = llvm::StringSwitch<SectionType>(section.Name)
                         .Case(".dwinfo", eSectionTypeDWARFDebugInfo)
                         .Case(".dwline", eSectionTypeDWARFDebugLine)
                         .Case(".dwabrev", eSectionTypeDWARFDebugAbbrev)
                         .Case(".dwrnges", eSectionTypeDWARFDebugRanges)
                         .Default(eSectionTypeInvalid);
    }

    SectionSP section_sp = std::make_shared<Section>(
        module_sp, this, ++idx, section.Name, section_type,
        section.VirtualAddress, section.SectionSize,
        section.FileOffsetToRawData, section.SectionSize, 0, section.Flags);

    uint32_t permissions = ePermissionsReadable;
    if (section.Flags & (XCOFF::STYP_DATA | XCOFF::STYP_BSS))
      permissions |= ePermissionsWritable;
    if (section.Flags & XCOFF::STYP_TEXT)
      permissions |= ePermissionsExecutable;

    section_sp->SetPermissions(permissions);
    m_sections_up->AddSection(section_sp);
    unified_section_list.AddSection(section_sp);
  }
}

void ObjectFileXCOFF::Dump(Stream *s) {}

ArchSpec ObjectFileXCOFF::GetArchitecture() {
  const uint32_t cpu_type =
      m_binary->is64Bit() ? XCOFF::TCPU_PPC64 : XCOFF::TCPU_PPC;
  return (ArchSpec(eArchTypeXCOFF, cpu_type, LLDB_INVALID_CPUTYPE));
}

UUID ObjectFileXCOFF::GetUUID() { return UUID(); }

uint32_t ObjectFileXCOFF::GetDependentModules(FileSpecList &files) { return 0; }

ObjectFile::Type ObjectFileXCOFF::CalculateType() {

  const auto flags = m_binary->is64Bit() ? m_binary->fileHeader64()->Flags
                                         : m_binary->fileHeader32()->Flags;

  if (flags & XCOFF::F_EXEC)
    return eTypeExecutable;
  else if (flags & XCOFF::F_SHROBJ)
    return eTypeSharedLibrary;
  return eTypeUnknown;
}

ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { return eStrataUnknown; }

lldb::WritableDataBufferSP
ObjectFileXCOFF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
                                     uint64_t Offset) {
  return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
                                                         Offset);
}

ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
                                 DataExtractorSP extractor_sp,
                                 lldb::offset_t data_offset,
                                 const FileSpec *file,
                                 lldb::offset_t file_offset,
                                 lldb::offset_t length)
    : ObjectFile(module_sp, file, file_offset, length, extractor_sp,
                 data_offset) {
  if (file)
    m_file = *file;
}

ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
                                 DataBufferSP header_data_sp,
                                 const lldb::ProcessSP &process_sp,
                                 addr_t header_addr)
    : ObjectFile(
          module_sp, process_sp, header_addr,
          std::make_shared<lldb_private::DataExtractor>(header_data_sp)) {}
