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