//===------ xcoff2yaml.cpp - XCOFF YAMLIO implementation --------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "obj2yaml.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/ObjectYAML/XCOFFYAML.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/YAMLTraits.h"

using namespace llvm;
using namespace llvm::object;
namespace {

class XCOFFDumper {
  const object::XCOFFObjectFile &Obj;
  XCOFFYAML::Object YAMLObj;
  void dumpHeader();
  Error dumpSections();
  Error dumpSymbols();
  template <typename Shdr, typename Reloc>
  Error dumpSections(ArrayRef<Shdr> Sections);

public:
  XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {}
  Error dump();
  XCOFFYAML::Object &getYAMLObj() { return YAMLObj; }
};
} // namespace

Error XCOFFDumper::dump() {
  dumpHeader();
  if (Error E = dumpSections())
    return E;
  return dumpSymbols();
}

void XCOFFDumper::dumpHeader() {
  YAMLObj.Header.Magic = Obj.getMagic();
  YAMLObj.Header.NumberOfSections = Obj.getNumberOfSections();
  YAMLObj.Header.TimeStamp = Obj.getTimeStamp();
  YAMLObj.Header.SymbolTableOffset = Obj.is64Bit()
                                         ? Obj.getSymbolTableOffset64()
                                         : Obj.getSymbolTableOffset32();
  YAMLObj.Header.NumberOfSymTableEntries =
      Obj.is64Bit() ? Obj.getNumberOfSymbolTableEntries64()
                    : Obj.getRawNumberOfSymbolTableEntries32();
  YAMLObj.Header.AuxHeaderSize = Obj.getOptionalHeaderSize();
  YAMLObj.Header.Flags = Obj.getFlags();
}

Error XCOFFDumper::dumpSections() {
  if (Obj.is64Bit())
    return dumpSections<XCOFFSectionHeader64, XCOFFRelocation64>(
        Obj.sections64());
  return dumpSections<XCOFFSectionHeader32, XCOFFRelocation32>(
      Obj.sections32());
}

template <typename Shdr, typename Reloc>
Error XCOFFDumper::dumpSections(ArrayRef<Shdr> Sections) {
  std::vector<XCOFFYAML::Section> &YamlSections = YAMLObj.Sections;
  for (const Shdr &S : Sections) {
    XCOFFYAML::Section YamlSec;
    YamlSec.SectionName = S.getName();
    YamlSec.Address = S.PhysicalAddress;
    YamlSec.Size = S.SectionSize;
    YamlSec.NumberOfRelocations = S.NumberOfRelocations;
    YamlSec.NumberOfLineNumbers = S.NumberOfLineNumbers;
    YamlSec.FileOffsetToData = S.FileOffsetToRawData;
    YamlSec.FileOffsetToRelocations = S.FileOffsetToRelocationInfo;
    YamlSec.FileOffsetToLineNumbers = S.FileOffsetToLineNumberInfo;
    YamlSec.Flags = S.Flags;

    // Dump section data.
    if (S.FileOffsetToRawData) {
      DataRefImpl SectionDRI;
      SectionDRI.p = reinterpret_cast<uintptr_t>(&S);
      Expected<ArrayRef<uint8_t>> SecDataRefOrErr =
          Obj.getSectionContents(SectionDRI);
      if (!SecDataRefOrErr)
        return SecDataRefOrErr.takeError();
      YamlSec.SectionData = SecDataRefOrErr.get();
    }

    // Dump relocations.
    if (S.NumberOfRelocations) {
      auto RelRefOrErr = Obj.relocations<Shdr, Reloc>(S);
      if (!RelRefOrErr)
        return RelRefOrErr.takeError();
      for (const Reloc &R : RelRefOrErr.get()) {
        XCOFFYAML::Relocation YamlRel;
        YamlRel.Type = R.Type;
        YamlRel.Info = R.Info;
        YamlRel.SymbolIndex = R.SymbolIndex;
        YamlRel.VirtualAddress = R.VirtualAddress;
        YamlSec.Relocations.push_back(YamlRel);
      }
    }
    YamlSections.push_back(YamlSec);
  }
  return Error::success();
}

Error XCOFFDumper::dumpSymbols() {
  std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols;

  for (const SymbolRef &S : Obj.symbols()) {
    DataRefImpl SymbolDRI = S.getRawDataRefImpl();
    const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
    XCOFFYAML::Symbol Sym;

    Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);
    if (!SymNameRefOrErr) {
      return SymNameRefOrErr.takeError();
    }
    Sym.SymbolName = SymNameRefOrErr.get();

    Sym.Value = SymbolEntRef.getValue();

    Expected<StringRef> SectionNameRefOrErr =
        Obj.getSymbolSectionName(SymbolEntRef);
    if (!SectionNameRefOrErr)
      return SectionNameRefOrErr.takeError();

    Sym.SectionName = SectionNameRefOrErr.get();

    Sym.Type = SymbolEntRef.getSymbolType();
    Sym.StorageClass = SymbolEntRef.getStorageClass();
    Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
    Symbols.push_back(Sym);
  }

  return Error::success();
}

Error xcoff2yaml(raw_ostream &Out, const object::XCOFFObjectFile &Obj) {
  XCOFFDumper Dumper(Obj);

  if (Error E = Dumper.dump())
    return E;

  yaml::Output Yout(Out);
  Yout << Dumper.getYAMLObj();

  return Error::success();
}
