//===-------------- COFF.cpp - JIT linker function for COFF -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// COFF jit-link function.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/JITLink/COFF.h"

#include "llvm/BinaryFormat/COFF.h"
#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cstring>

using namespace llvm;

#define DEBUG_TYPE "jitlink"

namespace llvm {
namespace jitlink {

static StringRef getMachineName(uint16_t Machine) {
  switch (Machine) {
  case COFF::IMAGE_FILE_MACHINE_I386:
    return "i386";
  case COFF::IMAGE_FILE_MACHINE_AMD64:
    return "x86_64";
  case COFF::IMAGE_FILE_MACHINE_ARMNT:
    return "ARM";
  case COFF::IMAGE_FILE_MACHINE_ARM64:
    return "ARM64";
  default:
    return "unknown";
  }
}

Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer) {
  StringRef Data = ObjectBuffer.getBuffer();

  // Check magic
  auto Magic = identify_magic(ObjectBuffer.getBuffer());
  if (Magic != file_magic::coff_object)
    return make_error<JITLinkError>("Invalid COFF buffer");

  if (Data.size() < sizeof(object::coff_file_header))
    return make_error<JITLinkError>("Truncated COFF buffer");

  uint64_t CurPtr = 0;
  bool IsPE = false;

  // Check if this is a PE/COFF file.
  if (Data.size() >= sizeof(object::dos_header) + sizeof(COFF::PEMagic)) {
    const auto *DH =
        reinterpret_cast<const object::dos_header *>(Data.data() + CurPtr);
    if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
      // Check the PE magic bytes. ("PE\0\0")
      CurPtr = DH->AddressOfNewExeHeader;
      if (memcmp(Data.data() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) !=
          0) {
        return make_error<JITLinkError>("Incorrect PE magic");
      }
      CurPtr += sizeof(COFF::PEMagic);
      IsPE = true;
    }
  }
  if (Data.size() < CurPtr + sizeof(object::coff_file_header))
    return make_error<JITLinkError>("Truncated COFF buffer");

  const object::coff_file_header *COFFHeader =
      reinterpret_cast<const object::coff_file_header *>(Data.data() + CurPtr);
  const object::coff_bigobj_file_header *COFFBigObjHeader = nullptr;

  // Deal with bigobj file
  if (!IsPE && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
      COFFHeader->NumberOfSections == uint16_t(0xffff) &&
      Data.size() >= sizeof(object::coff_bigobj_file_header)) {
    if (Data.size() < sizeof(object::coff_file_header)) {
      return make_error<JITLinkError>("Truncated COFF buffer");
    }
    COFFBigObjHeader =
        reinterpret_cast<const object::coff_bigobj_file_header *>(Data.data() +
                                                                  CurPtr);

    // Verify that we are dealing with bigobj.
    if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
        std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
                    sizeof(COFF::BigObjMagic)) == 0) {
      COFFHeader = nullptr;
      CurPtr += sizeof(object::coff_bigobj_file_header);
    } else
      COFFBigObjHeader = nullptr;
  }

  uint16_t Machine =
      COFFHeader ? COFFHeader->Machine : COFFBigObjHeader->Machine;
  LLVM_DEBUG({
    dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")
           << ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")
           << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "
           << "machine = " << getMachineName(Machine) << "\n";
  });

  switch (Machine) {
  case COFF::IMAGE_FILE_MACHINE_AMD64:
    return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer);
  default:
    return make_error<JITLinkError>(
        "Unsupported target machine architecture in COFF object " +
        ObjectBuffer.getBufferIdentifier() + ": " + getMachineName(Machine));
  }
}

void link_COFF(std::unique_ptr<LinkGraph> G,
               std::unique_ptr<JITLinkContext> Ctx) {
  switch (G->getTargetTriple().getArch()) {
  case Triple::x86_64:
    link_COFF_x86_64(std::move(G), std::move(Ctx));
    return;
  default:
    Ctx->notifyFailed(make_error<JITLinkError>(
        "Unsupported target machine architecture in COFF link graph " +
        G->getName()));
    return;
  }
}

} // end namespace jitlink
} // end namespace llvm
