//===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains an implementation of a Win32 COFF object file writer.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/MCWinCOFFObjectWriter.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSymbolCOFF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/JamCRC.h"
#include "llvm/Support/TimeValue.h"
#include <cstdio>
#include <ctime>

using namespace llvm;

#define DEBUG_TYPE "WinCOFFObjectWriter"

namespace {
typedef SmallString<COFF::NameSize> name;

enum AuxiliaryType {
  ATFunctionDefinition,
  ATbfAndefSymbol,
  ATWeakExternal,
  ATFile,
  ATSectionDefinition
};

struct AuxSymbol {
  AuxiliaryType AuxType;
  COFF::Auxiliary Aux;
};

class COFFSymbol;
class COFFSection;

class COFFSymbol {
public:
  COFF::symbol Data;

  typedef SmallVector<AuxSymbol, 1> AuxiliarySymbols;

  name Name;
  int Index;
  AuxiliarySymbols Aux;
  COFFSymbol *Other;
  COFFSection *Section;
  int Relocations;

  const MCSymbol *MC;

  COFFSymbol(StringRef name);
  void set_name_offset(uint32_t Offset);

  int64_t getIndex() const { return Index; }
  void setIndex(int Value) {
    Index = Value;
    if (MC)
      MC->setIndex(static_cast<uint32_t>(Value));
  }
};

// This class contains staging data for a COFF relocation entry.
struct COFFRelocation {
  COFF::relocation Data;
  COFFSymbol *Symb;

  COFFRelocation() : Symb(nullptr) {}
  static size_t size() { return COFF::RelocationSize; }
};

typedef std::vector<COFFRelocation> relocations;

class COFFSection {
public:
  COFF::section Header;

  std::string Name;
  int Number;
  MCSectionCOFF const *MCSection;
  COFFSymbol *Symbol;
  relocations Relocations;

  COFFSection(StringRef name);
};

class WinCOFFObjectWriter : public MCObjectWriter {
public:
  typedef std::vector<std::unique_ptr<COFFSymbol>> symbols;
  typedef std::vector<std::unique_ptr<COFFSection>> sections;

  typedef DenseMap<MCSymbol const *, COFFSymbol *> symbol_map;
  typedef DenseMap<MCSection const *, COFFSection *> section_map;

  std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;

  // Root level file contents.
  COFF::header Header;
  sections Sections;
  symbols Symbols;
  StringTableBuilder Strings{StringTableBuilder::WinCOFF};

  // Maps used during object file creation.
  section_map SectionMap;
  symbol_map SymbolMap;

  bool UseBigObj;

  WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_pwrite_stream &OS);

  void reset() override {
    memset(&Header, 0, sizeof(Header));
    Header.Machine = TargetObjectWriter->getMachine();
    Sections.clear();
    Symbols.clear();
    Strings.clear();
    SectionMap.clear();
    SymbolMap.clear();
    MCObjectWriter::reset();
  }

  COFFSymbol *createSymbol(StringRef Name);
  COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol);
  COFFSection *createSection(StringRef Name);

  template <typename object_t, typename list_t>
  object_t *createCOFFEntity(StringRef Name, list_t &List);

  void defineSection(MCSectionCOFF const &Sec);

  COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
  void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
                    const MCAsmLayout &Layout);

  void SetSymbolName(COFFSymbol &S);
  void SetSectionName(COFFSection &S);

  bool IsPhysicalSection(COFFSection *S);

  // Entity writing methods.

  void WriteFileHeader(const COFF::header &Header);
  void WriteSymbol(const COFFSymbol &S);
  void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
  void writeSectionHeader(const COFF::section &S);
  void WriteRelocation(const COFF::relocation &R);

  // MCObjectWriter interface implementation.

  void executePostLayoutBinding(MCAssembler &Asm,
                                const MCAsmLayout &Layout) override;

  bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                              const MCSymbol &SymA,
                                              const MCFragment &FB, bool InSet,
                                              bool IsPCRel) const override;

  bool isWeak(const MCSymbol &Sym) const override;

  void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
                        const MCFragment *Fragment, const MCFixup &Fixup,
                        MCValue Target, bool &IsPCRel,
                        uint64_t &FixedValue) override;

  void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
};
}

static inline void write_uint32_le(void *Data, uint32_t Value) {
  support::endian::write<uint32_t, support::little, support::unaligned>(Data,
                                                                        Value);
}

//------------------------------------------------------------------------------
// Symbol class implementation

COFFSymbol::COFFSymbol(StringRef name)
    : Name(name.begin(), name.end()), Other(nullptr), Section(nullptr),
      Relocations(0), MC(nullptr) {
  memset(&Data, 0, sizeof(Data));
}

// In the case that the name does not fit within 8 bytes, the offset
// into the string table is stored in the last 4 bytes instead, leaving
// the first 4 bytes as 0.
void COFFSymbol::set_name_offset(uint32_t Offset) {
  write_uint32_le(Data.Name + 0, 0);
  write_uint32_le(Data.Name + 4, Offset);
}

//------------------------------------------------------------------------------
// Section class implementation

COFFSection::COFFSection(StringRef name)
    : Name(name), MCSection(nullptr), Symbol(nullptr) {
  memset(&Header, 0, sizeof(Header));
}

//------------------------------------------------------------------------------
// WinCOFFObjectWriter class implementation

WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
                                         raw_pwrite_stream &OS)
    : MCObjectWriter(OS, true), TargetObjectWriter(MOTW) {
  memset(&Header, 0, sizeof(Header));

  Header.Machine = TargetObjectWriter->getMachine();
}

COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
  return createCOFFEntity<COFFSymbol>(Name, Symbols);
}

COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) {
  symbol_map::iterator i = SymbolMap.find(Symbol);
  if (i != SymbolMap.end())
    return i->second;
  COFFSymbol *RetSymbol =
      createCOFFEntity<COFFSymbol>(Symbol->getName(), Symbols);
  SymbolMap[Symbol] = RetSymbol;
  return RetSymbol;
}

COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) {
  return createCOFFEntity<COFFSection>(Name, Sections);
}

/// A template used to lookup or create a symbol/section, and initialize it if
/// needed.
template <typename object_t, typename list_t>
object_t *WinCOFFObjectWriter::createCOFFEntity(StringRef Name, list_t &List) {
  List.push_back(make_unique<object_t>(Name));

  return List.back().get();
}

/// This function takes a section data object from the assembler
/// and creates the associated COFF section staging object.
void WinCOFFObjectWriter::defineSection(MCSectionCOFF const &Sec) {
  COFFSection *coff_section = createSection(Sec.getSectionName());
  COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName());
  if (Sec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
    if (const MCSymbol *S = Sec.getCOMDATSymbol()) {
      COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
      if (COMDATSymbol->Section)
        report_fatal_error("two sections have the same comdat");
      COMDATSymbol->Section = coff_section;
    }
  }

  coff_section->Symbol = coff_symbol;
  coff_symbol->Section = coff_section;
  coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;

  // In this case the auxiliary symbol is a Section Definition.
  coff_symbol->Aux.resize(1);
  memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
  coff_symbol->Aux[0].AuxType = ATSectionDefinition;
  coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection();

  coff_section->Header.Characteristics = Sec.getCharacteristics();

  uint32_t &Characteristics = coff_section->Header.Characteristics;
  switch (Sec.getAlignment()) {
  case 1:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_1BYTES;
    break;
  case 2:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_2BYTES;
    break;
  case 4:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_4BYTES;
    break;
  case 8:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_8BYTES;
    break;
  case 16:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_16BYTES;
    break;
  case 32:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_32BYTES;
    break;
  case 64:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_64BYTES;
    break;
  case 128:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_128BYTES;
    break;
  case 256:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_256BYTES;
    break;
  case 512:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_512BYTES;
    break;
  case 1024:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_1024BYTES;
    break;
  case 2048:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_2048BYTES;
    break;
  case 4096:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_4096BYTES;
    break;
  case 8192:
    Characteristics |= COFF::IMAGE_SCN_ALIGN_8192BYTES;
    break;
  default:
    llvm_unreachable("unsupported section alignment");
  }

  // Bind internal COFF section to MC section.
  coff_section->MCSection = &Sec;
  SectionMap[&Sec] = coff_section;
}

static uint64_t getSymbolValue(const MCSymbol &Symbol,
                               const MCAsmLayout &Layout) {
  if (Symbol.isCommon() && Symbol.isExternal())
    return Symbol.getCommonSize();

  uint64_t Res;
  if (!Layout.getSymbolOffset(Symbol, Res))
    return 0;

  return Res;
}

COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
  if (!Symbol.isVariable())
    return nullptr;

  const MCSymbolRefExpr *SymRef =
      dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
  if (!SymRef)
    return nullptr;

  const MCSymbol &Aliasee = SymRef->getSymbol();
  if (!Aliasee.isUndefined())
    return nullptr;
  return GetOrCreateCOFFSymbol(&Aliasee);
}

/// This function takes a symbol data object from the assembler
/// and creates the associated COFF symbol staging object.
void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
                                       MCAssembler &Assembler,
                                       const MCAsmLayout &Layout) {
  COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
  const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
  COFFSection *Sec = nullptr;
  if (Base && Base->getFragment()) {
    Sec = SectionMap[Base->getFragment()->getParent()];
    if (coff_symbol->Section && coff_symbol->Section != Sec)
      report_fatal_error("conflicting sections for symbol");
  }

  COFFSymbol *Local = nullptr;
  if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
    coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;

    COFFSymbol *WeakDefault = getLinkedSymbol(Symbol);
    if (!WeakDefault) {
      std::string WeakName = (".weak." + Symbol.getName() + ".default").str();
      WeakDefault = createSymbol(WeakName);
      if (!Sec)
        WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
      else
        WeakDefault->Section = Sec;
      Local = WeakDefault;
    }

    coff_symbol->Other = WeakDefault;

    // Setup the Weak External auxiliary symbol.
    coff_symbol->Aux.resize(1);
    memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
    coff_symbol->Aux[0].AuxType = ATWeakExternal;
    coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
    coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
        COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
  } else {
    if (!Base)
      coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
    else
      coff_symbol->Section = Sec;
    Local = coff_symbol;
  }

  if (Local) {
    Local->Data.Value = getSymbolValue(Symbol, Layout);

    const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol);
    Local->Data.Type = SymbolCOFF.getType();
    Local->Data.StorageClass = SymbolCOFF.getClass();

    // If no storage class was specified in the streamer, define it here.
    if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
      bool IsExternal = Symbol.isExternal() ||
                        (!Symbol.getFragment() && !Symbol.isVariable());

      Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
                                            : COFF::IMAGE_SYM_CLASS_STATIC;
    }
  }

  coff_symbol->MC = &Symbol;
}

// Maximum offsets for different string table entry encodings.
enum : unsigned { Max7DecimalOffset = 9999999U };
enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0

// Encode a string table entry offset in base 64, padded to 6 chars, and
// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
// Buffer must be at least 8 bytes large. No terminating null appended.
static void encodeBase64StringEntry(char *Buffer, uint64_t Value) {
  assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset &&
         "Illegal section name encoding for value");

  static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                 "abcdefghijklmnopqrstuvwxyz"
                                 "0123456789+/";

  Buffer[0] = '/';
  Buffer[1] = '/';

  char *Ptr = Buffer + 7;
  for (unsigned i = 0; i < 6; ++i) {
    unsigned Rem = Value % 64;
    Value /= 64;
    *(Ptr--) = Alphabet[Rem];
  }
}

void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
  if (S.Name.size() > COFF::NameSize) {
    uint64_t StringTableEntry = Strings.getOffset(S.Name);

    if (StringTableEntry <= Max7DecimalOffset) {
      SmallVector<char, COFF::NameSize> Buffer;
      Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer);
      assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2);

      std::memcpy(S.Header.Name, Buffer.data(), Buffer.size());
    } else if (StringTableEntry <= MaxBase64Offset) {
      // Starting with 10,000,000, offsets are encoded as base64.
      encodeBase64StringEntry(S.Header.Name, StringTableEntry);
    } else {
      report_fatal_error("COFF string table is greater than 64 GB.");
    }
  } else {
    std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
  }
}

void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
  if (S.Name.size() > COFF::NameSize)
    S.set_name_offset(Strings.getOffset(S.Name));
  else
    std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
}

bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
  return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==
         0;
}

//------------------------------------------------------------------------------
// entity writing methods

void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
  if (UseBigObj) {
    writeLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
    writeLE16(0xFFFF);
    writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
    writeLE16(Header.Machine);
    writeLE32(Header.TimeDateStamp);
    writeBytes(StringRef(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)));
    writeLE32(0);
    writeLE32(0);
    writeLE32(0);
    writeLE32(0);
    writeLE32(Header.NumberOfSections);
    writeLE32(Header.PointerToSymbolTable);
    writeLE32(Header.NumberOfSymbols);
  } else {
    writeLE16(Header.Machine);
    writeLE16(static_cast<int16_t>(Header.NumberOfSections));
    writeLE32(Header.TimeDateStamp);
    writeLE32(Header.PointerToSymbolTable);
    writeLE32(Header.NumberOfSymbols);
    writeLE16(Header.SizeOfOptionalHeader);
    writeLE16(Header.Characteristics);
  }
}

void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
  writeBytes(StringRef(S.Data.Name, COFF::NameSize));
  writeLE32(S.Data.Value);
  if (UseBigObj)
    writeLE32(S.Data.SectionNumber);
  else
    writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
  writeLE16(S.Data.Type);
  write8(S.Data.StorageClass);
  write8(S.Data.NumberOfAuxSymbols);
  WriteAuxiliarySymbols(S.Aux);
}

void WinCOFFObjectWriter::WriteAuxiliarySymbols(
    const COFFSymbol::AuxiliarySymbols &S) {
  for (const AuxSymbol &i : S) {
    switch (i.AuxType) {
    case ATFunctionDefinition:
      writeLE32(i.Aux.FunctionDefinition.TagIndex);
      writeLE32(i.Aux.FunctionDefinition.TotalSize);
      writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber);
      writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction);
      WriteZeros(sizeof(i.Aux.FunctionDefinition.unused));
      if (UseBigObj)
        WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
      break;
    case ATbfAndefSymbol:
      WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused1));
      writeLE16(i.Aux.bfAndefSymbol.Linenumber);
      WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused2));
      writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction);
      WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused3));
      if (UseBigObj)
        WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
      break;
    case ATWeakExternal:
      writeLE32(i.Aux.WeakExternal.TagIndex);
      writeLE32(i.Aux.WeakExternal.Characteristics);
      WriteZeros(sizeof(i.Aux.WeakExternal.unused));
      if (UseBigObj)
        WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
      break;
    case ATFile:
      writeBytes(
          StringRef(reinterpret_cast<const char *>(&i.Aux),
                    UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size));
      break;
    case ATSectionDefinition:
      writeLE32(i.Aux.SectionDefinition.Length);
      writeLE16(i.Aux.SectionDefinition.NumberOfRelocations);
      writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers);
      writeLE32(i.Aux.SectionDefinition.CheckSum);
      writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
      write8(i.Aux.SectionDefinition.Selection);
      WriteZeros(sizeof(i.Aux.SectionDefinition.unused));
      writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
      if (UseBigObj)
        WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
      break;
    }
  }
}

void WinCOFFObjectWriter::writeSectionHeader(const COFF::section &S) {
  writeBytes(StringRef(S.Name, COFF::NameSize));

  writeLE32(S.VirtualSize);
  writeLE32(S.VirtualAddress);
  writeLE32(S.SizeOfRawData);
  writeLE32(S.PointerToRawData);
  writeLE32(S.PointerToRelocations);
  writeLE32(S.PointerToLineNumbers);
  writeLE16(S.NumberOfRelocations);
  writeLE16(S.NumberOfLineNumbers);
  writeLE32(S.Characteristics);
}

void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
  writeLE32(R.VirtualAddress);
  writeLE32(R.SymbolTableIndex);
  writeLE16(R.Type);
}

////////////////////////////////////////////////////////////////////////////////
// MCObjectWriter interface implementations

void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
                                                   const MCAsmLayout &Layout) {
  // "Define" each section & symbol. This creates section & symbol
  // entries in the staging area.
  for (const auto &Section : Asm)
    defineSection(static_cast<const MCSectionCOFF &>(Section));

  for (const MCSymbol &Symbol : Asm.symbols())
    if (!Symbol.isTemporary())
      DefineSymbol(Symbol, Asm, Layout);
}

bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
    const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
    bool InSet, bool IsPCRel) const {
  // MS LINK expects to be able to replace all references to a function with a
  // thunk to implement their /INCREMENTAL feature.  Make sure we don't optimize
  // away any relocations to functions.
  uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
  if (Asm.isIncrementalLinkerCompatible() &&
      (Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
    return false;
  return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
                                                                InSet, IsPCRel);
}

bool WinCOFFObjectWriter::isWeak(const MCSymbol &Sym) const {
  if (!Sym.isExternal())
    return false;

  if (!Sym.isInSection())
    return false;

  const auto &Sec = cast<MCSectionCOFF>(Sym.getSection());
  if (!Sec.getCOMDATSymbol())
    return false;

  // It looks like for COFF it is invalid to replace a reference to a global
  // in a comdat with a reference to a local.
  // FIXME: Add a specification reference if available.
  return true;
}

void WinCOFFObjectWriter::recordRelocation(
    MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment,
    const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) {
  assert(Target.getSymA() && "Relocation must reference a symbol!");

  const MCSymbol &A = Target.getSymA()->getSymbol();
  if (!A.isRegistered()) {
    Asm.getContext().reportError(Fixup.getLoc(),
                                      Twine("symbol '") + A.getName() +
                                          "' can not be undefined");
    return;
  }
  if (A.isTemporary() && A.isUndefined()) {
    Asm.getContext().reportError(Fixup.getLoc(),
                                      Twine("assembler label '") + A.getName() +
                                          "' can not be undefined");
    return;
  }

  MCSection *Section = Fragment->getParent();

  // Mark this symbol as requiring an entry in the symbol table.
  assert(SectionMap.find(Section) != SectionMap.end() &&
         "Section must already have been defined in executePostLayoutBinding!");

  COFFSection *coff_section = SectionMap[Section];
  const MCSymbolRefExpr *SymB = Target.getSymB();
  bool CrossSection = false;

  if (SymB) {
    const MCSymbol *B = &SymB->getSymbol();
    if (!B->getFragment()) {
      Asm.getContext().reportError(
          Fixup.getLoc(),
          Twine("symbol '") + B->getName() +
              "' can not be undefined in a subtraction expression");
      return;
    }

    if (!A.getFragment()) {
      Asm.getContext().reportError(
          Fixup.getLoc(),
          Twine("symbol '") + A.getName() +
              "' can not be undefined in a subtraction expression");
      return;
    }

    CrossSection = &A.getSection() != &B->getSection();

    // Offset of the symbol in the section
    int64_t OffsetOfB = Layout.getSymbolOffset(*B);

    // In the case where we have SymbA and SymB, we just need to store the delta
    // between the two symbols.  Update FixedValue to account for the delta, and
    // skip recording the relocation.
    if (!CrossSection) {
      int64_t OffsetOfA = Layout.getSymbolOffset(A);
      FixedValue = (OffsetOfA - OffsetOfB) + Target.getConstant();
      return;
    }

    // Offset of the relocation in the section
    int64_t OffsetOfRelocation =
        Layout.getFragmentOffset(Fragment) + Fixup.getOffset();

    FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant();
  } else {
    FixedValue = Target.getConstant();
  }

  COFFRelocation Reloc;

  Reloc.Data.SymbolTableIndex = 0;
  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);

  // Turn relocations for temporary symbols into section relocations.
  if (A.isTemporary() || CrossSection) {
    MCSection *TargetSection = &A.getSection();
    assert(
        SectionMap.find(TargetSection) != SectionMap.end() &&
        "Section must already have been defined in executePostLayoutBinding!");
    Reloc.Symb = SectionMap[TargetSection]->Symbol;
    FixedValue += Layout.getSymbolOffset(A);
  } else {
    assert(
        SymbolMap.find(&A) != SymbolMap.end() &&
        "Symbol must already have been defined in executePostLayoutBinding!");
    Reloc.Symb = SymbolMap[&A];
  }

  ++Reloc.Symb->Relocations;

  Reloc.Data.VirtualAddress += Fixup.getOffset();
  Reloc.Data.Type = TargetObjectWriter->getRelocType(
      Target, Fixup, CrossSection, Asm.getBackend());

  // FIXME: Can anyone explain what this does other than adjust for the size
  // of the offset?
  if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
       Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
      (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
       Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32))
    FixedValue += 4;

  if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
    switch (Reloc.Data.Type) {
    case COFF::IMAGE_REL_ARM_ABSOLUTE:
    case COFF::IMAGE_REL_ARM_ADDR32:
    case COFF::IMAGE_REL_ARM_ADDR32NB:
    case COFF::IMAGE_REL_ARM_TOKEN:
    case COFF::IMAGE_REL_ARM_SECTION:
    case COFF::IMAGE_REL_ARM_SECREL:
      break;
    case COFF::IMAGE_REL_ARM_BRANCH11:
    case COFF::IMAGE_REL_ARM_BLX11:
    // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for
    // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid
    // for Windows CE).
    case COFF::IMAGE_REL_ARM_BRANCH24:
    case COFF::IMAGE_REL_ARM_BLX24:
    case COFF::IMAGE_REL_ARM_MOV32A:
      // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are
      // only used for ARM mode code, which is documented as being unsupported
      // by Windows on ARM.  Empirical proof indicates that masm is able to
      // generate the relocations however the rest of the MSVC toolchain is
      // unable to handle it.
      llvm_unreachable("unsupported relocation");
      break;
    case COFF::IMAGE_REL_ARM_MOV32T:
      break;
    case COFF::IMAGE_REL_ARM_BRANCH20T:
    case COFF::IMAGE_REL_ARM_BRANCH24T:
    case COFF::IMAGE_REL_ARM_BLX23T:
      // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all
      // perform a 4 byte adjustment to the relocation.  Relative branches are
      // offset by 4 on ARM, however, because there is no RELA relocations, all
      // branches are offset by 4.
      FixedValue = FixedValue + 4;
      break;
    }
  }

  // The fixed value never makes sense for section indicies, ignore it.
  if (Fixup.getKind() == FK_SecRel_2)
    FixedValue = 0;

  if (TargetObjectWriter->recordRelocation(Fixup))
    coff_section->Relocations.push_back(Reloc);
}

void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
                                      const MCAsmLayout &Layout) {
  size_t SectionsSize = Sections.size();
  if (SectionsSize > static_cast<size_t>(INT32_MAX))
    report_fatal_error(
        "PE COFF object files can't have more than 2147483647 sections");

  // Assign symbol and section indexes and offsets.
  int32_t NumberOfSections = static_cast<int32_t>(SectionsSize);

  UseBigObj = NumberOfSections > COFF::MaxNumberOfSections16;

  // Assign section numbers.
  size_t Number = 1;
  for (const auto &Section : Sections) {
    Section->Number = Number;
    Section->Symbol->Data.SectionNumber = Number;
    Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number;
    ++Number;
  }

  Header.NumberOfSections = NumberOfSections;
  Header.NumberOfSymbols = 0;

  for (const std::string &Name : Asm.getFileNames()) {
    // round up to calculate the number of auxiliary symbols required
    unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
    unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize;

    COFFSymbol *file = createSymbol(".file");
    file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG;
    file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
    file->Aux.resize(Count);

    unsigned Offset = 0;
    unsigned Length = Name.size();
    for (auto &Aux : file->Aux) {
      Aux.AuxType = ATFile;

      if (Length > SymbolSize) {
        memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize);
        Length = Length - SymbolSize;
      } else {
        memcpy(&Aux.Aux, Name.c_str() + Offset, Length);
        memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length);
        break;
      }

      Offset += SymbolSize;
    }
  }

  for (auto &Symbol : Symbols) {
    // Update section number & offset for symbols that have them.
    if (Symbol->Section)
      Symbol->Data.SectionNumber = Symbol->Section->Number;
    Symbol->setIndex(Header.NumberOfSymbols++);
    // Update auxiliary symbol info.
    Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
    Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
  }

  // Build string table.
  for (const auto &S : Sections)
    if (S->Name.size() > COFF::NameSize)
      Strings.add(S->Name);
  for (const auto &S : Symbols)
    if (S->Name.size() > COFF::NameSize)
      Strings.add(S->Name);
  Strings.finalize();

  // Set names.
  for (const auto &S : Sections)
    SetSectionName(*S);
  for (auto &S : Symbols)
    SetSymbolName(*S);

  // Fixup weak external references.
  for (auto &Symbol : Symbols) {
    if (Symbol->Other) {
      assert(Symbol->getIndex() != -1);
      assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!");
      assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
             "Symbol's aux symbol must be a Weak External!");
      Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex();
    }
  }

  // Fixup associative COMDAT sections.
  for (auto &Section : Sections) {
    if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
        COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
      continue;

    const MCSectionCOFF &MCSec = *Section->MCSection;

    const MCSymbol *COMDAT = MCSec.getCOMDATSymbol();
    assert(COMDAT);
    COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT);
    assert(COMDATSymbol);
    COFFSection *Assoc = COMDATSymbol->Section;
    if (!Assoc)
      report_fatal_error(
          Twine("Missing associated COMDAT section for section ") +
          MCSec.getSectionName());

    // Skip this section if the associated section is unused.
    if (Assoc->Number == -1)
      continue;

    Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
  }

  // Assign file offsets to COFF object file structures.

  unsigned offset = getInitialOffset();

  if (UseBigObj)
    offset += COFF::Header32Size;
  else
    offset += COFF::Header16Size;
  offset += COFF::SectionSize * Header.NumberOfSections;

  for (const auto &Section : Asm) {
    COFFSection *Sec = SectionMap[&Section];

    if (Sec->Number == -1)
      continue;

    Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section);

    if (IsPhysicalSection(Sec)) {
      // Align the section data to a four byte boundary.
      offset = alignTo(offset, 4);
      Sec->Header.PointerToRawData = offset;

      offset += Sec->Header.SizeOfRawData;
    }

    if (Sec->Relocations.size() > 0) {
      bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;

      if (RelocationsOverflow) {
        // Signal overflow by setting NumberOfRelocations to max value. Actual
        // size is found in reloc #0. Microsoft tools understand this.
        Sec->Header.NumberOfRelocations = 0xffff;
      } else {
        Sec->Header.NumberOfRelocations = Sec->Relocations.size();
      }
      Sec->Header.PointerToRelocations = offset;

      if (RelocationsOverflow) {
        // Reloc #0 will contain actual count, so make room for it.
        offset += COFF::RelocationSize;
      }

      offset += COFF::RelocationSize * Sec->Relocations.size();

      for (auto &Relocation : Sec->Relocations) {
        assert(Relocation.Symb->getIndex() != -1);
        Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
      }
    }

    assert(Sec->Symbol->Aux.size() == 1 &&
           "Section's symbol must have one aux!");
    AuxSymbol &Aux = Sec->Symbol->Aux[0];
    assert(Aux.AuxType == ATSectionDefinition &&
           "Section's symbol's aux symbol must be a Section Definition!");
    Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
    Aux.Aux.SectionDefinition.NumberOfRelocations =
        Sec->Header.NumberOfRelocations;
    Aux.Aux.SectionDefinition.NumberOfLinenumbers =
        Sec->Header.NumberOfLineNumbers;
  }

  Header.PointerToSymbolTable = offset;

  // MS LINK expects to be able to use this timestamp to implement their
  // /INCREMENTAL feature.
  if (Asm.isIncrementalLinkerCompatible()) {
    std::time_t Now = time(nullptr);
    if (Now < 0 || !isUInt<32>(Now))
      Now = UINT32_MAX;
    Header.TimeDateStamp = Now;
  } else {
    // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU.
    Header.TimeDateStamp = 0;
  }

  // Write it all to disk...
  WriteFileHeader(Header);

  {
    sections::iterator i, ie;
    MCAssembler::iterator j, je;

    for (auto &Section : Sections) {
      if (Section->Number != -1) {
        if (Section->Relocations.size() >= 0xffff)
          Section->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
        writeSectionHeader(Section->Header);
      }
    }

    SmallVector<char, 128> SectionContents;
    for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(),
        je = Asm.end();
         (i != ie) && (j != je); ++i, ++j) {

      if ((*i)->Number == -1)
        continue;

      if ((*i)->Header.PointerToRawData != 0) {
        assert(getStream().tell() <= (*i)->Header.PointerToRawData &&
               "Section::PointerToRawData is insane!");

        unsigned SectionDataPadding =
            (*i)->Header.PointerToRawData - getStream().tell();
        assert(SectionDataPadding < 4 &&
               "Should only need at most three bytes of padding!");

        WriteZeros(SectionDataPadding);

        // Save the contents of the section to a temporary buffer, we need this
        // to CRC the data before we dump it into the object file.
        SectionContents.clear();
        raw_svector_ostream VecOS(SectionContents);
        raw_pwrite_stream &OldStream = getStream();
        // Redirect the output stream to our buffer.
        setStream(VecOS);
        // Fill our buffer with the section data.
        Asm.writeSectionData(&*j, Layout);
        // Reset the stream back to what it was before.
        setStream(OldStream);

        // Calculate our CRC with an initial value of '0', this is not how
        // JamCRC is specified but it aligns with the expected output.
        JamCRC JC(/*Init=*/0x00000000U);
        JC.update(SectionContents);

        // Write the section contents to the object file.
        getStream() << SectionContents;

        // Update the section definition auxiliary symbol to record the CRC.
        COFFSection *Sec = SectionMap[&*j];
        COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux;
        assert(AuxSyms.size() == 1 &&
               AuxSyms[0].AuxType == ATSectionDefinition);
        AuxSymbol &SecDef = AuxSyms[0];
        SecDef.Aux.SectionDefinition.CheckSum = JC.getCRC();
      }

      if ((*i)->Relocations.size() > 0) {
        assert(getStream().tell() == (*i)->Header.PointerToRelocations &&
               "Section::PointerToRelocations is insane!");

        if ((*i)->Relocations.size() >= 0xffff) {
          // In case of overflow, write actual relocation count as first
          // relocation. Including the synthetic reloc itself (+ 1).
          COFF::relocation r;
          r.VirtualAddress = (*i)->Relocations.size() + 1;
          r.SymbolTableIndex = 0;
          r.Type = 0;
          WriteRelocation(r);
        }

        for (const auto &Relocation : (*i)->Relocations)
          WriteRelocation(Relocation.Data);
      } else
        assert((*i)->Header.PointerToRelocations == 0 &&
               "Section::PointerToRelocations is insane!");
    }
  }

  assert(getStream().tell() == Header.PointerToSymbolTable &&
         "Header::PointerToSymbolTable is insane!");

  for (auto &Symbol : Symbols)
    if (Symbol->getIndex() != -1)
      WriteSymbol(*Symbol);

  getStream().write(Strings.data().data(), Strings.data().size());
}

MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)
    : Machine(Machine_) {}

// Pin the vtable to this file.
void MCWinCOFFObjectTargetWriter::anchor() {}

//------------------------------------------------------------------------------
// WinCOFFObjectWriter factory function

MCObjectWriter *
llvm::createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
                                raw_pwrite_stream &OS) {
  return new WinCOFFObjectWriter(MOTW, OS);
}
