//===------ 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) {
  const object::pe32_header *PE32Header = nullptr;
  Obj.getPE32Header(PE32Header);
  if (PE32Header) {
    dumpOptionalHeader(PE32Header);
  } else {
    const object::pe32plus_header *PE32PlusHeader = nullptr;
    Obj.getPE32PlusHeader(PE32PlusHeader);
    if (PE32PlusHeader) {
      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;
    if (Obj.getDataDirectory(I++, 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;

    StringRef SectionName;
    S.getName(SectionName);
    ArrayRef<uint8_t> sectionData;
    if (SectionName != ".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);

  StringMap<bool> SymbolUnique;
  for (const auto &S : Obj.symbols()) {
    object::COFFSymbolRef Symbol = Obj.getCOFFSymbol(S);
    StringRef Name;
    Obj.getSymbolName(Symbol, Name);
    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;
    ObjSection.getName(NewYAMLSection.Name);
    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) {
  std::vector<COFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
  for (const auto &S : Obj.symbols()) {
    object::COFFSymbolRef Symbol = Obj.getCOFFSymbol(S);
    COFFYAML::Symbol Sym;
    Obj.getSymbolName(Symbol, Sym.Name);
    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();
}
