//===-- 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().GetStringRef());
  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");
      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");
        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");
      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())) {

    ConstString const_sect_name(section.Name);

    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(new Section(
        module_sp, this, ++idx, const_sect_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)) {}
