//===------ utils/obj2yaml.cpp - obj2yaml conversion tool -------*- 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/ADT/StringMap.h"
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/Object/COFF.h"
#include "llvm/ObjectYAML/COFFYAML.h"
#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/YAMLTraits.h"

using namespace llvm;

namespace {

class COFFDumper {
  const object::COFFObjectFile &Obj;
  COFFYAML::Object YAMLObj;
  template <typename T>
  void dumpOptionalHeader(T OptionalHeader);
  void dumpHeader();
  void dumpSections(unsigned numSections);
  void dumpSymbols(unsigned numSymbols);

public:
  COFFDumper(const object::COFFObjectFile &Obj);
  COFFYAML::Object &getYAMLObj();
};

}

COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) {
  if (const object::pe32_header *PE32Header = Obj.getPE32Header())
    dumpOptionalHeader(PE32Header);
  else if (const object::pe32plus_header *PE32PlusHeader =
               Obj.getPE32PlusHeader())
    dumpOptionalHeader(PE32PlusHeader);

  dumpHeader();
  dumpSections(Obj.getNumberOfSections());
  dumpSymbols(Obj.getNumberOfSymbols());
}

template <typename T> void COFFDumper::dumpOptionalHeader(T OptionalHeader) {
  YAMLObj.OptionalHeader = COFFYAML::PEHeader();
  YAMLObj.OptionalHeader->Header.AddressOfEntryPoint =
      OptionalHeader->AddressOfEntryPoint;
  YAMLObj.OptionalHeader->Header.ImageBase = OptionalHeader->ImageBase;
  YAMLObj.OptionalHeader->Header.SectionAlignment =
      OptionalHeader->SectionAlignment;
  YAMLObj.OptionalHeader->Header.FileAlignment = OptionalHeader->FileAlignment;
  YAMLObj.OptionalHeader->Header.MajorOperatingSystemVersion =
      OptionalHeader->MajorOperatingSystemVersion;
  YAMLObj.OptionalHeader->Header.MinorOperatingSystemVersion =
      OptionalHeader->MinorOperatingSystemVersion;
  YAMLObj.OptionalHeader->Header.MajorImageVersion =
      OptionalHeader->MajorImageVersion;
  YAMLObj.OptionalHeader->Header.MinorImageVersion =
      OptionalHeader->MinorImageVersion;
  YAMLObj.OptionalHeader->Header.MajorSubsystemVersion =
      OptionalHeader->MajorSubsystemVersion;
  YAMLObj.OptionalHeader->Header.MinorSubsystemVersion =
      OptionalHeader->MinorSubsystemVersion;
  YAMLObj.OptionalHeader->Header.Subsystem = OptionalHeader->Subsystem;
  YAMLObj.OptionalHeader->Header.DLLCharacteristics =
      OptionalHeader->DLLCharacteristics;
  YAMLObj.OptionalHeader->Header.SizeOfStackReserve =
      OptionalHeader->SizeOfStackReserve;
  YAMLObj.OptionalHeader->Header.SizeOfStackCommit =
      OptionalHeader->SizeOfStackCommit;
  YAMLObj.OptionalHeader->Header.SizeOfHeapReserve =
      OptionalHeader->SizeOfHeapReserve;
  YAMLObj.OptionalHeader->Header.SizeOfHeapCommit =
      OptionalHeader->SizeOfHeapCommit;
  unsigned I = 0;
  for (auto &DestDD : YAMLObj.OptionalHeader->DataDirectories) {
    const object::data_directory *DD = Obj.getDataDirectory(I++);
    if (!DD)
      continue;
    DestDD = COFF::DataDirectory();
    DestDD->RelativeVirtualAddress = DD->RelativeVirtualAddress;
    DestDD->Size = DD->Size;
  }
}

void COFFDumper::dumpHeader() {
  YAMLObj.Header.Machine = Obj.getMachine();
  YAMLObj.Header.Characteristics = Obj.getCharacteristics();
}

static void
initializeFileAndStringTable(const llvm::object::COFFObjectFile &Obj,
                             codeview::StringsAndChecksumsRef &SC) {

  ExitOnError Err("invalid .debug$S section");
  // Iterate all .debug$S sections looking for the checksums and string table.
  // Exit as soon as both sections are found.
  for (const auto &S : Obj.sections()) {
    if (SC.hasStrings() && SC.hasChecksums())
      break;

    Expected<StringRef> SectionNameOrErr = S.getName();
    if (!SectionNameOrErr) {
      consumeError(SectionNameOrErr.takeError());
      continue;
    }

    ArrayRef<uint8_t> sectionData;
    if ((*SectionNameOrErr) != ".debug$S")
      continue;

    const object::coff_section *COFFSection = Obj.getCOFFSection(S);

    cantFail(Obj.getSectionContents(COFFSection, sectionData));

    BinaryStreamReader Reader(sectionData, support::little);
    uint32_t Magic;

    Err(Reader.readInteger(Magic));
    assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");

    codeview::DebugSubsectionArray Subsections;
    Err(Reader.readArray(Subsections, Reader.bytesRemaining()));

    SC.initialize(Subsections);
  }
}

void COFFDumper::dumpSections(unsigned NumSections) {
  std::vector<COFFYAML::Section> &YAMLSections = YAMLObj.Sections;
  codeview::StringsAndChecksumsRef SC;
  initializeFileAndStringTable(Obj, SC);

  ExitOnError Err("invalid section table");
  StringMap<bool> SymbolUnique;
  for (const auto &S : Obj.symbols()) {
    StringRef Name = Err(Obj.getSymbolName(Obj.getCOFFSymbol(S)));
    StringMap<bool>::iterator It;
    bool Inserted;
    std::tie(It, Inserted) = SymbolUnique.insert(std::make_pair(Name, true));
    if (!Inserted)
      It->second = false;
  }

  for (const auto &ObjSection : Obj.sections()) {
    const object::coff_section *COFFSection = Obj.getCOFFSection(ObjSection);
    COFFYAML::Section NewYAMLSection;

    if (Expected<StringRef> NameOrErr = ObjSection.getName())
      NewYAMLSection.Name = *NameOrErr;
    else
      consumeError(NameOrErr.takeError());

    NewYAMLSection.Header.Characteristics = COFFSection->Characteristics;
    NewYAMLSection.Header.VirtualAddress = COFFSection->VirtualAddress;
    NewYAMLSection.Header.VirtualSize = COFFSection->VirtualSize;
    NewYAMLSection.Header.NumberOfLineNumbers =
        COFFSection->NumberOfLinenumbers;
    NewYAMLSection.Header.NumberOfRelocations =
        COFFSection->NumberOfRelocations;
    NewYAMLSection.Header.PointerToLineNumbers =
        COFFSection->PointerToLinenumbers;
    NewYAMLSection.Header.PointerToRawData = COFFSection->PointerToRawData;
    NewYAMLSection.Header.PointerToRelocations =
        COFFSection->PointerToRelocations;
    NewYAMLSection.Header.SizeOfRawData = COFFSection->SizeOfRawData;
    uint32_t Shift = (COFFSection->Characteristics >> 20) & 0xF;
    NewYAMLSection.Alignment = (1U << Shift) >> 1;
    assert(NewYAMLSection.Alignment <= 8192);

    ArrayRef<uint8_t> sectionData;
    if (!ObjSection.isBSS())
      cantFail(Obj.getSectionContents(COFFSection, sectionData));
    NewYAMLSection.SectionData = yaml::BinaryRef(sectionData);

    if (NewYAMLSection.Name == ".debug$S")
      NewYAMLSection.DebugS = CodeViewYAML::fromDebugS(sectionData, SC);
    else if (NewYAMLSection.Name == ".debug$T")
      NewYAMLSection.DebugT = CodeViewYAML::fromDebugT(sectionData,
                                                       NewYAMLSection.Name);
    else if (NewYAMLSection.Name == ".debug$P")
      NewYAMLSection.DebugP = CodeViewYAML::fromDebugT(sectionData,
                                                       NewYAMLSection.Name);
    else if (NewYAMLSection.Name == ".debug$H")
      NewYAMLSection.DebugH = CodeViewYAML::fromDebugH(sectionData);

    std::vector<COFFYAML::Relocation> Relocations;
    for (const auto &Reloc : ObjSection.relocations()) {
      const object::coff_relocation *reloc = Obj.getCOFFRelocation(Reloc);
      COFFYAML::Relocation Rel;
      object::symbol_iterator Sym = Reloc.getSymbol();
      Expected<StringRef> SymbolNameOrErr = Sym->getName();
      if (!SymbolNameOrErr) {
       std::string Buf;
       raw_string_ostream OS(Buf);
       logAllUnhandledErrors(SymbolNameOrErr.takeError(), OS);
       OS.flush();
       report_fatal_error(Buf);
      }
      if (SymbolUnique.lookup(*SymbolNameOrErr))
        Rel.SymbolName = *SymbolNameOrErr;
      else
        Rel.SymbolTableIndex = reloc->SymbolTableIndex;
      Rel.VirtualAddress = reloc->VirtualAddress;
      Rel.Type = reloc->Type;
      Relocations.push_back(Rel);
    }
    NewYAMLSection.Relocations = Relocations;
    YAMLSections.push_back(NewYAMLSection);
  }
}

static void
dumpFunctionDefinition(COFFYAML::Symbol *Sym,
                       const object::coff_aux_function_definition *ObjFD) {
  COFF::AuxiliaryFunctionDefinition YAMLFD;
  YAMLFD.TagIndex = ObjFD->TagIndex;
  YAMLFD.TotalSize = ObjFD->TotalSize;
  YAMLFD.PointerToLinenumber = ObjFD->PointerToLinenumber;
  YAMLFD.PointerToNextFunction = ObjFD->PointerToNextFunction;

  Sym->FunctionDefinition = YAMLFD;
}

static void
dumpbfAndEfLineInfo(COFFYAML::Symbol *Sym,
                    const object::coff_aux_bf_and_ef_symbol *ObjBES) {
  COFF::AuxiliarybfAndefSymbol YAMLAAS;
  YAMLAAS.Linenumber = ObjBES->Linenumber;
  YAMLAAS.PointerToNextFunction = ObjBES->PointerToNextFunction;

  Sym->bfAndefSymbol = YAMLAAS;
}

static void dumpWeakExternal(COFFYAML::Symbol *Sym,
                             const object::coff_aux_weak_external *ObjWE) {
  COFF::AuxiliaryWeakExternal YAMLWE;
  YAMLWE.TagIndex = ObjWE->TagIndex;
  YAMLWE.Characteristics = ObjWE->Characteristics;

  Sym->WeakExternal = YAMLWE;
}

static void
dumpSectionDefinition(COFFYAML::Symbol *Sym,
                      const object::coff_aux_section_definition *ObjSD,
                      bool IsBigObj) {
  COFF::AuxiliarySectionDefinition YAMLASD;
  int32_t AuxNumber = ObjSD->getNumber(IsBigObj);
  YAMLASD.Length = ObjSD->Length;
  YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations;
  YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers;
  YAMLASD.CheckSum = ObjSD->CheckSum;
  YAMLASD.Number = AuxNumber;
  YAMLASD.Selection = ObjSD->Selection;

  Sym->SectionDefinition = YAMLASD;
}

static void
dumpCLRTokenDefinition(COFFYAML::Symbol *Sym,
                       const object::coff_aux_clr_token *ObjCLRToken) {
  COFF::AuxiliaryCLRToken YAMLCLRToken;
  YAMLCLRToken.AuxType = ObjCLRToken->AuxType;
  YAMLCLRToken.SymbolTableIndex = ObjCLRToken->SymbolTableIndex;

  Sym->CLRToken = YAMLCLRToken;
}

void COFFDumper::dumpSymbols(unsigned NumSymbols) {
  ExitOnError Err("invalid symbol table");

  std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
  for (const auto &S : Obj.symbols()) {
    object::COFFSymbolRef Symbol = Obj.getCOFFSymbol(S);
    COFFYAML::Symbol Sym;
    Sym.Name = Err(Obj.getSymbolName(Symbol));
    Sym.SimpleType = COFF::SymbolBaseType(Symbol.getBaseType());
    Sym.ComplexType = COFF::SymbolComplexType(Symbol.getComplexType());
    Sym.Header.StorageClass = Symbol.getStorageClass();
    Sym.Header.Value = Symbol.getValue();
    Sym.Header.SectionNumber = Symbol.getSectionNumber();
    Sym.Header.NumberOfAuxSymbols = Symbol.getNumberOfAuxSymbols();

    if (Symbol.getNumberOfAuxSymbols() > 0) {
      ArrayRef<uint8_t> AuxData = Obj.getSymbolAuxData(Symbol);
      if (Symbol.isFunctionDefinition()) {
        // This symbol represents a function definition.
        assert(Symbol.getNumberOfAuxSymbols() == 1 &&
               "Expected a single aux symbol to describe this function!");

        const object::coff_aux_function_definition *ObjFD =
            reinterpret_cast<const object::coff_aux_function_definition *>(
                AuxData.data());
        dumpFunctionDefinition(&Sym, ObjFD);
      } else if (Symbol.isFunctionLineInfo()) {
        // This symbol describes function line number information.
        assert(Symbol.getNumberOfAuxSymbols() == 1 &&
               "Expected a single aux symbol to describe this function!");

        const object::coff_aux_bf_and_ef_symbol *ObjBES =
            reinterpret_cast<const object::coff_aux_bf_and_ef_symbol *>(
                AuxData.data());
        dumpbfAndEfLineInfo(&Sym, ObjBES);
      } else if (Symbol.isAnyUndefined()) {
        // This symbol represents a weak external definition.
        assert(Symbol.getNumberOfAuxSymbols() == 1 &&
               "Expected a single aux symbol to describe this weak symbol!");

        const object::coff_aux_weak_external *ObjWE =
            reinterpret_cast<const object::coff_aux_weak_external *>(
                AuxData.data());
        dumpWeakExternal(&Sym, ObjWE);
      } else if (Symbol.isFileRecord()) {
        // This symbol represents a file record.
        Sym.File = StringRef(reinterpret_cast<const char *>(AuxData.data()),
                             Symbol.getNumberOfAuxSymbols() *
                                 Obj.getSymbolTableEntrySize())
                       .rtrim(StringRef("\0", /*length=*/1));
      } else if (Symbol.isSectionDefinition()) {
        // This symbol represents a section definition.
        assert(Symbol.getNumberOfAuxSymbols() == 1 &&
               "Expected a single aux symbol to describe this section!");

        const object::coff_aux_section_definition *ObjSD =
            reinterpret_cast<const object::coff_aux_section_definition *>(
                AuxData.data());
        dumpSectionDefinition(&Sym, ObjSD, Symbol.isBigObj());
      } else if (Symbol.isCLRToken()) {
        // This symbol represents a CLR token definition.
        assert(Symbol.getNumberOfAuxSymbols() == 1 &&
               "Expected a single aux symbol to describe this CLR Token!");

        const object::coff_aux_clr_token *ObjCLRToken =
            reinterpret_cast<const object::coff_aux_clr_token *>(
                AuxData.data());
        dumpCLRTokenDefinition(&Sym, ObjCLRToken);
      } else {
        llvm_unreachable("Unhandled auxiliary symbol!");
      }
    }
    Symbols.push_back(Sym);
  }
}

COFFYAML::Object &COFFDumper::getYAMLObj() {
  return YAMLObj;
}

std::error_code coff2yaml(raw_ostream &Out, const object::COFFObjectFile &Obj) {
  COFFDumper Dumper(Obj);

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

  return std::error_code();
}
