106f32e7eSjoerg //===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file contains an implementation of a Win32 COFF object file writer.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #include "llvm/ADT/DenseMap.h"
14*da58b97aSjoerg #include "llvm/ADT/DenseSet.h"
1506f32e7eSjoerg #include "llvm/ADT/STLExtras.h"
1606f32e7eSjoerg #include "llvm/ADT/SmallString.h"
1706f32e7eSjoerg #include "llvm/ADT/SmallVector.h"
1806f32e7eSjoerg #include "llvm/ADT/StringRef.h"
1906f32e7eSjoerg #include "llvm/ADT/Twine.h"
2006f32e7eSjoerg #include "llvm/BinaryFormat/COFF.h"
2106f32e7eSjoerg #include "llvm/MC/MCAsmLayout.h"
2206f32e7eSjoerg #include "llvm/MC/MCAssembler.h"
2306f32e7eSjoerg #include "llvm/MC/MCContext.h"
2406f32e7eSjoerg #include "llvm/MC/MCExpr.h"
2506f32e7eSjoerg #include "llvm/MC/MCFixup.h"
2606f32e7eSjoerg #include "llvm/MC/MCFragment.h"
2706f32e7eSjoerg #include "llvm/MC/MCObjectWriter.h"
2806f32e7eSjoerg #include "llvm/MC/MCSection.h"
2906f32e7eSjoerg #include "llvm/MC/MCSectionCOFF.h"
3006f32e7eSjoerg #include "llvm/MC/MCSymbol.h"
3106f32e7eSjoerg #include "llvm/MC/MCSymbolCOFF.h"
3206f32e7eSjoerg #include "llvm/MC/MCValue.h"
3306f32e7eSjoerg #include "llvm/MC/MCWinCOFFObjectWriter.h"
3406f32e7eSjoerg #include "llvm/MC/StringTableBuilder.h"
3506f32e7eSjoerg #include "llvm/Support/CRC.h"
3606f32e7eSjoerg #include "llvm/Support/Casting.h"
37*da58b97aSjoerg #include "llvm/Support/EndianStream.h"
3806f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
3906f32e7eSjoerg #include "llvm/Support/LEB128.h"
4006f32e7eSjoerg #include "llvm/Support/MathExtras.h"
4106f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
4206f32e7eSjoerg #include <algorithm>
4306f32e7eSjoerg #include <cassert>
4406f32e7eSjoerg #include <cstddef>
4506f32e7eSjoerg #include <cstdint>
4606f32e7eSjoerg #include <cstring>
4706f32e7eSjoerg #include <ctime>
4806f32e7eSjoerg #include <memory>
4906f32e7eSjoerg #include <string>
5006f32e7eSjoerg #include <vector>
5106f32e7eSjoerg 
5206f32e7eSjoerg using namespace llvm;
5306f32e7eSjoerg using llvm::support::endian::write32le;
5406f32e7eSjoerg 
5506f32e7eSjoerg #define DEBUG_TYPE "WinCOFFObjectWriter"
5606f32e7eSjoerg 
5706f32e7eSjoerg namespace {
5806f32e7eSjoerg 
5906f32e7eSjoerg using name = SmallString<COFF::NameSize>;
6006f32e7eSjoerg 
6106f32e7eSjoerg enum AuxiliaryType {
6206f32e7eSjoerg   ATWeakExternal,
6306f32e7eSjoerg   ATFile,
6406f32e7eSjoerg   ATSectionDefinition
6506f32e7eSjoerg };
6606f32e7eSjoerg 
6706f32e7eSjoerg struct AuxSymbol {
6806f32e7eSjoerg   AuxiliaryType AuxType;
6906f32e7eSjoerg   COFF::Auxiliary Aux;
7006f32e7eSjoerg };
7106f32e7eSjoerg 
7206f32e7eSjoerg class COFFSection;
7306f32e7eSjoerg 
7406f32e7eSjoerg class COFFSymbol {
7506f32e7eSjoerg public:
7606f32e7eSjoerg   COFF::symbol Data = {};
7706f32e7eSjoerg 
7806f32e7eSjoerg   using AuxiliarySymbols = SmallVector<AuxSymbol, 1>;
7906f32e7eSjoerg 
8006f32e7eSjoerg   name Name;
8106f32e7eSjoerg   int Index;
8206f32e7eSjoerg   AuxiliarySymbols Aux;
8306f32e7eSjoerg   COFFSymbol *Other = nullptr;
8406f32e7eSjoerg   COFFSection *Section = nullptr;
8506f32e7eSjoerg   int Relocations = 0;
8606f32e7eSjoerg   const MCSymbol *MC = nullptr;
8706f32e7eSjoerg 
COFFSymbol(StringRef Name)8806f32e7eSjoerg   COFFSymbol(StringRef Name) : Name(Name) {}
8906f32e7eSjoerg 
9006f32e7eSjoerg   void set_name_offset(uint32_t Offset);
9106f32e7eSjoerg 
getIndex() const9206f32e7eSjoerg   int64_t getIndex() const { return Index; }
setIndex(int Value)9306f32e7eSjoerg   void setIndex(int Value) {
9406f32e7eSjoerg     Index = Value;
9506f32e7eSjoerg     if (MC)
9606f32e7eSjoerg       MC->setIndex(static_cast<uint32_t>(Value));
9706f32e7eSjoerg   }
9806f32e7eSjoerg };
9906f32e7eSjoerg 
10006f32e7eSjoerg // This class contains staging data for a COFF relocation entry.
10106f32e7eSjoerg struct COFFRelocation {
10206f32e7eSjoerg   COFF::relocation Data;
10306f32e7eSjoerg   COFFSymbol *Symb = nullptr;
10406f32e7eSjoerg 
10506f32e7eSjoerg   COFFRelocation() = default;
10606f32e7eSjoerg 
size__anone71771500111::COFFRelocation10706f32e7eSjoerg   static size_t size() { return COFF::RelocationSize; }
10806f32e7eSjoerg };
10906f32e7eSjoerg 
11006f32e7eSjoerg using relocations = std::vector<COFFRelocation>;
11106f32e7eSjoerg 
11206f32e7eSjoerg class COFFSection {
11306f32e7eSjoerg public:
11406f32e7eSjoerg   COFF::section Header = {};
11506f32e7eSjoerg 
11606f32e7eSjoerg   std::string Name;
11706f32e7eSjoerg   int Number;
11806f32e7eSjoerg   MCSectionCOFF const *MCSection = nullptr;
11906f32e7eSjoerg   COFFSymbol *Symbol = nullptr;
12006f32e7eSjoerg   relocations Relocations;
12106f32e7eSjoerg 
COFFSection(StringRef Name)122*da58b97aSjoerg   COFFSection(StringRef Name) : Name(std::string(Name)) {}
12306f32e7eSjoerg };
12406f32e7eSjoerg 
12506f32e7eSjoerg class WinCOFFObjectWriter : public MCObjectWriter {
12606f32e7eSjoerg public:
12706f32e7eSjoerg   support::endian::Writer W;
12806f32e7eSjoerg 
12906f32e7eSjoerg   using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
13006f32e7eSjoerg   using sections = std::vector<std::unique_ptr<COFFSection>>;
13106f32e7eSjoerg 
13206f32e7eSjoerg   using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>;
13306f32e7eSjoerg   using section_map = DenseMap<MCSection const *, COFFSection *>;
13406f32e7eSjoerg 
135*da58b97aSjoerg   using symbol_list = DenseSet<COFFSymbol *>;
136*da58b97aSjoerg 
13706f32e7eSjoerg   std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
13806f32e7eSjoerg 
13906f32e7eSjoerg   // Root level file contents.
14006f32e7eSjoerg   COFF::header Header = {};
14106f32e7eSjoerg   sections Sections;
14206f32e7eSjoerg   symbols Symbols;
14306f32e7eSjoerg   StringTableBuilder Strings{StringTableBuilder::WinCOFF};
14406f32e7eSjoerg 
14506f32e7eSjoerg   // Maps used during object file creation.
14606f32e7eSjoerg   section_map SectionMap;
14706f32e7eSjoerg   symbol_map SymbolMap;
14806f32e7eSjoerg 
149*da58b97aSjoerg   symbol_list WeakDefaults;
150*da58b97aSjoerg 
15106f32e7eSjoerg   bool UseBigObj;
15206f32e7eSjoerg 
15306f32e7eSjoerg   bool EmitAddrsigSection = false;
15406f32e7eSjoerg   MCSectionCOFF *AddrsigSection;
15506f32e7eSjoerg   std::vector<const MCSymbol *> AddrsigSyms;
15606f32e7eSjoerg 
157*da58b97aSjoerg   MCSectionCOFF *CGProfileSection = nullptr;
158*da58b97aSjoerg 
15906f32e7eSjoerg   WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
16006f32e7eSjoerg                       raw_pwrite_stream &OS);
16106f32e7eSjoerg 
reset()16206f32e7eSjoerg   void reset() override {
16306f32e7eSjoerg     memset(&Header, 0, sizeof(Header));
16406f32e7eSjoerg     Header.Machine = TargetObjectWriter->getMachine();
16506f32e7eSjoerg     Sections.clear();
16606f32e7eSjoerg     Symbols.clear();
16706f32e7eSjoerg     Strings.clear();
16806f32e7eSjoerg     SectionMap.clear();
16906f32e7eSjoerg     SymbolMap.clear();
17006f32e7eSjoerg     MCObjectWriter::reset();
17106f32e7eSjoerg   }
17206f32e7eSjoerg 
17306f32e7eSjoerg   COFFSymbol *createSymbol(StringRef Name);
17406f32e7eSjoerg   COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol);
17506f32e7eSjoerg   COFFSection *createSection(StringRef Name);
17606f32e7eSjoerg 
17706f32e7eSjoerg   void defineSection(MCSectionCOFF const &Sec);
17806f32e7eSjoerg 
17906f32e7eSjoerg   COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
18006f32e7eSjoerg   void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
18106f32e7eSjoerg                     const MCAsmLayout &Layout);
18206f32e7eSjoerg 
18306f32e7eSjoerg   void SetSymbolName(COFFSymbol &S);
18406f32e7eSjoerg   void SetSectionName(COFFSection &S);
18506f32e7eSjoerg 
18606f32e7eSjoerg   bool IsPhysicalSection(COFFSection *S);
18706f32e7eSjoerg 
18806f32e7eSjoerg   // Entity writing methods.
18906f32e7eSjoerg 
19006f32e7eSjoerg   void WriteFileHeader(const COFF::header &Header);
19106f32e7eSjoerg   void WriteSymbol(const COFFSymbol &S);
19206f32e7eSjoerg   void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
19306f32e7eSjoerg   void writeSectionHeaders();
19406f32e7eSjoerg   void WriteRelocation(const COFF::relocation &R);
19506f32e7eSjoerg   uint32_t writeSectionContents(MCAssembler &Asm, const MCAsmLayout &Layout,
19606f32e7eSjoerg                                 const MCSection &MCSec);
19706f32e7eSjoerg   void writeSection(MCAssembler &Asm, const MCAsmLayout &Layout,
19806f32e7eSjoerg                     const COFFSection &Sec, const MCSection &MCSec);
19906f32e7eSjoerg 
20006f32e7eSjoerg   // MCObjectWriter interface implementation.
20106f32e7eSjoerg 
20206f32e7eSjoerg   void executePostLayoutBinding(MCAssembler &Asm,
20306f32e7eSjoerg                                 const MCAsmLayout &Layout) override;
20406f32e7eSjoerg 
20506f32e7eSjoerg   bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
20606f32e7eSjoerg                                               const MCSymbol &SymA,
20706f32e7eSjoerg                                               const MCFragment &FB, bool InSet,
20806f32e7eSjoerg                                               bool IsPCRel) const override;
20906f32e7eSjoerg 
21006f32e7eSjoerg   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
21106f32e7eSjoerg                         const MCFragment *Fragment, const MCFixup &Fixup,
21206f32e7eSjoerg                         MCValue Target, uint64_t &FixedValue) override;
21306f32e7eSjoerg 
21406f32e7eSjoerg   void createFileSymbols(MCAssembler &Asm);
215*da58b97aSjoerg   void setWeakDefaultNames();
21606f32e7eSjoerg   void assignSectionNumbers();
21706f32e7eSjoerg   void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
21806f32e7eSjoerg 
emitAddrsigSection()21906f32e7eSjoerg   void emitAddrsigSection() override { EmitAddrsigSection = true; }
addAddrsigSymbol(const MCSymbol * Sym)22006f32e7eSjoerg   void addAddrsigSymbol(const MCSymbol *Sym) override {
22106f32e7eSjoerg     AddrsigSyms.push_back(Sym);
22206f32e7eSjoerg   }
22306f32e7eSjoerg 
22406f32e7eSjoerg   uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
22506f32e7eSjoerg };
22606f32e7eSjoerg 
22706f32e7eSjoerg } // end anonymous namespace
22806f32e7eSjoerg 
22906f32e7eSjoerg //------------------------------------------------------------------------------
23006f32e7eSjoerg // Symbol class implementation
23106f32e7eSjoerg 
23206f32e7eSjoerg // In the case that the name does not fit within 8 bytes, the offset
23306f32e7eSjoerg // into the string table is stored in the last 4 bytes instead, leaving
23406f32e7eSjoerg // the first 4 bytes as 0.
set_name_offset(uint32_t Offset)23506f32e7eSjoerg void COFFSymbol::set_name_offset(uint32_t Offset) {
23606f32e7eSjoerg   write32le(Data.Name + 0, 0);
23706f32e7eSjoerg   write32le(Data.Name + 4, Offset);
23806f32e7eSjoerg }
23906f32e7eSjoerg 
24006f32e7eSjoerg //------------------------------------------------------------------------------
24106f32e7eSjoerg // WinCOFFObjectWriter class implementation
24206f32e7eSjoerg 
WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,raw_pwrite_stream & OS)24306f32e7eSjoerg WinCOFFObjectWriter::WinCOFFObjectWriter(
24406f32e7eSjoerg     std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
24506f32e7eSjoerg     : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {
24606f32e7eSjoerg   Header.Machine = TargetObjectWriter->getMachine();
24706f32e7eSjoerg }
24806f32e7eSjoerg 
createSymbol(StringRef Name)24906f32e7eSjoerg COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
25006f32e7eSjoerg   Symbols.push_back(std::make_unique<COFFSymbol>(Name));
25106f32e7eSjoerg   return Symbols.back().get();
25206f32e7eSjoerg }
25306f32e7eSjoerg 
GetOrCreateCOFFSymbol(const MCSymbol * Symbol)25406f32e7eSjoerg COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) {
25506f32e7eSjoerg   COFFSymbol *&Ret = SymbolMap[Symbol];
25606f32e7eSjoerg   if (!Ret)
25706f32e7eSjoerg     Ret = createSymbol(Symbol->getName());
25806f32e7eSjoerg   return Ret;
25906f32e7eSjoerg }
26006f32e7eSjoerg 
createSection(StringRef Name)26106f32e7eSjoerg COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) {
26206f32e7eSjoerg   Sections.emplace_back(std::make_unique<COFFSection>(Name));
26306f32e7eSjoerg   return Sections.back().get();
26406f32e7eSjoerg }
26506f32e7eSjoerg 
getAlignment(const MCSectionCOFF & Sec)26606f32e7eSjoerg static uint32_t getAlignment(const MCSectionCOFF &Sec) {
26706f32e7eSjoerg   switch (Sec.getAlignment()) {
26806f32e7eSjoerg   case 1:
26906f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_1BYTES;
27006f32e7eSjoerg   case 2:
27106f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_2BYTES;
27206f32e7eSjoerg   case 4:
27306f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_4BYTES;
27406f32e7eSjoerg   case 8:
27506f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_8BYTES;
27606f32e7eSjoerg   case 16:
27706f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_16BYTES;
27806f32e7eSjoerg   case 32:
27906f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_32BYTES;
28006f32e7eSjoerg   case 64:
28106f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_64BYTES;
28206f32e7eSjoerg   case 128:
28306f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_128BYTES;
28406f32e7eSjoerg   case 256:
28506f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_256BYTES;
28606f32e7eSjoerg   case 512:
28706f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_512BYTES;
28806f32e7eSjoerg   case 1024:
28906f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_1024BYTES;
29006f32e7eSjoerg   case 2048:
29106f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_2048BYTES;
29206f32e7eSjoerg   case 4096:
29306f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_4096BYTES;
29406f32e7eSjoerg   case 8192:
29506f32e7eSjoerg     return COFF::IMAGE_SCN_ALIGN_8192BYTES;
29606f32e7eSjoerg   }
29706f32e7eSjoerg   llvm_unreachable("unsupported section alignment");
29806f32e7eSjoerg }
29906f32e7eSjoerg 
30006f32e7eSjoerg /// This function takes a section data object from the assembler
30106f32e7eSjoerg /// and creates the associated COFF section staging object.
defineSection(const MCSectionCOFF & MCSec)30206f32e7eSjoerg void WinCOFFObjectWriter::defineSection(const MCSectionCOFF &MCSec) {
303*da58b97aSjoerg   COFFSection *Section = createSection(MCSec.getName());
304*da58b97aSjoerg   COFFSymbol *Symbol = createSymbol(MCSec.getName());
30506f32e7eSjoerg   Section->Symbol = Symbol;
30606f32e7eSjoerg   Symbol->Section = Section;
30706f32e7eSjoerg   Symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
30806f32e7eSjoerg 
30906f32e7eSjoerg   // Create a COMDAT symbol if needed.
31006f32e7eSjoerg   if (MCSec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
31106f32e7eSjoerg     if (const MCSymbol *S = MCSec.getCOMDATSymbol()) {
31206f32e7eSjoerg       COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
31306f32e7eSjoerg       if (COMDATSymbol->Section)
31406f32e7eSjoerg         report_fatal_error("two sections have the same comdat");
31506f32e7eSjoerg       COMDATSymbol->Section = Section;
31606f32e7eSjoerg     }
31706f32e7eSjoerg   }
31806f32e7eSjoerg 
31906f32e7eSjoerg   // In this case the auxiliary symbol is a Section Definition.
32006f32e7eSjoerg   Symbol->Aux.resize(1);
32106f32e7eSjoerg   Symbol->Aux[0] = {};
32206f32e7eSjoerg   Symbol->Aux[0].AuxType = ATSectionDefinition;
32306f32e7eSjoerg   Symbol->Aux[0].Aux.SectionDefinition.Selection = MCSec.getSelection();
32406f32e7eSjoerg 
32506f32e7eSjoerg   // Set section alignment.
32606f32e7eSjoerg   Section->Header.Characteristics = MCSec.getCharacteristics();
32706f32e7eSjoerg   Section->Header.Characteristics |= getAlignment(MCSec);
32806f32e7eSjoerg 
32906f32e7eSjoerg   // Bind internal COFF section to MC section.
33006f32e7eSjoerg   Section->MCSection = &MCSec;
33106f32e7eSjoerg   SectionMap[&MCSec] = Section;
33206f32e7eSjoerg }
33306f32e7eSjoerg 
getSymbolValue(const MCSymbol & Symbol,const MCAsmLayout & Layout)33406f32e7eSjoerg static uint64_t getSymbolValue(const MCSymbol &Symbol,
33506f32e7eSjoerg                                const MCAsmLayout &Layout) {
33606f32e7eSjoerg   if (Symbol.isCommon() && Symbol.isExternal())
33706f32e7eSjoerg     return Symbol.getCommonSize();
33806f32e7eSjoerg 
33906f32e7eSjoerg   uint64_t Res;
34006f32e7eSjoerg   if (!Layout.getSymbolOffset(Symbol, Res))
34106f32e7eSjoerg     return 0;
34206f32e7eSjoerg 
34306f32e7eSjoerg   return Res;
34406f32e7eSjoerg }
34506f32e7eSjoerg 
getLinkedSymbol(const MCSymbol & Symbol)34606f32e7eSjoerg COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
34706f32e7eSjoerg   if (!Symbol.isVariable())
34806f32e7eSjoerg     return nullptr;
34906f32e7eSjoerg 
35006f32e7eSjoerg   const MCSymbolRefExpr *SymRef =
35106f32e7eSjoerg       dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
35206f32e7eSjoerg   if (!SymRef)
35306f32e7eSjoerg     return nullptr;
35406f32e7eSjoerg 
35506f32e7eSjoerg   const MCSymbol &Aliasee = SymRef->getSymbol();
356*da58b97aSjoerg   if (Aliasee.isUndefined() || Aliasee.isExternal())
35706f32e7eSjoerg     return GetOrCreateCOFFSymbol(&Aliasee);
358*da58b97aSjoerg   else
359*da58b97aSjoerg     return nullptr;
36006f32e7eSjoerg }
36106f32e7eSjoerg 
36206f32e7eSjoerg /// This function takes a symbol data object from the assembler
36306f32e7eSjoerg /// and creates the associated COFF symbol staging object.
DefineSymbol(const MCSymbol & MCSym,MCAssembler & Assembler,const MCAsmLayout & Layout)36406f32e7eSjoerg void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym,
36506f32e7eSjoerg                                        MCAssembler &Assembler,
36606f32e7eSjoerg                                        const MCAsmLayout &Layout) {
36706f32e7eSjoerg   COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym);
36806f32e7eSjoerg   const MCSymbol *Base = Layout.getBaseSymbol(MCSym);
36906f32e7eSjoerg   COFFSection *Sec = nullptr;
37006f32e7eSjoerg   if (Base && Base->getFragment()) {
37106f32e7eSjoerg     Sec = SectionMap[Base->getFragment()->getParent()];
37206f32e7eSjoerg     if (Sym->Section && Sym->Section != Sec)
37306f32e7eSjoerg       report_fatal_error("conflicting sections for symbol");
37406f32e7eSjoerg   }
37506f32e7eSjoerg 
37606f32e7eSjoerg   COFFSymbol *Local = nullptr;
37706f32e7eSjoerg   if (cast<MCSymbolCOFF>(MCSym).isWeakExternal()) {
37806f32e7eSjoerg     Sym->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
379*da58b97aSjoerg     Sym->Section = nullptr;
38006f32e7eSjoerg 
38106f32e7eSjoerg     COFFSymbol *WeakDefault = getLinkedSymbol(MCSym);
38206f32e7eSjoerg     if (!WeakDefault) {
38306f32e7eSjoerg       std::string WeakName = (".weak." + MCSym.getName() + ".default").str();
38406f32e7eSjoerg       WeakDefault = createSymbol(WeakName);
38506f32e7eSjoerg       if (!Sec)
38606f32e7eSjoerg         WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
38706f32e7eSjoerg       else
38806f32e7eSjoerg         WeakDefault->Section = Sec;
389*da58b97aSjoerg       WeakDefaults.insert(WeakDefault);
39006f32e7eSjoerg       Local = WeakDefault;
39106f32e7eSjoerg     }
39206f32e7eSjoerg 
39306f32e7eSjoerg     Sym->Other = WeakDefault;
39406f32e7eSjoerg 
39506f32e7eSjoerg     // Setup the Weak External auxiliary symbol.
39606f32e7eSjoerg     Sym->Aux.resize(1);
39706f32e7eSjoerg     memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0]));
39806f32e7eSjoerg     Sym->Aux[0].AuxType = ATWeakExternal;
39906f32e7eSjoerg     Sym->Aux[0].Aux.WeakExternal.TagIndex = 0;
40006f32e7eSjoerg     Sym->Aux[0].Aux.WeakExternal.Characteristics =
40106f32e7eSjoerg         COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS;
40206f32e7eSjoerg   } else {
40306f32e7eSjoerg     if (!Base)
40406f32e7eSjoerg       Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
40506f32e7eSjoerg     else
40606f32e7eSjoerg       Sym->Section = Sec;
40706f32e7eSjoerg     Local = Sym;
40806f32e7eSjoerg   }
40906f32e7eSjoerg 
41006f32e7eSjoerg   if (Local) {
41106f32e7eSjoerg     Local->Data.Value = getSymbolValue(MCSym, Layout);
41206f32e7eSjoerg 
41306f32e7eSjoerg     const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(MCSym);
41406f32e7eSjoerg     Local->Data.Type = SymbolCOFF.getType();
41506f32e7eSjoerg     Local->Data.StorageClass = SymbolCOFF.getClass();
41606f32e7eSjoerg 
41706f32e7eSjoerg     // If no storage class was specified in the streamer, define it here.
41806f32e7eSjoerg     if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
41906f32e7eSjoerg       bool IsExternal = MCSym.isExternal() ||
42006f32e7eSjoerg                         (!MCSym.getFragment() && !MCSym.isVariable());
42106f32e7eSjoerg 
42206f32e7eSjoerg       Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
42306f32e7eSjoerg                                             : COFF::IMAGE_SYM_CLASS_STATIC;
42406f32e7eSjoerg     }
42506f32e7eSjoerg   }
42606f32e7eSjoerg 
42706f32e7eSjoerg   Sym->MC = &MCSym;
42806f32e7eSjoerg }
42906f32e7eSjoerg 
43006f32e7eSjoerg // Maximum offsets for different string table entry encodings.
43106f32e7eSjoerg enum : unsigned { Max7DecimalOffset = 9999999U };
43206f32e7eSjoerg enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0
43306f32e7eSjoerg 
43406f32e7eSjoerg // Encode a string table entry offset in base 64, padded to 6 chars, and
43506f32e7eSjoerg // prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
43606f32e7eSjoerg // Buffer must be at least 8 bytes large. No terminating null appended.
encodeBase64StringEntry(char * Buffer,uint64_t Value)43706f32e7eSjoerg static void encodeBase64StringEntry(char *Buffer, uint64_t Value) {
43806f32e7eSjoerg   assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset &&
43906f32e7eSjoerg          "Illegal section name encoding for value");
44006f32e7eSjoerg 
44106f32e7eSjoerg   static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
44206f32e7eSjoerg                                  "abcdefghijklmnopqrstuvwxyz"
44306f32e7eSjoerg                                  "0123456789+/";
44406f32e7eSjoerg 
44506f32e7eSjoerg   Buffer[0] = '/';
44606f32e7eSjoerg   Buffer[1] = '/';
44706f32e7eSjoerg 
44806f32e7eSjoerg   char *Ptr = Buffer + 7;
44906f32e7eSjoerg   for (unsigned i = 0; i < 6; ++i) {
45006f32e7eSjoerg     unsigned Rem = Value % 64;
45106f32e7eSjoerg     Value /= 64;
45206f32e7eSjoerg     *(Ptr--) = Alphabet[Rem];
45306f32e7eSjoerg   }
45406f32e7eSjoerg }
45506f32e7eSjoerg 
SetSectionName(COFFSection & S)45606f32e7eSjoerg void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
45706f32e7eSjoerg   if (S.Name.size() <= COFF::NameSize) {
45806f32e7eSjoerg     std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
45906f32e7eSjoerg     return;
46006f32e7eSjoerg   }
46106f32e7eSjoerg 
46206f32e7eSjoerg   uint64_t StringTableEntry = Strings.getOffset(S.Name);
46306f32e7eSjoerg   if (StringTableEntry <= Max7DecimalOffset) {
46406f32e7eSjoerg     SmallVector<char, COFF::NameSize> Buffer;
46506f32e7eSjoerg     Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer);
46606f32e7eSjoerg     assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2);
46706f32e7eSjoerg     std::memcpy(S.Header.Name, Buffer.data(), Buffer.size());
46806f32e7eSjoerg     return;
46906f32e7eSjoerg   }
47006f32e7eSjoerg   if (StringTableEntry <= MaxBase64Offset) {
47106f32e7eSjoerg     // Starting with 10,000,000, offsets are encoded as base64.
47206f32e7eSjoerg     encodeBase64StringEntry(S.Header.Name, StringTableEntry);
47306f32e7eSjoerg     return;
47406f32e7eSjoerg   }
47506f32e7eSjoerg   report_fatal_error("COFF string table is greater than 64 GB.");
47606f32e7eSjoerg }
47706f32e7eSjoerg 
SetSymbolName(COFFSymbol & S)47806f32e7eSjoerg void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
47906f32e7eSjoerg   if (S.Name.size() > COFF::NameSize)
48006f32e7eSjoerg     S.set_name_offset(Strings.getOffset(S.Name));
48106f32e7eSjoerg   else
48206f32e7eSjoerg     std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
48306f32e7eSjoerg }
48406f32e7eSjoerg 
IsPhysicalSection(COFFSection * S)48506f32e7eSjoerg bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
48606f32e7eSjoerg   return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==
48706f32e7eSjoerg          0;
48806f32e7eSjoerg }
48906f32e7eSjoerg 
49006f32e7eSjoerg //------------------------------------------------------------------------------
49106f32e7eSjoerg // entity writing methods
49206f32e7eSjoerg 
WriteFileHeader(const COFF::header & Header)49306f32e7eSjoerg void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
49406f32e7eSjoerg   if (UseBigObj) {
49506f32e7eSjoerg     W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
49606f32e7eSjoerg     W.write<uint16_t>(0xFFFF);
49706f32e7eSjoerg     W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion);
49806f32e7eSjoerg     W.write<uint16_t>(Header.Machine);
49906f32e7eSjoerg     W.write<uint32_t>(Header.TimeDateStamp);
50006f32e7eSjoerg     W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
50106f32e7eSjoerg     W.write<uint32_t>(0);
50206f32e7eSjoerg     W.write<uint32_t>(0);
50306f32e7eSjoerg     W.write<uint32_t>(0);
50406f32e7eSjoerg     W.write<uint32_t>(0);
50506f32e7eSjoerg     W.write<uint32_t>(Header.NumberOfSections);
50606f32e7eSjoerg     W.write<uint32_t>(Header.PointerToSymbolTable);
50706f32e7eSjoerg     W.write<uint32_t>(Header.NumberOfSymbols);
50806f32e7eSjoerg   } else {
50906f32e7eSjoerg     W.write<uint16_t>(Header.Machine);
51006f32e7eSjoerg     W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections));
51106f32e7eSjoerg     W.write<uint32_t>(Header.TimeDateStamp);
51206f32e7eSjoerg     W.write<uint32_t>(Header.PointerToSymbolTable);
51306f32e7eSjoerg     W.write<uint32_t>(Header.NumberOfSymbols);
51406f32e7eSjoerg     W.write<uint16_t>(Header.SizeOfOptionalHeader);
51506f32e7eSjoerg     W.write<uint16_t>(Header.Characteristics);
51606f32e7eSjoerg   }
51706f32e7eSjoerg }
51806f32e7eSjoerg 
WriteSymbol(const COFFSymbol & S)51906f32e7eSjoerg void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
52006f32e7eSjoerg   W.OS.write(S.Data.Name, COFF::NameSize);
52106f32e7eSjoerg   W.write<uint32_t>(S.Data.Value);
52206f32e7eSjoerg   if (UseBigObj)
52306f32e7eSjoerg     W.write<uint32_t>(S.Data.SectionNumber);
52406f32e7eSjoerg   else
52506f32e7eSjoerg     W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber));
52606f32e7eSjoerg   W.write<uint16_t>(S.Data.Type);
52706f32e7eSjoerg   W.OS << char(S.Data.StorageClass);
52806f32e7eSjoerg   W.OS << char(S.Data.NumberOfAuxSymbols);
52906f32e7eSjoerg   WriteAuxiliarySymbols(S.Aux);
53006f32e7eSjoerg }
53106f32e7eSjoerg 
WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols & S)53206f32e7eSjoerg void WinCOFFObjectWriter::WriteAuxiliarySymbols(
53306f32e7eSjoerg     const COFFSymbol::AuxiliarySymbols &S) {
53406f32e7eSjoerg   for (const AuxSymbol &i : S) {
53506f32e7eSjoerg     switch (i.AuxType) {
53606f32e7eSjoerg     case ATWeakExternal:
53706f32e7eSjoerg       W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
53806f32e7eSjoerg       W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
53906f32e7eSjoerg       W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused));
54006f32e7eSjoerg       if (UseBigObj)
54106f32e7eSjoerg         W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
54206f32e7eSjoerg       break;
54306f32e7eSjoerg     case ATFile:
54406f32e7eSjoerg       W.OS.write(reinterpret_cast<const char *>(&i.Aux),
54506f32e7eSjoerg                         UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size);
54606f32e7eSjoerg       break;
54706f32e7eSjoerg     case ATSectionDefinition:
54806f32e7eSjoerg       W.write<uint32_t>(i.Aux.SectionDefinition.Length);
54906f32e7eSjoerg       W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
55006f32e7eSjoerg       W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
55106f32e7eSjoerg       W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum);
55206f32e7eSjoerg       W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
55306f32e7eSjoerg       W.OS << char(i.Aux.SectionDefinition.Selection);
55406f32e7eSjoerg       W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused));
55506f32e7eSjoerg       W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
55606f32e7eSjoerg       if (UseBigObj)
55706f32e7eSjoerg         W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
55806f32e7eSjoerg       break;
55906f32e7eSjoerg     }
56006f32e7eSjoerg   }
56106f32e7eSjoerg }
56206f32e7eSjoerg 
56306f32e7eSjoerg // Write the section header.
writeSectionHeaders()56406f32e7eSjoerg void WinCOFFObjectWriter::writeSectionHeaders() {
56506f32e7eSjoerg   // Section numbers must be monotonically increasing in the section
56606f32e7eSjoerg   // header, but our Sections array is not sorted by section number,
56706f32e7eSjoerg   // so make a copy of Sections and sort it.
56806f32e7eSjoerg   std::vector<COFFSection *> Arr;
56906f32e7eSjoerg   for (auto &Section : Sections)
57006f32e7eSjoerg     Arr.push_back(Section.get());
57106f32e7eSjoerg   llvm::sort(Arr, [](const COFFSection *A, const COFFSection *B) {
57206f32e7eSjoerg     return A->Number < B->Number;
57306f32e7eSjoerg   });
57406f32e7eSjoerg 
57506f32e7eSjoerg   for (auto &Section : Arr) {
57606f32e7eSjoerg     if (Section->Number == -1)
57706f32e7eSjoerg       continue;
57806f32e7eSjoerg 
57906f32e7eSjoerg     COFF::section &S = Section->Header;
58006f32e7eSjoerg     if (Section->Relocations.size() >= 0xffff)
58106f32e7eSjoerg       S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
58206f32e7eSjoerg     W.OS.write(S.Name, COFF::NameSize);
58306f32e7eSjoerg     W.write<uint32_t>(S.VirtualSize);
58406f32e7eSjoerg     W.write<uint32_t>(S.VirtualAddress);
58506f32e7eSjoerg     W.write<uint32_t>(S.SizeOfRawData);
58606f32e7eSjoerg     W.write<uint32_t>(S.PointerToRawData);
58706f32e7eSjoerg     W.write<uint32_t>(S.PointerToRelocations);
58806f32e7eSjoerg     W.write<uint32_t>(S.PointerToLineNumbers);
58906f32e7eSjoerg     W.write<uint16_t>(S.NumberOfRelocations);
59006f32e7eSjoerg     W.write<uint16_t>(S.NumberOfLineNumbers);
59106f32e7eSjoerg     W.write<uint32_t>(S.Characteristics);
59206f32e7eSjoerg   }
59306f32e7eSjoerg }
59406f32e7eSjoerg 
WriteRelocation(const COFF::relocation & R)59506f32e7eSjoerg void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
59606f32e7eSjoerg   W.write<uint32_t>(R.VirtualAddress);
59706f32e7eSjoerg   W.write<uint32_t>(R.SymbolTableIndex);
59806f32e7eSjoerg   W.write<uint16_t>(R.Type);
59906f32e7eSjoerg }
60006f32e7eSjoerg 
60106f32e7eSjoerg // Write MCSec's contents. What this function does is essentially
60206f32e7eSjoerg // "Asm.writeSectionData(&MCSec, Layout)", but it's a bit complicated
60306f32e7eSjoerg // because it needs to compute a CRC.
writeSectionContents(MCAssembler & Asm,const MCAsmLayout & Layout,const MCSection & MCSec)60406f32e7eSjoerg uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
60506f32e7eSjoerg                                                    const MCAsmLayout &Layout,
60606f32e7eSjoerg                                                    const MCSection &MCSec) {
60706f32e7eSjoerg   // Save the contents of the section to a temporary buffer, we need this
60806f32e7eSjoerg   // to CRC the data before we dump it into the object file.
60906f32e7eSjoerg   SmallVector<char, 128> Buf;
61006f32e7eSjoerg   raw_svector_ostream VecOS(Buf);
61106f32e7eSjoerg   Asm.writeSectionData(VecOS, &MCSec, Layout);
61206f32e7eSjoerg 
61306f32e7eSjoerg   // Write the section contents to the object file.
61406f32e7eSjoerg   W.OS << Buf;
61506f32e7eSjoerg 
61606f32e7eSjoerg   // Calculate our CRC with an initial value of '0', this is not how
61706f32e7eSjoerg   // JamCRC is specified but it aligns with the expected output.
61806f32e7eSjoerg   JamCRC JC(/*Init=*/0);
61906f32e7eSjoerg   JC.update(makeArrayRef(reinterpret_cast<uint8_t*>(Buf.data()), Buf.size()));
62006f32e7eSjoerg   return JC.getCRC();
62106f32e7eSjoerg }
62206f32e7eSjoerg 
writeSection(MCAssembler & Asm,const MCAsmLayout & Layout,const COFFSection & Sec,const MCSection & MCSec)62306f32e7eSjoerg void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
62406f32e7eSjoerg                                        const MCAsmLayout &Layout,
62506f32e7eSjoerg                                        const COFFSection &Sec,
62606f32e7eSjoerg                                        const MCSection &MCSec) {
62706f32e7eSjoerg   if (Sec.Number == -1)
62806f32e7eSjoerg     return;
62906f32e7eSjoerg 
63006f32e7eSjoerg   // Write the section contents.
63106f32e7eSjoerg   if (Sec.Header.PointerToRawData != 0) {
63206f32e7eSjoerg     assert(W.OS.tell() == Sec.Header.PointerToRawData &&
63306f32e7eSjoerg            "Section::PointerToRawData is insane!");
63406f32e7eSjoerg 
63506f32e7eSjoerg     uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
63606f32e7eSjoerg 
63706f32e7eSjoerg     // Update the section definition auxiliary symbol to record the CRC.
63806f32e7eSjoerg     COFFSection *Sec = SectionMap[&MCSec];
63906f32e7eSjoerg     COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux;
64006f32e7eSjoerg     assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition);
64106f32e7eSjoerg     AuxSymbol &SecDef = AuxSyms[0];
64206f32e7eSjoerg     SecDef.Aux.SectionDefinition.CheckSum = CRC;
64306f32e7eSjoerg   }
64406f32e7eSjoerg 
64506f32e7eSjoerg   // Write relocations for this section.
64606f32e7eSjoerg   if (Sec.Relocations.empty()) {
64706f32e7eSjoerg     assert(Sec.Header.PointerToRelocations == 0 &&
64806f32e7eSjoerg            "Section::PointerToRelocations is insane!");
64906f32e7eSjoerg     return;
65006f32e7eSjoerg   }
65106f32e7eSjoerg 
65206f32e7eSjoerg   assert(W.OS.tell() == Sec.Header.PointerToRelocations &&
65306f32e7eSjoerg          "Section::PointerToRelocations is insane!");
65406f32e7eSjoerg 
65506f32e7eSjoerg   if (Sec.Relocations.size() >= 0xffff) {
65606f32e7eSjoerg     // In case of overflow, write actual relocation count as first
65706f32e7eSjoerg     // relocation. Including the synthetic reloc itself (+ 1).
65806f32e7eSjoerg     COFF::relocation R;
65906f32e7eSjoerg     R.VirtualAddress = Sec.Relocations.size() + 1;
66006f32e7eSjoerg     R.SymbolTableIndex = 0;
66106f32e7eSjoerg     R.Type = 0;
66206f32e7eSjoerg     WriteRelocation(R);
66306f32e7eSjoerg   }
66406f32e7eSjoerg 
66506f32e7eSjoerg   for (const auto &Relocation : Sec.Relocations)
66606f32e7eSjoerg     WriteRelocation(Relocation.Data);
66706f32e7eSjoerg }
66806f32e7eSjoerg 
66906f32e7eSjoerg ////////////////////////////////////////////////////////////////////////////////
67006f32e7eSjoerg // MCObjectWriter interface implementations
67106f32e7eSjoerg 
executePostLayoutBinding(MCAssembler & Asm,const MCAsmLayout & Layout)67206f32e7eSjoerg void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
67306f32e7eSjoerg                                                    const MCAsmLayout &Layout) {
67406f32e7eSjoerg   if (EmitAddrsigSection) {
67506f32e7eSjoerg     AddrsigSection = Asm.getContext().getCOFFSection(
67606f32e7eSjoerg         ".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE,
67706f32e7eSjoerg         SectionKind::getMetadata());
67806f32e7eSjoerg     Asm.registerSection(*AddrsigSection);
67906f32e7eSjoerg   }
68006f32e7eSjoerg 
681*da58b97aSjoerg   if (!Asm.CGProfile.empty()) {
682*da58b97aSjoerg     CGProfileSection = Asm.getContext().getCOFFSection(
683*da58b97aSjoerg         ".llvm.call-graph-profile", COFF::IMAGE_SCN_LNK_REMOVE,
684*da58b97aSjoerg         SectionKind::getMetadata());
685*da58b97aSjoerg     Asm.registerSection(*CGProfileSection);
686*da58b97aSjoerg   }
687*da58b97aSjoerg 
68806f32e7eSjoerg   // "Define" each section & symbol. This creates section & symbol
68906f32e7eSjoerg   // entries in the staging area.
69006f32e7eSjoerg   for (const auto &Section : Asm)
69106f32e7eSjoerg     defineSection(static_cast<const MCSectionCOFF &>(Section));
69206f32e7eSjoerg 
69306f32e7eSjoerg   for (const MCSymbol &Symbol : Asm.symbols())
69406f32e7eSjoerg     if (!Symbol.isTemporary())
69506f32e7eSjoerg       DefineSymbol(Symbol, Asm, Layout);
69606f32e7eSjoerg }
69706f32e7eSjoerg 
isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler & Asm,const MCSymbol & SymA,const MCFragment & FB,bool InSet,bool IsPCRel) const69806f32e7eSjoerg bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
69906f32e7eSjoerg     const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
70006f32e7eSjoerg     bool InSet, bool IsPCRel) const {
70106f32e7eSjoerg   // Don't drop relocations between functions, even if they are in the same text
70206f32e7eSjoerg   // section. Multiple Visual C++ linker features depend on having the
70306f32e7eSjoerg   // relocations present. The /INCREMENTAL flag will cause these relocations to
70406f32e7eSjoerg   // point to thunks, and the /GUARD:CF flag assumes that it can use relocations
70506f32e7eSjoerg   // to approximate the set of all address taken functions. LLD's implementation
70606f32e7eSjoerg   // of /GUARD:CF also relies on the existance of these relocations.
70706f32e7eSjoerg   uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
70806f32e7eSjoerg   if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
70906f32e7eSjoerg     return false;
71006f32e7eSjoerg   return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
71106f32e7eSjoerg                                                                 InSet, IsPCRel);
71206f32e7eSjoerg }
71306f32e7eSjoerg 
recordRelocation(MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)71406f32e7eSjoerg void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
71506f32e7eSjoerg                                            const MCAsmLayout &Layout,
71606f32e7eSjoerg                                            const MCFragment *Fragment,
71706f32e7eSjoerg                                            const MCFixup &Fixup, MCValue Target,
71806f32e7eSjoerg                                            uint64_t &FixedValue) {
71906f32e7eSjoerg   assert(Target.getSymA() && "Relocation must reference a symbol!");
72006f32e7eSjoerg 
72106f32e7eSjoerg   const MCSymbol &A = Target.getSymA()->getSymbol();
72206f32e7eSjoerg   if (!A.isRegistered()) {
72306f32e7eSjoerg     Asm.getContext().reportError(Fixup.getLoc(),
72406f32e7eSjoerg                                       Twine("symbol '") + A.getName() +
72506f32e7eSjoerg                                           "' can not be undefined");
72606f32e7eSjoerg     return;
72706f32e7eSjoerg   }
72806f32e7eSjoerg   if (A.isTemporary() && A.isUndefined()) {
72906f32e7eSjoerg     Asm.getContext().reportError(Fixup.getLoc(),
73006f32e7eSjoerg                                       Twine("assembler label '") + A.getName() +
73106f32e7eSjoerg                                           "' can not be undefined");
73206f32e7eSjoerg     return;
73306f32e7eSjoerg   }
73406f32e7eSjoerg 
73506f32e7eSjoerg   MCSection *MCSec = Fragment->getParent();
73606f32e7eSjoerg 
73706f32e7eSjoerg   // Mark this symbol as requiring an entry in the symbol table.
73806f32e7eSjoerg   assert(SectionMap.find(MCSec) != SectionMap.end() &&
73906f32e7eSjoerg          "Section must already have been defined in executePostLayoutBinding!");
74006f32e7eSjoerg 
74106f32e7eSjoerg   COFFSection *Sec = SectionMap[MCSec];
74206f32e7eSjoerg   const MCSymbolRefExpr *SymB = Target.getSymB();
74306f32e7eSjoerg 
74406f32e7eSjoerg   if (SymB) {
74506f32e7eSjoerg     const MCSymbol *B = &SymB->getSymbol();
74606f32e7eSjoerg     if (!B->getFragment()) {
74706f32e7eSjoerg       Asm.getContext().reportError(
74806f32e7eSjoerg           Fixup.getLoc(),
74906f32e7eSjoerg           Twine("symbol '") + B->getName() +
75006f32e7eSjoerg               "' can not be undefined in a subtraction expression");
75106f32e7eSjoerg       return;
75206f32e7eSjoerg     }
75306f32e7eSjoerg 
75406f32e7eSjoerg     // Offset of the symbol in the section
75506f32e7eSjoerg     int64_t OffsetOfB = Layout.getSymbolOffset(*B);
75606f32e7eSjoerg 
75706f32e7eSjoerg     // Offset of the relocation in the section
75806f32e7eSjoerg     int64_t OffsetOfRelocation =
75906f32e7eSjoerg         Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
76006f32e7eSjoerg 
76106f32e7eSjoerg     FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant();
76206f32e7eSjoerg   } else {
76306f32e7eSjoerg     FixedValue = Target.getConstant();
76406f32e7eSjoerg   }
76506f32e7eSjoerg 
76606f32e7eSjoerg   COFFRelocation Reloc;
76706f32e7eSjoerg 
76806f32e7eSjoerg   Reloc.Data.SymbolTableIndex = 0;
76906f32e7eSjoerg   Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
77006f32e7eSjoerg 
77106f32e7eSjoerg   // Turn relocations for temporary symbols into section relocations.
77206f32e7eSjoerg   if (A.isTemporary()) {
77306f32e7eSjoerg     MCSection *TargetSection = &A.getSection();
77406f32e7eSjoerg     assert(
77506f32e7eSjoerg         SectionMap.find(TargetSection) != SectionMap.end() &&
77606f32e7eSjoerg         "Section must already have been defined in executePostLayoutBinding!");
77706f32e7eSjoerg     Reloc.Symb = SectionMap[TargetSection]->Symbol;
77806f32e7eSjoerg     FixedValue += Layout.getSymbolOffset(A);
77906f32e7eSjoerg   } else {
78006f32e7eSjoerg     assert(
78106f32e7eSjoerg         SymbolMap.find(&A) != SymbolMap.end() &&
78206f32e7eSjoerg         "Symbol must already have been defined in executePostLayoutBinding!");
78306f32e7eSjoerg     Reloc.Symb = SymbolMap[&A];
78406f32e7eSjoerg   }
78506f32e7eSjoerg 
78606f32e7eSjoerg   ++Reloc.Symb->Relocations;
78706f32e7eSjoerg 
78806f32e7eSjoerg   Reloc.Data.VirtualAddress += Fixup.getOffset();
78906f32e7eSjoerg   Reloc.Data.Type = TargetObjectWriter->getRelocType(
79006f32e7eSjoerg       Asm.getContext(), Target, Fixup, SymB, Asm.getBackend());
79106f32e7eSjoerg 
792*da58b97aSjoerg   // The *_REL32 relocations are relative to the end of the relocation,
793*da58b97aSjoerg   // not to the start.
79406f32e7eSjoerg   if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
79506f32e7eSjoerg        Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
79606f32e7eSjoerg       (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
797*da58b97aSjoerg        Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32) ||
798*da58b97aSjoerg       (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT &&
799*da58b97aSjoerg        Reloc.Data.Type == COFF::IMAGE_REL_ARM_REL32) ||
800*da58b97aSjoerg       (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARM64 &&
801*da58b97aSjoerg        Reloc.Data.Type == COFF::IMAGE_REL_ARM64_REL32))
80206f32e7eSjoerg     FixedValue += 4;
80306f32e7eSjoerg 
80406f32e7eSjoerg   if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
80506f32e7eSjoerg     switch (Reloc.Data.Type) {
80606f32e7eSjoerg     case COFF::IMAGE_REL_ARM_ABSOLUTE:
80706f32e7eSjoerg     case COFF::IMAGE_REL_ARM_ADDR32:
80806f32e7eSjoerg     case COFF::IMAGE_REL_ARM_ADDR32NB:
80906f32e7eSjoerg     case COFF::IMAGE_REL_ARM_TOKEN:
81006f32e7eSjoerg     case COFF::IMAGE_REL_ARM_SECTION:
81106f32e7eSjoerg     case COFF::IMAGE_REL_ARM_SECREL:
81206f32e7eSjoerg       break;
81306f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BRANCH11:
81406f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BLX11:
81506f32e7eSjoerg     // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for
81606f32e7eSjoerg     // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid
81706f32e7eSjoerg     // for Windows CE).
81806f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BRANCH24:
81906f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BLX24:
82006f32e7eSjoerg     case COFF::IMAGE_REL_ARM_MOV32A:
82106f32e7eSjoerg       // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are
82206f32e7eSjoerg       // only used for ARM mode code, which is documented as being unsupported
82306f32e7eSjoerg       // by Windows on ARM.  Empirical proof indicates that masm is able to
82406f32e7eSjoerg       // generate the relocations however the rest of the MSVC toolchain is
82506f32e7eSjoerg       // unable to handle it.
82606f32e7eSjoerg       llvm_unreachable("unsupported relocation");
82706f32e7eSjoerg       break;
82806f32e7eSjoerg     case COFF::IMAGE_REL_ARM_MOV32T:
82906f32e7eSjoerg       break;
83006f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BRANCH20T:
83106f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BRANCH24T:
83206f32e7eSjoerg     case COFF::IMAGE_REL_ARM_BLX23T:
83306f32e7eSjoerg       // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all
83406f32e7eSjoerg       // perform a 4 byte adjustment to the relocation.  Relative branches are
83506f32e7eSjoerg       // offset by 4 on ARM, however, because there is no RELA relocations, all
83606f32e7eSjoerg       // branches are offset by 4.
83706f32e7eSjoerg       FixedValue = FixedValue + 4;
83806f32e7eSjoerg       break;
83906f32e7eSjoerg     }
84006f32e7eSjoerg   }
84106f32e7eSjoerg 
84206f32e7eSjoerg   // The fixed value never makes sense for section indices, ignore it.
84306f32e7eSjoerg   if (Fixup.getKind() == FK_SecRel_2)
84406f32e7eSjoerg     FixedValue = 0;
84506f32e7eSjoerg 
84606f32e7eSjoerg   if (TargetObjectWriter->recordRelocation(Fixup))
84706f32e7eSjoerg     Sec->Relocations.push_back(Reloc);
84806f32e7eSjoerg }
84906f32e7eSjoerg 
getTime()85006f32e7eSjoerg static std::time_t getTime() {
85106f32e7eSjoerg   std::time_t Now = time(nullptr);
85206f32e7eSjoerg   if (Now < 0 || !isUInt<32>(Now))
85306f32e7eSjoerg     return UINT32_MAX;
85406f32e7eSjoerg   return Now;
85506f32e7eSjoerg }
85606f32e7eSjoerg 
85706f32e7eSjoerg // Create .file symbols.
createFileSymbols(MCAssembler & Asm)85806f32e7eSjoerg void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
859*da58b97aSjoerg   for (const std::pair<std::string, size_t> &It : Asm.getFileNames()) {
86006f32e7eSjoerg     // round up to calculate the number of auxiliary symbols required
861*da58b97aSjoerg     const std::string &Name = It.first;
86206f32e7eSjoerg     unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
86306f32e7eSjoerg     unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize;
86406f32e7eSjoerg 
86506f32e7eSjoerg     COFFSymbol *File = createSymbol(".file");
86606f32e7eSjoerg     File->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG;
86706f32e7eSjoerg     File->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
86806f32e7eSjoerg     File->Aux.resize(Count);
86906f32e7eSjoerg 
87006f32e7eSjoerg     unsigned Offset = 0;
87106f32e7eSjoerg     unsigned Length = Name.size();
87206f32e7eSjoerg     for (auto &Aux : File->Aux) {
87306f32e7eSjoerg       Aux.AuxType = ATFile;
87406f32e7eSjoerg 
87506f32e7eSjoerg       if (Length > SymbolSize) {
87606f32e7eSjoerg         memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize);
87706f32e7eSjoerg         Length = Length - SymbolSize;
87806f32e7eSjoerg       } else {
87906f32e7eSjoerg         memcpy(&Aux.Aux, Name.c_str() + Offset, Length);
88006f32e7eSjoerg         memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length);
88106f32e7eSjoerg         break;
88206f32e7eSjoerg       }
88306f32e7eSjoerg 
88406f32e7eSjoerg       Offset += SymbolSize;
88506f32e7eSjoerg     }
88606f32e7eSjoerg   }
88706f32e7eSjoerg }
88806f32e7eSjoerg 
setWeakDefaultNames()889*da58b97aSjoerg void WinCOFFObjectWriter::setWeakDefaultNames() {
890*da58b97aSjoerg   if (WeakDefaults.empty())
891*da58b97aSjoerg     return;
892*da58b97aSjoerg 
893*da58b97aSjoerg   // If multiple object files use a weak symbol (either with a regular
894*da58b97aSjoerg   // defined default, or an absolute zero symbol as default), the defaults
895*da58b97aSjoerg   // cause duplicate definitions unless their names are made unique. Look
896*da58b97aSjoerg   // for a defined extern symbol, that isn't comdat - that should be unique
897*da58b97aSjoerg   // unless there are other duplicate definitions. And if none is found,
898*da58b97aSjoerg   // allow picking a comdat symbol, as that's still better than nothing.
899*da58b97aSjoerg 
900*da58b97aSjoerg   COFFSymbol *Unique = nullptr;
901*da58b97aSjoerg   for (bool AllowComdat : {false, true}) {
902*da58b97aSjoerg     for (auto &Sym : Symbols) {
903*da58b97aSjoerg       // Don't include the names of the defaults themselves
904*da58b97aSjoerg       if (WeakDefaults.count(Sym.get()))
905*da58b97aSjoerg         continue;
906*da58b97aSjoerg       // Only consider external symbols
907*da58b97aSjoerg       if (Sym->Data.StorageClass != COFF::IMAGE_SYM_CLASS_EXTERNAL)
908*da58b97aSjoerg         continue;
909*da58b97aSjoerg       // Only consider symbols defined in a section or that are absolute
910*da58b97aSjoerg       if (!Sym->Section && Sym->Data.SectionNumber != COFF::IMAGE_SYM_ABSOLUTE)
911*da58b97aSjoerg         continue;
912*da58b97aSjoerg       if (!AllowComdat && Sym->Section &&
913*da58b97aSjoerg           Sym->Section->Header.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
914*da58b97aSjoerg         continue;
915*da58b97aSjoerg       Unique = Sym.get();
916*da58b97aSjoerg       break;
917*da58b97aSjoerg     }
918*da58b97aSjoerg     if (Unique)
919*da58b97aSjoerg       break;
920*da58b97aSjoerg   }
921*da58b97aSjoerg   // If we didn't find any unique symbol to use for the names, just skip this.
922*da58b97aSjoerg   if (!Unique)
923*da58b97aSjoerg     return;
924*da58b97aSjoerg   for (auto *Sym : WeakDefaults) {
925*da58b97aSjoerg     Sym->Name.append(".");
926*da58b97aSjoerg     Sym->Name.append(Unique->Name);
927*da58b97aSjoerg   }
928*da58b97aSjoerg }
929*da58b97aSjoerg 
isAssociative(const COFFSection & Section)93006f32e7eSjoerg static bool isAssociative(const COFFSection &Section) {
93106f32e7eSjoerg   return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection ==
93206f32e7eSjoerg          COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
93306f32e7eSjoerg }
93406f32e7eSjoerg 
assignSectionNumbers()93506f32e7eSjoerg void WinCOFFObjectWriter::assignSectionNumbers() {
93606f32e7eSjoerg   size_t I = 1;
93706f32e7eSjoerg   auto Assign = [&](COFFSection &Section) {
93806f32e7eSjoerg     Section.Number = I;
93906f32e7eSjoerg     Section.Symbol->Data.SectionNumber = I;
94006f32e7eSjoerg     Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I;
94106f32e7eSjoerg     ++I;
94206f32e7eSjoerg   };
94306f32e7eSjoerg 
94406f32e7eSjoerg   // Although it is not explicitly requested by the Microsoft COFF spec,
94506f32e7eSjoerg   // we should avoid emitting forward associative section references,
94606f32e7eSjoerg   // because MSVC link.exe as of 2017 cannot handle that.
94706f32e7eSjoerg   for (const std::unique_ptr<COFFSection> &Section : Sections)
94806f32e7eSjoerg     if (!isAssociative(*Section))
94906f32e7eSjoerg       Assign(*Section);
95006f32e7eSjoerg   for (const std::unique_ptr<COFFSection> &Section : Sections)
95106f32e7eSjoerg     if (isAssociative(*Section))
95206f32e7eSjoerg       Assign(*Section);
95306f32e7eSjoerg }
95406f32e7eSjoerg 
95506f32e7eSjoerg // Assign file offsets to COFF object file structures.
assignFileOffsets(MCAssembler & Asm,const MCAsmLayout & Layout)95606f32e7eSjoerg void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
95706f32e7eSjoerg                                             const MCAsmLayout &Layout) {
95806f32e7eSjoerg   unsigned Offset = W.OS.tell();
95906f32e7eSjoerg 
96006f32e7eSjoerg   Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size;
96106f32e7eSjoerg   Offset += COFF::SectionSize * Header.NumberOfSections;
96206f32e7eSjoerg 
96306f32e7eSjoerg   for (const auto &Section : Asm) {
96406f32e7eSjoerg     COFFSection *Sec = SectionMap[&Section];
96506f32e7eSjoerg 
96606f32e7eSjoerg     if (Sec->Number == -1)
96706f32e7eSjoerg       continue;
96806f32e7eSjoerg 
96906f32e7eSjoerg     Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section);
97006f32e7eSjoerg 
97106f32e7eSjoerg     if (IsPhysicalSection(Sec)) {
97206f32e7eSjoerg       Sec->Header.PointerToRawData = Offset;
97306f32e7eSjoerg       Offset += Sec->Header.SizeOfRawData;
97406f32e7eSjoerg     }
97506f32e7eSjoerg 
97606f32e7eSjoerg     if (!Sec->Relocations.empty()) {
97706f32e7eSjoerg       bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
97806f32e7eSjoerg 
97906f32e7eSjoerg       if (RelocationsOverflow) {
98006f32e7eSjoerg         // Signal overflow by setting NumberOfRelocations to max value. Actual
98106f32e7eSjoerg         // size is found in reloc #0. Microsoft tools understand this.
98206f32e7eSjoerg         Sec->Header.NumberOfRelocations = 0xffff;
98306f32e7eSjoerg       } else {
98406f32e7eSjoerg         Sec->Header.NumberOfRelocations = Sec->Relocations.size();
98506f32e7eSjoerg       }
98606f32e7eSjoerg       Sec->Header.PointerToRelocations = Offset;
98706f32e7eSjoerg 
98806f32e7eSjoerg       if (RelocationsOverflow) {
98906f32e7eSjoerg         // Reloc #0 will contain actual count, so make room for it.
99006f32e7eSjoerg         Offset += COFF::RelocationSize;
99106f32e7eSjoerg       }
99206f32e7eSjoerg 
99306f32e7eSjoerg       Offset += COFF::RelocationSize * Sec->Relocations.size();
99406f32e7eSjoerg 
99506f32e7eSjoerg       for (auto &Relocation : Sec->Relocations) {
99606f32e7eSjoerg         assert(Relocation.Symb->getIndex() != -1);
99706f32e7eSjoerg         Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
99806f32e7eSjoerg       }
99906f32e7eSjoerg     }
100006f32e7eSjoerg 
100106f32e7eSjoerg     assert(Sec->Symbol->Aux.size() == 1 &&
100206f32e7eSjoerg            "Section's symbol must have one aux!");
100306f32e7eSjoerg     AuxSymbol &Aux = Sec->Symbol->Aux[0];
100406f32e7eSjoerg     assert(Aux.AuxType == ATSectionDefinition &&
100506f32e7eSjoerg            "Section's symbol's aux symbol must be a Section Definition!");
100606f32e7eSjoerg     Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
100706f32e7eSjoerg     Aux.Aux.SectionDefinition.NumberOfRelocations =
100806f32e7eSjoerg         Sec->Header.NumberOfRelocations;
100906f32e7eSjoerg     Aux.Aux.SectionDefinition.NumberOfLinenumbers =
101006f32e7eSjoerg         Sec->Header.NumberOfLineNumbers;
101106f32e7eSjoerg   }
101206f32e7eSjoerg 
101306f32e7eSjoerg   Header.PointerToSymbolTable = Offset;
101406f32e7eSjoerg }
101506f32e7eSjoerg 
writeObject(MCAssembler & Asm,const MCAsmLayout & Layout)101606f32e7eSjoerg uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
101706f32e7eSjoerg                                           const MCAsmLayout &Layout) {
101806f32e7eSjoerg   uint64_t StartOffset = W.OS.tell();
101906f32e7eSjoerg 
102006f32e7eSjoerg   if (Sections.size() > INT32_MAX)
102106f32e7eSjoerg     report_fatal_error(
102206f32e7eSjoerg         "PE COFF object files can't have more than 2147483647 sections");
102306f32e7eSjoerg 
102406f32e7eSjoerg   UseBigObj = Sections.size() > COFF::MaxNumberOfSections16;
102506f32e7eSjoerg   Header.NumberOfSections = Sections.size();
102606f32e7eSjoerg   Header.NumberOfSymbols = 0;
102706f32e7eSjoerg 
1028*da58b97aSjoerg   setWeakDefaultNames();
102906f32e7eSjoerg   assignSectionNumbers();
103006f32e7eSjoerg   createFileSymbols(Asm);
103106f32e7eSjoerg 
103206f32e7eSjoerg   for (auto &Symbol : Symbols) {
103306f32e7eSjoerg     // Update section number & offset for symbols that have them.
103406f32e7eSjoerg     if (Symbol->Section)
103506f32e7eSjoerg       Symbol->Data.SectionNumber = Symbol->Section->Number;
103606f32e7eSjoerg     Symbol->setIndex(Header.NumberOfSymbols++);
103706f32e7eSjoerg     // Update auxiliary symbol info.
103806f32e7eSjoerg     Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
103906f32e7eSjoerg     Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
104006f32e7eSjoerg   }
104106f32e7eSjoerg 
104206f32e7eSjoerg   // Build string table.
104306f32e7eSjoerg   for (const auto &S : Sections)
104406f32e7eSjoerg     if (S->Name.size() > COFF::NameSize)
104506f32e7eSjoerg       Strings.add(S->Name);
104606f32e7eSjoerg   for (const auto &S : Symbols)
104706f32e7eSjoerg     if (S->Name.size() > COFF::NameSize)
104806f32e7eSjoerg       Strings.add(S->Name);
104906f32e7eSjoerg   Strings.finalize();
105006f32e7eSjoerg 
105106f32e7eSjoerg   // Set names.
105206f32e7eSjoerg   for (const auto &S : Sections)
105306f32e7eSjoerg     SetSectionName(*S);
105406f32e7eSjoerg   for (auto &S : Symbols)
105506f32e7eSjoerg     SetSymbolName(*S);
105606f32e7eSjoerg 
105706f32e7eSjoerg   // Fixup weak external references.
105806f32e7eSjoerg   for (auto &Symbol : Symbols) {
105906f32e7eSjoerg     if (Symbol->Other) {
106006f32e7eSjoerg       assert(Symbol->getIndex() != -1);
106106f32e7eSjoerg       assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!");
106206f32e7eSjoerg       assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
106306f32e7eSjoerg              "Symbol's aux symbol must be a Weak External!");
106406f32e7eSjoerg       Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex();
106506f32e7eSjoerg     }
106606f32e7eSjoerg   }
106706f32e7eSjoerg 
106806f32e7eSjoerg   // Fixup associative COMDAT sections.
106906f32e7eSjoerg   for (auto &Section : Sections) {
107006f32e7eSjoerg     if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
107106f32e7eSjoerg         COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
107206f32e7eSjoerg       continue;
107306f32e7eSjoerg 
107406f32e7eSjoerg     const MCSectionCOFF &MCSec = *Section->MCSection;
107506f32e7eSjoerg     const MCSymbol *AssocMCSym = MCSec.getCOMDATSymbol();
107606f32e7eSjoerg     assert(AssocMCSym);
107706f32e7eSjoerg 
107806f32e7eSjoerg     // It's an error to try to associate with an undefined symbol or a symbol
107906f32e7eSjoerg     // without a section.
108006f32e7eSjoerg     if (!AssocMCSym->isInSection()) {
108106f32e7eSjoerg       Asm.getContext().reportError(
1082*da58b97aSjoerg           SMLoc(), Twine("cannot make section ") + MCSec.getName() +
108306f32e7eSjoerg                        Twine(" associative with sectionless symbol ") +
108406f32e7eSjoerg                        AssocMCSym->getName());
108506f32e7eSjoerg       continue;
108606f32e7eSjoerg     }
108706f32e7eSjoerg 
108806f32e7eSjoerg     const auto *AssocMCSec = cast<MCSectionCOFF>(&AssocMCSym->getSection());
108906f32e7eSjoerg     assert(SectionMap.count(AssocMCSec));
109006f32e7eSjoerg     COFFSection *AssocSec = SectionMap[AssocMCSec];
109106f32e7eSjoerg 
109206f32e7eSjoerg     // Skip this section if the associated section is unused.
109306f32e7eSjoerg     if (AssocSec->Number == -1)
109406f32e7eSjoerg       continue;
109506f32e7eSjoerg 
109606f32e7eSjoerg     Section->Symbol->Aux[0].Aux.SectionDefinition.Number = AssocSec->Number;
109706f32e7eSjoerg   }
109806f32e7eSjoerg 
109906f32e7eSjoerg   // Create the contents of the .llvm_addrsig section.
110006f32e7eSjoerg   if (EmitAddrsigSection) {
110106f32e7eSjoerg     auto Frag = new MCDataFragment(AddrsigSection);
110206f32e7eSjoerg     Frag->setLayoutOrder(0);
110306f32e7eSjoerg     raw_svector_ostream OS(Frag->getContents());
110406f32e7eSjoerg     for (const MCSymbol *S : AddrsigSyms) {
110506f32e7eSjoerg       if (!S->isTemporary()) {
110606f32e7eSjoerg         encodeULEB128(S->getIndex(), OS);
110706f32e7eSjoerg         continue;
110806f32e7eSjoerg       }
110906f32e7eSjoerg 
111006f32e7eSjoerg       MCSection *TargetSection = &S->getSection();
111106f32e7eSjoerg       assert(SectionMap.find(TargetSection) != SectionMap.end() &&
111206f32e7eSjoerg              "Section must already have been defined in "
111306f32e7eSjoerg              "executePostLayoutBinding!");
111406f32e7eSjoerg       encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS);
111506f32e7eSjoerg     }
111606f32e7eSjoerg   }
111706f32e7eSjoerg 
1118*da58b97aSjoerg   // Create the contents of the .llvm.call-graph-profile section.
1119*da58b97aSjoerg   if (CGProfileSection) {
1120*da58b97aSjoerg     auto *Frag = new MCDataFragment(CGProfileSection);
1121*da58b97aSjoerg     Frag->setLayoutOrder(0);
1122*da58b97aSjoerg     raw_svector_ostream OS(Frag->getContents());
1123*da58b97aSjoerg     for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) {
1124*da58b97aSjoerg       uint32_t FromIndex = CGPE.From->getSymbol().getIndex();
1125*da58b97aSjoerg       uint32_t ToIndex = CGPE.To->getSymbol().getIndex();
1126*da58b97aSjoerg       support::endian::write(OS, FromIndex, W.Endian);
1127*da58b97aSjoerg       support::endian::write(OS, ToIndex, W.Endian);
1128*da58b97aSjoerg       support::endian::write(OS, CGPE.Count, W.Endian);
1129*da58b97aSjoerg     }
1130*da58b97aSjoerg   }
1131*da58b97aSjoerg 
113206f32e7eSjoerg   assignFileOffsets(Asm, Layout);
113306f32e7eSjoerg 
113406f32e7eSjoerg   // MS LINK expects to be able to use this timestamp to implement their
113506f32e7eSjoerg   // /INCREMENTAL feature.
113606f32e7eSjoerg   if (Asm.isIncrementalLinkerCompatible()) {
113706f32e7eSjoerg     Header.TimeDateStamp = getTime();
113806f32e7eSjoerg   } else {
113906f32e7eSjoerg     // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU.
114006f32e7eSjoerg     Header.TimeDateStamp = 0;
114106f32e7eSjoerg   }
114206f32e7eSjoerg 
114306f32e7eSjoerg   // Write it all to disk...
114406f32e7eSjoerg   WriteFileHeader(Header);
114506f32e7eSjoerg   writeSectionHeaders();
114606f32e7eSjoerg 
114706f32e7eSjoerg   // Write section contents.
114806f32e7eSjoerg   sections::iterator I = Sections.begin();
114906f32e7eSjoerg   sections::iterator IE = Sections.end();
115006f32e7eSjoerg   MCAssembler::iterator J = Asm.begin();
115106f32e7eSjoerg   MCAssembler::iterator JE = Asm.end();
115206f32e7eSjoerg   for (; I != IE && J != JE; ++I, ++J)
115306f32e7eSjoerg     writeSection(Asm, Layout, **I, *J);
115406f32e7eSjoerg 
115506f32e7eSjoerg   assert(W.OS.tell() == Header.PointerToSymbolTable &&
115606f32e7eSjoerg          "Header::PointerToSymbolTable is insane!");
115706f32e7eSjoerg 
115806f32e7eSjoerg   // Write a symbol table.
115906f32e7eSjoerg   for (auto &Symbol : Symbols)
116006f32e7eSjoerg     if (Symbol->getIndex() != -1)
116106f32e7eSjoerg       WriteSymbol(*Symbol);
116206f32e7eSjoerg 
116306f32e7eSjoerg   // Write a string table, which completes the entire COFF file.
116406f32e7eSjoerg   Strings.write(W.OS);
116506f32e7eSjoerg 
116606f32e7eSjoerg   return W.OS.tell() - StartOffset;
116706f32e7eSjoerg }
116806f32e7eSjoerg 
MCWinCOFFObjectTargetWriter(unsigned Machine_)116906f32e7eSjoerg MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)
117006f32e7eSjoerg     : Machine(Machine_) {}
117106f32e7eSjoerg 
117206f32e7eSjoerg // Pin the vtable to this file.
anchor()117306f32e7eSjoerg void MCWinCOFFObjectTargetWriter::anchor() {}
117406f32e7eSjoerg 
117506f32e7eSjoerg //------------------------------------------------------------------------------
117606f32e7eSjoerg // WinCOFFObjectWriter factory function
117706f32e7eSjoerg 
createWinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,raw_pwrite_stream & OS)117806f32e7eSjoerg std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter(
117906f32e7eSjoerg     std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) {
118006f32e7eSjoerg   return std::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
118106f32e7eSjoerg }
1182