10b57cec5SDimitry Andric //===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains an implementation of a Win32 COFF object file writer. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 145ffd83dbSDimitry Andric #include "llvm/ADT/DenseSet.h" 150b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 160b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 190b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 200b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCFragment.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h" 270b57cec5SDimitry Andric #include "llvm/MC/MCSection.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCSectionCOFF.h" 290b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCSymbolCOFF.h" 310b57cec5SDimitry Andric #include "llvm/MC/MCValue.h" 320b57cec5SDimitry Andric #include "llvm/MC/MCWinCOFFObjectWriter.h" 330b57cec5SDimitry Andric #include "llvm/MC/StringTableBuilder.h" 348bcb0991SDimitry Andric #include "llvm/Support/CRC.h" 350b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 365ffd83dbSDimitry Andric #include "llvm/Support/EndianStream.h" 370b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 380b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 390b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 400b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 410b57cec5SDimitry Andric #include <algorithm> 420b57cec5SDimitry Andric #include <cassert> 430b57cec5SDimitry Andric #include <cstdint> 440b57cec5SDimitry Andric #include <cstring> 450b57cec5SDimitry Andric #include <ctime> 460b57cec5SDimitry Andric #include <memory> 470b57cec5SDimitry Andric #include <string> 480b57cec5SDimitry Andric #include <vector> 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric using namespace llvm; 510b57cec5SDimitry Andric using llvm::support::endian::write32le; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric #define DEBUG_TYPE "WinCOFFObjectWriter" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric namespace { 560b57cec5SDimitry Andric 574824e7fdSDimitry Andric constexpr int OffsetLabelIntervalBits = 20; 584824e7fdSDimitry Andric 590b57cec5SDimitry Andric using name = SmallString<COFF::NameSize>; 600b57cec5SDimitry Andric 6106c3fb27SDimitry Andric enum AuxiliaryType { ATWeakExternal, ATFile, ATSectionDefinition }; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric struct AuxSymbol { 640b57cec5SDimitry Andric AuxiliaryType AuxType; 650b57cec5SDimitry Andric COFF::Auxiliary Aux; 660b57cec5SDimitry Andric }; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric class COFFSection; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric class COFFSymbol { 710b57cec5SDimitry Andric public: 720b57cec5SDimitry Andric COFF::symbol Data = {}; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric using AuxiliarySymbols = SmallVector<AuxSymbol, 1>; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric name Name; 7706c3fb27SDimitry Andric int Index = 0; 780b57cec5SDimitry Andric AuxiliarySymbols Aux; 790b57cec5SDimitry Andric COFFSymbol *Other = nullptr; 800b57cec5SDimitry Andric COFFSection *Section = nullptr; 810b57cec5SDimitry Andric int Relocations = 0; 820b57cec5SDimitry Andric const MCSymbol *MC = nullptr; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric COFFSymbol(StringRef Name) : Name(Name) {} 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric void set_name_offset(uint32_t Offset); 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric int64_t getIndex() const { return Index; } 890b57cec5SDimitry Andric void setIndex(int Value) { 900b57cec5SDimitry Andric Index = Value; 910b57cec5SDimitry Andric if (MC) 920b57cec5SDimitry Andric MC->setIndex(static_cast<uint32_t>(Value)); 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric }; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric // This class contains staging data for a COFF relocation entry. 970b57cec5SDimitry Andric struct COFFRelocation { 980b57cec5SDimitry Andric COFF::relocation Data; 990b57cec5SDimitry Andric COFFSymbol *Symb = nullptr; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric COFFRelocation() = default; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric static size_t size() { return COFF::RelocationSize; } 1040b57cec5SDimitry Andric }; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric using relocations = std::vector<COFFRelocation>; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric class COFFSection { 1090b57cec5SDimitry Andric public: 1100b57cec5SDimitry Andric COFF::section Header = {}; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric std::string Name; 11306c3fb27SDimitry Andric int Number = 0; 1140b57cec5SDimitry Andric MCSectionCOFF const *MCSection = nullptr; 1150b57cec5SDimitry Andric COFFSymbol *Symbol = nullptr; 1160b57cec5SDimitry Andric relocations Relocations; 1170b57cec5SDimitry Andric 1185ffd83dbSDimitry Andric COFFSection(StringRef Name) : Name(std::string(Name)) {} 1194824e7fdSDimitry Andric 1204824e7fdSDimitry Andric SmallVector<COFFSymbol *, 1> OffsetSymbols; 1210b57cec5SDimitry Andric }; 122*0fca6ea1SDimitry Andric } // namespace 1230b57cec5SDimitry Andric 124*0fca6ea1SDimitry Andric class llvm::WinCOFFWriter { 12506c3fb27SDimitry Andric WinCOFFObjectWriter &OWriter; 1260b57cec5SDimitry Andric support::endian::Writer W; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric using symbols = std::vector<std::unique_ptr<COFFSymbol>>; 1290b57cec5SDimitry Andric using sections = std::vector<std::unique_ptr<COFFSection>>; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>; 1320b57cec5SDimitry Andric using section_map = DenseMap<MCSection const *, COFFSection *>; 1330b57cec5SDimitry Andric 1345ffd83dbSDimitry Andric using symbol_list = DenseSet<COFFSymbol *>; 1355ffd83dbSDimitry Andric 1360b57cec5SDimitry Andric // Root level file contents. 1370b57cec5SDimitry Andric COFF::header Header = {}; 1380b57cec5SDimitry Andric sections Sections; 1390b57cec5SDimitry Andric symbols Symbols; 1400b57cec5SDimitry Andric StringTableBuilder Strings{StringTableBuilder::WinCOFF}; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // Maps used during object file creation. 1430b57cec5SDimitry Andric section_map SectionMap; 1440b57cec5SDimitry Andric symbol_map SymbolMap; 1450b57cec5SDimitry Andric 1465ffd83dbSDimitry Andric symbol_list WeakDefaults; 1475ffd83dbSDimitry Andric 1480b57cec5SDimitry Andric bool UseBigObj; 1494824e7fdSDimitry Andric bool UseOffsetLabels = false; 1500b57cec5SDimitry Andric 15106c3fb27SDimitry Andric public: 15206c3fb27SDimitry Andric enum DwoMode { 15306c3fb27SDimitry Andric AllSections, 15406c3fb27SDimitry Andric NonDwoOnly, 15506c3fb27SDimitry Andric DwoOnly, 15606c3fb27SDimitry Andric } Mode; 1570b57cec5SDimitry Andric 15806c3fb27SDimitry Andric WinCOFFWriter(WinCOFFObjectWriter &OWriter, raw_pwrite_stream &OS, 15906c3fb27SDimitry Andric DwoMode Mode); 1600b57cec5SDimitry Andric 16106c3fb27SDimitry Andric void reset(); 162*0fca6ea1SDimitry Andric void executePostLayoutBinding(MCAssembler &Asm); 163*0fca6ea1SDimitry Andric void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment, 164*0fca6ea1SDimitry Andric const MCFixup &Fixup, MCValue Target, 165*0fca6ea1SDimitry Andric uint64_t &FixedValue); 166*0fca6ea1SDimitry Andric uint64_t writeObject(MCAssembler &Asm); 16706c3fb27SDimitry Andric 16806c3fb27SDimitry Andric private: 1690b57cec5SDimitry Andric COFFSymbol *createSymbol(StringRef Name); 1700b57cec5SDimitry Andric COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol); 1710b57cec5SDimitry Andric COFFSection *createSection(StringRef Name); 1720b57cec5SDimitry Andric 173*0fca6ea1SDimitry Andric void defineSection(const MCAssembler &Asm, MCSectionCOFF const &Sec); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol); 176*0fca6ea1SDimitry Andric void defineSymbol(const MCAssembler &Asm, const MCSymbol &Symbol); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric void SetSymbolName(COFFSymbol &S); 1790b57cec5SDimitry Andric void SetSectionName(COFFSection &S); 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric bool IsPhysicalSection(COFFSection *S); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // Entity writing methods. 1840b57cec5SDimitry Andric void WriteFileHeader(const COFF::header &Header); 1850b57cec5SDimitry Andric void WriteSymbol(const COFFSymbol &S); 1860b57cec5SDimitry Andric void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); 1870b57cec5SDimitry Andric void writeSectionHeaders(); 1880b57cec5SDimitry Andric void WriteRelocation(const COFF::relocation &R); 189*0fca6ea1SDimitry Andric uint32_t writeSectionContents(MCAssembler &Asm, const MCSection &MCSec); 190*0fca6ea1SDimitry Andric void writeSection(MCAssembler &Asm, const COFFSection &Sec); 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric void createFileSymbols(MCAssembler &Asm); 1935ffd83dbSDimitry Andric void setWeakDefaultNames(); 1940b57cec5SDimitry Andric void assignSectionNumbers(); 195*0fca6ea1SDimitry Andric void assignFileOffsets(MCAssembler &Asm); 19606c3fb27SDimitry Andric }; 1970b57cec5SDimitry Andric 198*0fca6ea1SDimitry Andric WinCOFFObjectWriter::WinCOFFObjectWriter( 199*0fca6ea1SDimitry Andric std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) 20006c3fb27SDimitry Andric : TargetObjectWriter(std::move(MOTW)), 20106c3fb27SDimitry Andric ObjWriter(std::make_unique<WinCOFFWriter>(*this, OS, 202*0fca6ea1SDimitry Andric WinCOFFWriter::AllSections)) {} 203*0fca6ea1SDimitry Andric WinCOFFObjectWriter::WinCOFFObjectWriter( 204*0fca6ea1SDimitry Andric std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS, 205*0fca6ea1SDimitry Andric raw_pwrite_stream &DwoOS) 20606c3fb27SDimitry Andric : TargetObjectWriter(std::move(MOTW)), 20706c3fb27SDimitry Andric ObjWriter(std::make_unique<WinCOFFWriter>(*this, OS, 20806c3fb27SDimitry Andric WinCOFFWriter::NonDwoOnly)), 20906c3fb27SDimitry Andric DwoWriter(std::make_unique<WinCOFFWriter>(*this, DwoOS, 21006c3fb27SDimitry Andric WinCOFFWriter::DwoOnly)) {} 21106c3fb27SDimitry Andric 21206c3fb27SDimitry Andric static bool isDwoSection(const MCSection &Sec) { 2135f757f3fSDimitry Andric return Sec.getName().ends_with(".dwo"); 21406c3fb27SDimitry Andric } 21506c3fb27SDimitry Andric 2160b57cec5SDimitry Andric //------------------------------------------------------------------------------ 2170b57cec5SDimitry Andric // Symbol class implementation 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric // In the case that the name does not fit within 8 bytes, the offset 2200b57cec5SDimitry Andric // into the string table is stored in the last 4 bytes instead, leaving 2210b57cec5SDimitry Andric // the first 4 bytes as 0. 2220b57cec5SDimitry Andric void COFFSymbol::set_name_offset(uint32_t Offset) { 2230b57cec5SDimitry Andric write32le(Data.Name + 0, 0); 2240b57cec5SDimitry Andric write32le(Data.Name + 4, Offset); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric //------------------------------------------------------------------------------ 22806c3fb27SDimitry Andric // WinCOFFWriter class implementation 2290b57cec5SDimitry Andric 23006c3fb27SDimitry Andric WinCOFFWriter::WinCOFFWriter(WinCOFFObjectWriter &OWriter, 23106c3fb27SDimitry Andric raw_pwrite_stream &OS, DwoMode Mode) 2325f757f3fSDimitry Andric : OWriter(OWriter), W(OS, llvm::endianness::little), Mode(Mode) { 23306c3fb27SDimitry Andric Header.Machine = OWriter.TargetObjectWriter->getMachine(); 2344824e7fdSDimitry Andric // Some relocations on ARM64 (the 21 bit ADRP relocations) have a slightly 2354824e7fdSDimitry Andric // limited range for the immediate offset (+/- 1 MB); create extra offset 2364824e7fdSDimitry Andric // label symbols with regular intervals to allow referencing a 2374824e7fdSDimitry Andric // non-temporary symbol that is close enough. 238*0fca6ea1SDimitry Andric UseOffsetLabels = COFF::isAnyArm64(Header.Machine); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 24106c3fb27SDimitry Andric COFFSymbol *WinCOFFWriter::createSymbol(StringRef Name) { 2428bcb0991SDimitry Andric Symbols.push_back(std::make_unique<COFFSymbol>(Name)); 2430b57cec5SDimitry Andric return Symbols.back().get(); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 24606c3fb27SDimitry Andric COFFSymbol *WinCOFFWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) { 2470b57cec5SDimitry Andric COFFSymbol *&Ret = SymbolMap[Symbol]; 2480b57cec5SDimitry Andric if (!Ret) 2490b57cec5SDimitry Andric Ret = createSymbol(Symbol->getName()); 2500b57cec5SDimitry Andric return Ret; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 25306c3fb27SDimitry Andric COFFSection *WinCOFFWriter::createSection(StringRef Name) { 2548bcb0991SDimitry Andric Sections.emplace_back(std::make_unique<COFFSection>(Name)); 2550b57cec5SDimitry Andric return Sections.back().get(); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric static uint32_t getAlignment(const MCSectionCOFF &Sec) { 259bdd1243dSDimitry Andric switch (Sec.getAlign().value()) { 2600b57cec5SDimitry Andric case 1: 2610b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_1BYTES; 2620b57cec5SDimitry Andric case 2: 2630b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_2BYTES; 2640b57cec5SDimitry Andric case 4: 2650b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_4BYTES; 2660b57cec5SDimitry Andric case 8: 2670b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_8BYTES; 2680b57cec5SDimitry Andric case 16: 2690b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_16BYTES; 2700b57cec5SDimitry Andric case 32: 2710b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_32BYTES; 2720b57cec5SDimitry Andric case 64: 2730b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_64BYTES; 2740b57cec5SDimitry Andric case 128: 2750b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_128BYTES; 2760b57cec5SDimitry Andric case 256: 2770b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_256BYTES; 2780b57cec5SDimitry Andric case 512: 2790b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_512BYTES; 2800b57cec5SDimitry Andric case 1024: 2810b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_1024BYTES; 2820b57cec5SDimitry Andric case 2048: 2830b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_2048BYTES; 2840b57cec5SDimitry Andric case 4096: 2850b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_4096BYTES; 2860b57cec5SDimitry Andric case 8192: 2870b57cec5SDimitry Andric return COFF::IMAGE_SCN_ALIGN_8192BYTES; 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric llvm_unreachable("unsupported section alignment"); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric /// This function takes a section data object from the assembler 2930b57cec5SDimitry Andric /// and creates the associated COFF section staging object. 294*0fca6ea1SDimitry Andric void WinCOFFWriter::defineSection(const MCAssembler &Asm, 295*0fca6ea1SDimitry Andric const MCSectionCOFF &MCSec) { 2965ffd83dbSDimitry Andric COFFSection *Section = createSection(MCSec.getName()); 2975ffd83dbSDimitry Andric COFFSymbol *Symbol = createSymbol(MCSec.getName()); 2980b57cec5SDimitry Andric Section->Symbol = Symbol; 299*0fca6ea1SDimitry Andric SymbolMap[MCSec.getBeginSymbol()] = Symbol; 3000b57cec5SDimitry Andric Symbol->Section = Section; 3010b57cec5SDimitry Andric Symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // Create a COMDAT symbol if needed. 3040b57cec5SDimitry Andric if (MCSec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { 3050b57cec5SDimitry Andric if (const MCSymbol *S = MCSec.getCOMDATSymbol()) { 3060b57cec5SDimitry Andric COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S); 3070b57cec5SDimitry Andric if (COMDATSymbol->Section) 3080b57cec5SDimitry Andric report_fatal_error("two sections have the same comdat"); 3090b57cec5SDimitry Andric COMDATSymbol->Section = Section; 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // In this case the auxiliary symbol is a Section Definition. 3140b57cec5SDimitry Andric Symbol->Aux.resize(1); 3150b57cec5SDimitry Andric Symbol->Aux[0] = {}; 3160b57cec5SDimitry Andric Symbol->Aux[0].AuxType = ATSectionDefinition; 3170b57cec5SDimitry Andric Symbol->Aux[0].Aux.SectionDefinition.Selection = MCSec.getSelection(); 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric // Set section alignment. 3200b57cec5SDimitry Andric Section->Header.Characteristics = MCSec.getCharacteristics(); 3210b57cec5SDimitry Andric Section->Header.Characteristics |= getAlignment(MCSec); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // Bind internal COFF section to MC section. 3240b57cec5SDimitry Andric Section->MCSection = &MCSec; 3250b57cec5SDimitry Andric SectionMap[&MCSec] = Section; 3264824e7fdSDimitry Andric 327*0fca6ea1SDimitry Andric if (UseOffsetLabels && !MCSec.empty()) { 3284824e7fdSDimitry Andric const uint32_t Interval = 1 << OffsetLabelIntervalBits; 3294824e7fdSDimitry Andric uint32_t N = 1; 330*0fca6ea1SDimitry Andric for (uint32_t Off = Interval, E = Asm.getSectionAddressSize(MCSec); Off < E; 331*0fca6ea1SDimitry Andric Off += Interval) { 3324824e7fdSDimitry Andric auto Name = ("$L" + MCSec.getName() + "_" + Twine(N++)).str(); 3334824e7fdSDimitry Andric COFFSymbol *Label = createSymbol(Name); 3344824e7fdSDimitry Andric Label->Section = Section; 3354824e7fdSDimitry Andric Label->Data.StorageClass = COFF::IMAGE_SYM_CLASS_LABEL; 3364824e7fdSDimitry Andric Label->Data.Value = Off; 3374824e7fdSDimitry Andric Section->OffsetSymbols.push_back(Label); 3384824e7fdSDimitry Andric } 3394824e7fdSDimitry Andric } 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 342*0fca6ea1SDimitry Andric static uint64_t getSymbolValue(const MCSymbol &Symbol, const MCAssembler &Asm) { 3430b57cec5SDimitry Andric if (Symbol.isCommon() && Symbol.isExternal()) 3440b57cec5SDimitry Andric return Symbol.getCommonSize(); 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric uint64_t Res; 347*0fca6ea1SDimitry Andric if (!Asm.getSymbolOffset(Symbol, Res)) 3480b57cec5SDimitry Andric return 0; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric return Res; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 35306c3fb27SDimitry Andric COFFSymbol *WinCOFFWriter::getLinkedSymbol(const MCSymbol &Symbol) { 3540b57cec5SDimitry Andric if (!Symbol.isVariable()) 3550b57cec5SDimitry Andric return nullptr; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric const MCSymbolRefExpr *SymRef = 3580b57cec5SDimitry Andric dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue()); 3590b57cec5SDimitry Andric if (!SymRef) 3600b57cec5SDimitry Andric return nullptr; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric const MCSymbol &Aliasee = SymRef->getSymbol(); 363e8d8bef9SDimitry Andric if (Aliasee.isUndefined() || Aliasee.isExternal()) 3640b57cec5SDimitry Andric return GetOrCreateCOFFSymbol(&Aliasee); 365e8d8bef9SDimitry Andric else 366e8d8bef9SDimitry Andric return nullptr; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric /// This function takes a symbol data object from the assembler 3700b57cec5SDimitry Andric /// and creates the associated COFF symbol staging object. 371*0fca6ea1SDimitry Andric void WinCOFFWriter::defineSymbol(const MCAssembler &Asm, 372*0fca6ea1SDimitry Andric const MCSymbol &MCSym) { 373*0fca6ea1SDimitry Andric const MCSymbol *Base = Asm.getBaseSymbol(MCSym); 3740b57cec5SDimitry Andric COFFSection *Sec = nullptr; 375*0fca6ea1SDimitry Andric MCSectionCOFF *MCSec = nullptr; 3760b57cec5SDimitry Andric if (Base && Base->getFragment()) { 377*0fca6ea1SDimitry Andric MCSec = cast<MCSectionCOFF>(Base->getFragment()->getParent()); 378*0fca6ea1SDimitry Andric Sec = SectionMap[MCSec]; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 381*0fca6ea1SDimitry Andric if (Mode == NonDwoOnly && MCSec && isDwoSection(*MCSec)) 382*0fca6ea1SDimitry Andric return; 383*0fca6ea1SDimitry Andric 384*0fca6ea1SDimitry Andric COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym); 3850b57cec5SDimitry Andric COFFSymbol *Local = nullptr; 38606c3fb27SDimitry Andric if (cast<MCSymbolCOFF>(MCSym).getWeakExternalCharacteristics()) { 3870b57cec5SDimitry Andric Sym->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; 388979e22ffSDimitry Andric Sym->Section = nullptr; 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric COFFSymbol *WeakDefault = getLinkedSymbol(MCSym); 3910b57cec5SDimitry Andric if (!WeakDefault) { 3920b57cec5SDimitry Andric std::string WeakName = (".weak." + MCSym.getName() + ".default").str(); 3930b57cec5SDimitry Andric WeakDefault = createSymbol(WeakName); 3940b57cec5SDimitry Andric if (!Sec) 3950b57cec5SDimitry Andric WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; 3960b57cec5SDimitry Andric else 3970b57cec5SDimitry Andric WeakDefault->Section = Sec; 3985ffd83dbSDimitry Andric WeakDefaults.insert(WeakDefault); 3990b57cec5SDimitry Andric Local = WeakDefault; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric Sym->Other = WeakDefault; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // Setup the Weak External auxiliary symbol. 4050b57cec5SDimitry Andric Sym->Aux.resize(1); 4060b57cec5SDimitry Andric memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0])); 4070b57cec5SDimitry Andric Sym->Aux[0].AuxType = ATWeakExternal; 40806c3fb27SDimitry Andric Sym->Aux[0].Aux.WeakExternal.TagIndex = 0; // Filled in later 4090b57cec5SDimitry Andric Sym->Aux[0].Aux.WeakExternal.Characteristics = 41006c3fb27SDimitry Andric cast<MCSymbolCOFF>(MCSym).getWeakExternalCharacteristics(); 4110b57cec5SDimitry Andric } else { 4120b57cec5SDimitry Andric if (!Base) 4130b57cec5SDimitry Andric Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; 4140b57cec5SDimitry Andric else 4150b57cec5SDimitry Andric Sym->Section = Sec; 4160b57cec5SDimitry Andric Local = Sym; 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric if (Local) { 420*0fca6ea1SDimitry Andric Local->Data.Value = getSymbolValue(MCSym, Asm); 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(MCSym); 4230b57cec5SDimitry Andric Local->Data.Type = SymbolCOFF.getType(); 4240b57cec5SDimitry Andric Local->Data.StorageClass = SymbolCOFF.getClass(); 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric // If no storage class was specified in the streamer, define it here. 4270b57cec5SDimitry Andric if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) { 42806c3fb27SDimitry Andric bool IsExternal = 42906c3fb27SDimitry Andric MCSym.isExternal() || (!MCSym.getFragment() && !MCSym.isVariable()); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL 4320b57cec5SDimitry Andric : COFF::IMAGE_SYM_CLASS_STATIC; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric Sym->MC = &MCSym; 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 43906c3fb27SDimitry Andric void WinCOFFWriter::SetSectionName(COFFSection &S) { 4400b57cec5SDimitry Andric if (S.Name.size() <= COFF::NameSize) { 4410b57cec5SDimitry Andric std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); 4420b57cec5SDimitry Andric return; 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric uint64_t StringTableEntry = Strings.getOffset(S.Name); 446d781ede6SDimitry Andric if (!COFF::encodeSectionName(S.Header.Name, StringTableEntry)) 4470b57cec5SDimitry Andric report_fatal_error("COFF string table is greater than 64 GB."); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 45006c3fb27SDimitry Andric void WinCOFFWriter::SetSymbolName(COFFSymbol &S) { 4510b57cec5SDimitry Andric if (S.Name.size() > COFF::NameSize) 4520b57cec5SDimitry Andric S.set_name_offset(Strings.getOffset(S.Name)); 4530b57cec5SDimitry Andric else 4540b57cec5SDimitry Andric std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size()); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 45706c3fb27SDimitry Andric bool WinCOFFWriter::IsPhysicalSection(COFFSection *S) { 4580b57cec5SDimitry Andric return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 4590b57cec5SDimitry Andric 0; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric //------------------------------------------------------------------------------ 4630b57cec5SDimitry Andric // entity writing methods 4640b57cec5SDimitry Andric 46506c3fb27SDimitry Andric void WinCOFFWriter::WriteFileHeader(const COFF::header &Header) { 4660b57cec5SDimitry Andric if (UseBigObj) { 4670b57cec5SDimitry Andric W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN); 4680b57cec5SDimitry Andric W.write<uint16_t>(0xFFFF); 4690b57cec5SDimitry Andric W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion); 4700b57cec5SDimitry Andric W.write<uint16_t>(Header.Machine); 4710b57cec5SDimitry Andric W.write<uint32_t>(Header.TimeDateStamp); 4720b57cec5SDimitry Andric W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)); 4730b57cec5SDimitry Andric W.write<uint32_t>(0); 4740b57cec5SDimitry Andric W.write<uint32_t>(0); 4750b57cec5SDimitry Andric W.write<uint32_t>(0); 4760b57cec5SDimitry Andric W.write<uint32_t>(0); 4770b57cec5SDimitry Andric W.write<uint32_t>(Header.NumberOfSections); 4780b57cec5SDimitry Andric W.write<uint32_t>(Header.PointerToSymbolTable); 4790b57cec5SDimitry Andric W.write<uint32_t>(Header.NumberOfSymbols); 4800b57cec5SDimitry Andric } else { 4810b57cec5SDimitry Andric W.write<uint16_t>(Header.Machine); 4820b57cec5SDimitry Andric W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections)); 4830b57cec5SDimitry Andric W.write<uint32_t>(Header.TimeDateStamp); 4840b57cec5SDimitry Andric W.write<uint32_t>(Header.PointerToSymbolTable); 4850b57cec5SDimitry Andric W.write<uint32_t>(Header.NumberOfSymbols); 4860b57cec5SDimitry Andric W.write<uint16_t>(Header.SizeOfOptionalHeader); 4870b57cec5SDimitry Andric W.write<uint16_t>(Header.Characteristics); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 49106c3fb27SDimitry Andric void WinCOFFWriter::WriteSymbol(const COFFSymbol &S) { 4920b57cec5SDimitry Andric W.OS.write(S.Data.Name, COFF::NameSize); 4930b57cec5SDimitry Andric W.write<uint32_t>(S.Data.Value); 4940b57cec5SDimitry Andric if (UseBigObj) 4950b57cec5SDimitry Andric W.write<uint32_t>(S.Data.SectionNumber); 4960b57cec5SDimitry Andric else 4970b57cec5SDimitry Andric W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber)); 4980b57cec5SDimitry Andric W.write<uint16_t>(S.Data.Type); 4990b57cec5SDimitry Andric W.OS << char(S.Data.StorageClass); 5000b57cec5SDimitry Andric W.OS << char(S.Data.NumberOfAuxSymbols); 5010b57cec5SDimitry Andric WriteAuxiliarySymbols(S.Aux); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric 50406c3fb27SDimitry Andric void WinCOFFWriter::WriteAuxiliarySymbols( 5050b57cec5SDimitry Andric const COFFSymbol::AuxiliarySymbols &S) { 5060b57cec5SDimitry Andric for (const AuxSymbol &i : S) { 5070b57cec5SDimitry Andric switch (i.AuxType) { 5080b57cec5SDimitry Andric case ATWeakExternal: 5090b57cec5SDimitry Andric W.write<uint32_t>(i.Aux.WeakExternal.TagIndex); 5100b57cec5SDimitry Andric W.write<uint32_t>(i.Aux.WeakExternal.Characteristics); 5110b57cec5SDimitry Andric W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused)); 5120b57cec5SDimitry Andric if (UseBigObj) 5130b57cec5SDimitry Andric W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size); 5140b57cec5SDimitry Andric break; 5150b57cec5SDimitry Andric case ATFile: 5160b57cec5SDimitry Andric W.OS.write(reinterpret_cast<const char *>(&i.Aux), 5170b57cec5SDimitry Andric UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size); 5180b57cec5SDimitry Andric break; 5190b57cec5SDimitry Andric case ATSectionDefinition: 5200b57cec5SDimitry Andric W.write<uint32_t>(i.Aux.SectionDefinition.Length); 5210b57cec5SDimitry Andric W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations); 5220b57cec5SDimitry Andric W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers); 5230b57cec5SDimitry Andric W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum); 5240b57cec5SDimitry Andric W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number)); 5250b57cec5SDimitry Andric W.OS << char(i.Aux.SectionDefinition.Selection); 5260b57cec5SDimitry Andric W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused)); 52706c3fb27SDimitry Andric W.write<uint16_t>( 52806c3fb27SDimitry Andric static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16)); 5290b57cec5SDimitry Andric if (UseBigObj) 5300b57cec5SDimitry Andric W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size); 5310b57cec5SDimitry Andric break; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric // Write the section header. 53706c3fb27SDimitry Andric void WinCOFFWriter::writeSectionHeaders() { 5380b57cec5SDimitry Andric // Section numbers must be monotonically increasing in the section 5390b57cec5SDimitry Andric // header, but our Sections array is not sorted by section number, 5400b57cec5SDimitry Andric // so make a copy of Sections and sort it. 5410b57cec5SDimitry Andric std::vector<COFFSection *> Arr; 5420b57cec5SDimitry Andric for (auto &Section : Sections) 5430b57cec5SDimitry Andric Arr.push_back(Section.get()); 5440b57cec5SDimitry Andric llvm::sort(Arr, [](const COFFSection *A, const COFFSection *B) { 5450b57cec5SDimitry Andric return A->Number < B->Number; 5460b57cec5SDimitry Andric }); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric for (auto &Section : Arr) { 5490b57cec5SDimitry Andric if (Section->Number == -1) 5500b57cec5SDimitry Andric continue; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric COFF::section &S = Section->Header; 5530b57cec5SDimitry Andric if (Section->Relocations.size() >= 0xffff) 5540b57cec5SDimitry Andric S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; 5550b57cec5SDimitry Andric W.OS.write(S.Name, COFF::NameSize); 5560b57cec5SDimitry Andric W.write<uint32_t>(S.VirtualSize); 5570b57cec5SDimitry Andric W.write<uint32_t>(S.VirtualAddress); 5580b57cec5SDimitry Andric W.write<uint32_t>(S.SizeOfRawData); 5590b57cec5SDimitry Andric W.write<uint32_t>(S.PointerToRawData); 5600b57cec5SDimitry Andric W.write<uint32_t>(S.PointerToRelocations); 5610b57cec5SDimitry Andric W.write<uint32_t>(S.PointerToLineNumbers); 5620b57cec5SDimitry Andric W.write<uint16_t>(S.NumberOfRelocations); 5630b57cec5SDimitry Andric W.write<uint16_t>(S.NumberOfLineNumbers); 5640b57cec5SDimitry Andric W.write<uint32_t>(S.Characteristics); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 56806c3fb27SDimitry Andric void WinCOFFWriter::WriteRelocation(const COFF::relocation &R) { 5690b57cec5SDimitry Andric W.write<uint32_t>(R.VirtualAddress); 5700b57cec5SDimitry Andric W.write<uint32_t>(R.SymbolTableIndex); 5710b57cec5SDimitry Andric W.write<uint16_t>(R.Type); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric // Write MCSec's contents. What this function does is essentially 575*0fca6ea1SDimitry Andric // "Asm.writeSectionData(&MCSec)", but it's a bit complicated 5760b57cec5SDimitry Andric // because it needs to compute a CRC. 57706c3fb27SDimitry Andric uint32_t WinCOFFWriter::writeSectionContents(MCAssembler &Asm, 5780b57cec5SDimitry Andric const MCSection &MCSec) { 5790b57cec5SDimitry Andric // Save the contents of the section to a temporary buffer, we need this 5800b57cec5SDimitry Andric // to CRC the data before we dump it into the object file. 5810b57cec5SDimitry Andric SmallVector<char, 128> Buf; 5820b57cec5SDimitry Andric raw_svector_ostream VecOS(Buf); 583*0fca6ea1SDimitry Andric Asm.writeSectionData(VecOS, &MCSec); 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric // Write the section contents to the object file. 5860b57cec5SDimitry Andric W.OS << Buf; 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric // Calculate our CRC with an initial value of '0', this is not how 5890b57cec5SDimitry Andric // JamCRC is specified but it aligns with the expected output. 5900b57cec5SDimitry Andric JamCRC JC(/*Init=*/0); 591bdd1243dSDimitry Andric JC.update(ArrayRef(reinterpret_cast<uint8_t *>(Buf.data()), Buf.size())); 5920b57cec5SDimitry Andric return JC.getCRC(); 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 595*0fca6ea1SDimitry Andric void WinCOFFWriter::writeSection(MCAssembler &Asm, const COFFSection &Sec) { 5960b57cec5SDimitry Andric if (Sec.Number == -1) 5970b57cec5SDimitry Andric return; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric // Write the section contents. 6000b57cec5SDimitry Andric if (Sec.Header.PointerToRawData != 0) { 6010b57cec5SDimitry Andric assert(W.OS.tell() == Sec.Header.PointerToRawData && 6020b57cec5SDimitry Andric "Section::PointerToRawData is insane!"); 6030b57cec5SDimitry Andric 604*0fca6ea1SDimitry Andric uint32_t CRC = writeSectionContents(Asm, *Sec.MCSection); 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric // Update the section definition auxiliary symbol to record the CRC. 60706c3fb27SDimitry Andric COFFSymbol::AuxiliarySymbols &AuxSyms = Sec.Symbol->Aux; 6080b57cec5SDimitry Andric assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition); 6090b57cec5SDimitry Andric AuxSymbol &SecDef = AuxSyms[0]; 6100b57cec5SDimitry Andric SecDef.Aux.SectionDefinition.CheckSum = CRC; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric // Write relocations for this section. 6140b57cec5SDimitry Andric if (Sec.Relocations.empty()) { 6150b57cec5SDimitry Andric assert(Sec.Header.PointerToRelocations == 0 && 6160b57cec5SDimitry Andric "Section::PointerToRelocations is insane!"); 6170b57cec5SDimitry Andric return; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric assert(W.OS.tell() == Sec.Header.PointerToRelocations && 6210b57cec5SDimitry Andric "Section::PointerToRelocations is insane!"); 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric if (Sec.Relocations.size() >= 0xffff) { 6240b57cec5SDimitry Andric // In case of overflow, write actual relocation count as first 6250b57cec5SDimitry Andric // relocation. Including the synthetic reloc itself (+ 1). 6260b57cec5SDimitry Andric COFF::relocation R; 6270b57cec5SDimitry Andric R.VirtualAddress = Sec.Relocations.size() + 1; 6280b57cec5SDimitry Andric R.SymbolTableIndex = 0; 6290b57cec5SDimitry Andric R.Type = 0; 6300b57cec5SDimitry Andric WriteRelocation(R); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric for (const auto &Relocation : Sec.Relocations) 6340b57cec5SDimitry Andric WriteRelocation(Relocation.Data); 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric // Create .file symbols. 63806c3fb27SDimitry Andric void WinCOFFWriter::createFileSymbols(MCAssembler &Asm) { 639*0fca6ea1SDimitry Andric for (const std::pair<std::string, size_t> &It : OWriter.getFileNames()) { 6400b57cec5SDimitry Andric // round up to calculate the number of auxiliary symbols required 641fe6060f1SDimitry Andric const std::string &Name = It.first; 6420b57cec5SDimitry Andric unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size; 6430b57cec5SDimitry Andric unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize; 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric COFFSymbol *File = createSymbol(".file"); 6460b57cec5SDimitry Andric File->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; 6470b57cec5SDimitry Andric File->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; 6480b57cec5SDimitry Andric File->Aux.resize(Count); 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric unsigned Offset = 0; 6510b57cec5SDimitry Andric unsigned Length = Name.size(); 6520b57cec5SDimitry Andric for (auto &Aux : File->Aux) { 6530b57cec5SDimitry Andric Aux.AuxType = ATFile; 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric if (Length > SymbolSize) { 6560b57cec5SDimitry Andric memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize); 6570b57cec5SDimitry Andric Length = Length - SymbolSize; 6580b57cec5SDimitry Andric } else { 6590b57cec5SDimitry Andric memcpy(&Aux.Aux, Name.c_str() + Offset, Length); 6600b57cec5SDimitry Andric memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length); 6610b57cec5SDimitry Andric break; 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric Offset += SymbolSize; 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 66906c3fb27SDimitry Andric void WinCOFFWriter::setWeakDefaultNames() { 6705ffd83dbSDimitry Andric if (WeakDefaults.empty()) 6715ffd83dbSDimitry Andric return; 6725ffd83dbSDimitry Andric 6735ffd83dbSDimitry Andric // If multiple object files use a weak symbol (either with a regular 6745ffd83dbSDimitry Andric // defined default, or an absolute zero symbol as default), the defaults 6755ffd83dbSDimitry Andric // cause duplicate definitions unless their names are made unique. Look 6765ffd83dbSDimitry Andric // for a defined extern symbol, that isn't comdat - that should be unique 6775ffd83dbSDimitry Andric // unless there are other duplicate definitions. And if none is found, 6785ffd83dbSDimitry Andric // allow picking a comdat symbol, as that's still better than nothing. 6795ffd83dbSDimitry Andric 6805ffd83dbSDimitry Andric COFFSymbol *Unique = nullptr; 6815ffd83dbSDimitry Andric for (bool AllowComdat : {false, true}) { 6825ffd83dbSDimitry Andric for (auto &Sym : Symbols) { 6835ffd83dbSDimitry Andric // Don't include the names of the defaults themselves 6845ffd83dbSDimitry Andric if (WeakDefaults.count(Sym.get())) 6855ffd83dbSDimitry Andric continue; 6865ffd83dbSDimitry Andric // Only consider external symbols 6875ffd83dbSDimitry Andric if (Sym->Data.StorageClass != COFF::IMAGE_SYM_CLASS_EXTERNAL) 6885ffd83dbSDimitry Andric continue; 6895ffd83dbSDimitry Andric // Only consider symbols defined in a section or that are absolute 6905ffd83dbSDimitry Andric if (!Sym->Section && Sym->Data.SectionNumber != COFF::IMAGE_SYM_ABSOLUTE) 6915ffd83dbSDimitry Andric continue; 6925ffd83dbSDimitry Andric if (!AllowComdat && Sym->Section && 6935ffd83dbSDimitry Andric Sym->Section->Header.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) 6945ffd83dbSDimitry Andric continue; 6955ffd83dbSDimitry Andric Unique = Sym.get(); 6965ffd83dbSDimitry Andric break; 6975ffd83dbSDimitry Andric } 6985ffd83dbSDimitry Andric if (Unique) 6995ffd83dbSDimitry Andric break; 7005ffd83dbSDimitry Andric } 7015ffd83dbSDimitry Andric // If we didn't find any unique symbol to use for the names, just skip this. 7025ffd83dbSDimitry Andric if (!Unique) 7035ffd83dbSDimitry Andric return; 7045ffd83dbSDimitry Andric for (auto *Sym : WeakDefaults) { 7055ffd83dbSDimitry Andric Sym->Name.append("."); 7065ffd83dbSDimitry Andric Sym->Name.append(Unique->Name); 7075ffd83dbSDimitry Andric } 7085ffd83dbSDimitry Andric } 7095ffd83dbSDimitry Andric 7100b57cec5SDimitry Andric static bool isAssociative(const COFFSection &Section) { 7110b57cec5SDimitry Andric return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection == 7120b57cec5SDimitry Andric COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 71506c3fb27SDimitry Andric void WinCOFFWriter::assignSectionNumbers() { 7160b57cec5SDimitry Andric size_t I = 1; 7170b57cec5SDimitry Andric auto Assign = [&](COFFSection &Section) { 7180b57cec5SDimitry Andric Section.Number = I; 7190b57cec5SDimitry Andric Section.Symbol->Data.SectionNumber = I; 7200b57cec5SDimitry Andric Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I; 7210b57cec5SDimitry Andric ++I; 7220b57cec5SDimitry Andric }; 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric // Although it is not explicitly requested by the Microsoft COFF spec, 7250b57cec5SDimitry Andric // we should avoid emitting forward associative section references, 7260b57cec5SDimitry Andric // because MSVC link.exe as of 2017 cannot handle that. 7270b57cec5SDimitry Andric for (const std::unique_ptr<COFFSection> &Section : Sections) 7280b57cec5SDimitry Andric if (!isAssociative(*Section)) 7290b57cec5SDimitry Andric Assign(*Section); 7300b57cec5SDimitry Andric for (const std::unique_ptr<COFFSection> &Section : Sections) 7310b57cec5SDimitry Andric if (isAssociative(*Section)) 7320b57cec5SDimitry Andric Assign(*Section); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric // Assign file offsets to COFF object file structures. 736*0fca6ea1SDimitry Andric void WinCOFFWriter::assignFileOffsets(MCAssembler &Asm) { 7370b57cec5SDimitry Andric unsigned Offset = W.OS.tell(); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size; 7400b57cec5SDimitry Andric Offset += COFF::SectionSize * Header.NumberOfSections; 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric for (const auto &Section : Asm) { 7430b57cec5SDimitry Andric COFFSection *Sec = SectionMap[&Section]; 7440b57cec5SDimitry Andric 74581ad6265SDimitry Andric if (!Sec || Sec->Number == -1) 7460b57cec5SDimitry Andric continue; 7470b57cec5SDimitry Andric 748*0fca6ea1SDimitry Andric Sec->Header.SizeOfRawData = Asm.getSectionAddressSize(Section); 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric if (IsPhysicalSection(Sec)) { 7510b57cec5SDimitry Andric Sec->Header.PointerToRawData = Offset; 7520b57cec5SDimitry Andric Offset += Sec->Header.SizeOfRawData; 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric if (!Sec->Relocations.empty()) { 7560b57cec5SDimitry Andric bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff; 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric if (RelocationsOverflow) { 7590b57cec5SDimitry Andric // Signal overflow by setting NumberOfRelocations to max value. Actual 7600b57cec5SDimitry Andric // size is found in reloc #0. Microsoft tools understand this. 7610b57cec5SDimitry Andric Sec->Header.NumberOfRelocations = 0xffff; 7620b57cec5SDimitry Andric } else { 7630b57cec5SDimitry Andric Sec->Header.NumberOfRelocations = Sec->Relocations.size(); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric Sec->Header.PointerToRelocations = Offset; 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric if (RelocationsOverflow) { 7680b57cec5SDimitry Andric // Reloc #0 will contain actual count, so make room for it. 7690b57cec5SDimitry Andric Offset += COFF::RelocationSize; 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric Offset += COFF::RelocationSize * Sec->Relocations.size(); 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric for (auto &Relocation : Sec->Relocations) { 7750b57cec5SDimitry Andric assert(Relocation.Symb->getIndex() != -1); 7760b57cec5SDimitry Andric Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex(); 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric assert(Sec->Symbol->Aux.size() == 1 && 7810b57cec5SDimitry Andric "Section's symbol must have one aux!"); 7820b57cec5SDimitry Andric AuxSymbol &Aux = Sec->Symbol->Aux[0]; 7830b57cec5SDimitry Andric assert(Aux.AuxType == ATSectionDefinition && 7840b57cec5SDimitry Andric "Section's symbol's aux symbol must be a Section Definition!"); 7850b57cec5SDimitry Andric Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; 7860b57cec5SDimitry Andric Aux.Aux.SectionDefinition.NumberOfRelocations = 7870b57cec5SDimitry Andric Sec->Header.NumberOfRelocations; 7880b57cec5SDimitry Andric Aux.Aux.SectionDefinition.NumberOfLinenumbers = 7890b57cec5SDimitry Andric Sec->Header.NumberOfLineNumbers; 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric Header.PointerToSymbolTable = Offset; 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 79506c3fb27SDimitry Andric void WinCOFFWriter::reset() { 79606c3fb27SDimitry Andric memset(&Header, 0, sizeof(Header)); 79706c3fb27SDimitry Andric Header.Machine = OWriter.TargetObjectWriter->getMachine(); 79806c3fb27SDimitry Andric Sections.clear(); 79906c3fb27SDimitry Andric Symbols.clear(); 80006c3fb27SDimitry Andric Strings.clear(); 80106c3fb27SDimitry Andric SectionMap.clear(); 80206c3fb27SDimitry Andric SymbolMap.clear(); 80306c3fb27SDimitry Andric WeakDefaults.clear(); 80406c3fb27SDimitry Andric } 80506c3fb27SDimitry Andric 806*0fca6ea1SDimitry Andric void WinCOFFWriter::executePostLayoutBinding(MCAssembler &Asm) { 80706c3fb27SDimitry Andric // "Define" each section & symbol. This creates section & symbol 80806c3fb27SDimitry Andric // entries in the staging area. 80906c3fb27SDimitry Andric for (const auto &Section : Asm) { 81006c3fb27SDimitry Andric if ((Mode == NonDwoOnly && isDwoSection(Section)) || 81106c3fb27SDimitry Andric (Mode == DwoOnly && !isDwoSection(Section))) 81206c3fb27SDimitry Andric continue; 813*0fca6ea1SDimitry Andric defineSection(Asm, static_cast<const MCSectionCOFF &>(Section)); 81406c3fb27SDimitry Andric } 81506c3fb27SDimitry Andric 81606c3fb27SDimitry Andric if (Mode != DwoOnly) 81706c3fb27SDimitry Andric for (const MCSymbol &Symbol : Asm.symbols()) 8185f757f3fSDimitry Andric // Define non-temporary or temporary static (private-linkage) symbols 8195f757f3fSDimitry Andric if (!Symbol.isTemporary() || 8205f757f3fSDimitry Andric cast<MCSymbolCOFF>(Symbol).getClass() == COFF::IMAGE_SYM_CLASS_STATIC) 821*0fca6ea1SDimitry Andric defineSymbol(Asm, Symbol); 82206c3fb27SDimitry Andric } 82306c3fb27SDimitry Andric 82406c3fb27SDimitry Andric void WinCOFFWriter::recordRelocation(MCAssembler &Asm, 82506c3fb27SDimitry Andric const MCFragment *Fragment, 82606c3fb27SDimitry Andric const MCFixup &Fixup, MCValue Target, 82706c3fb27SDimitry Andric uint64_t &FixedValue) { 82806c3fb27SDimitry Andric assert(Target.getSymA() && "Relocation must reference a symbol!"); 82906c3fb27SDimitry Andric 83006c3fb27SDimitry Andric const MCSymbol &A = Target.getSymA()->getSymbol(); 83106c3fb27SDimitry Andric if (!A.isRegistered()) { 83206c3fb27SDimitry Andric Asm.getContext().reportError(Fixup.getLoc(), Twine("symbol '") + 83306c3fb27SDimitry Andric A.getName() + 83406c3fb27SDimitry Andric "' can not be undefined"); 83506c3fb27SDimitry Andric return; 83606c3fb27SDimitry Andric } 83706c3fb27SDimitry Andric if (A.isTemporary() && A.isUndefined()) { 83806c3fb27SDimitry Andric Asm.getContext().reportError(Fixup.getLoc(), Twine("assembler label '") + 83906c3fb27SDimitry Andric A.getName() + 84006c3fb27SDimitry Andric "' can not be undefined"); 84106c3fb27SDimitry Andric return; 84206c3fb27SDimitry Andric } 84306c3fb27SDimitry Andric 84406c3fb27SDimitry Andric MCSection *MCSec = Fragment->getParent(); 84506c3fb27SDimitry Andric 84606c3fb27SDimitry Andric // Mark this symbol as requiring an entry in the symbol table. 84706c3fb27SDimitry Andric assert(SectionMap.contains(MCSec) && 84806c3fb27SDimitry Andric "Section must already have been defined in executePostLayoutBinding!"); 84906c3fb27SDimitry Andric 85006c3fb27SDimitry Andric COFFSection *Sec = SectionMap[MCSec]; 85106c3fb27SDimitry Andric const MCSymbolRefExpr *SymB = Target.getSymB(); 85206c3fb27SDimitry Andric 85306c3fb27SDimitry Andric if (SymB) { 85406c3fb27SDimitry Andric const MCSymbol *B = &SymB->getSymbol(); 85506c3fb27SDimitry Andric if (!B->getFragment()) { 85606c3fb27SDimitry Andric Asm.getContext().reportError( 85706c3fb27SDimitry Andric Fixup.getLoc(), 85806c3fb27SDimitry Andric Twine("symbol '") + B->getName() + 85906c3fb27SDimitry Andric "' can not be undefined in a subtraction expression"); 86006c3fb27SDimitry Andric return; 86106c3fb27SDimitry Andric } 86206c3fb27SDimitry Andric 86306c3fb27SDimitry Andric // Offset of the symbol in the section 864*0fca6ea1SDimitry Andric int64_t OffsetOfB = Asm.getSymbolOffset(*B); 86506c3fb27SDimitry Andric 86606c3fb27SDimitry Andric // Offset of the relocation in the section 86706c3fb27SDimitry Andric int64_t OffsetOfRelocation = 868*0fca6ea1SDimitry Andric Asm.getFragmentOffset(*Fragment) + Fixup.getOffset(); 86906c3fb27SDimitry Andric 87006c3fb27SDimitry Andric FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant(); 87106c3fb27SDimitry Andric } else { 87206c3fb27SDimitry Andric FixedValue = Target.getConstant(); 87306c3fb27SDimitry Andric } 87406c3fb27SDimitry Andric 87506c3fb27SDimitry Andric COFFRelocation Reloc; 87606c3fb27SDimitry Andric 87706c3fb27SDimitry Andric Reloc.Data.SymbolTableIndex = 0; 878*0fca6ea1SDimitry Andric Reloc.Data.VirtualAddress = Asm.getFragmentOffset(*Fragment); 87906c3fb27SDimitry Andric 88006c3fb27SDimitry Andric // Turn relocations for temporary symbols into section relocations. 8815f757f3fSDimitry Andric if (A.isTemporary() && !SymbolMap[&A]) { 88206c3fb27SDimitry Andric MCSection *TargetSection = &A.getSection(); 88306c3fb27SDimitry Andric assert( 88406c3fb27SDimitry Andric SectionMap.contains(TargetSection) && 88506c3fb27SDimitry Andric "Section must already have been defined in executePostLayoutBinding!"); 88606c3fb27SDimitry Andric COFFSection *Section = SectionMap[TargetSection]; 88706c3fb27SDimitry Andric Reloc.Symb = Section->Symbol; 888*0fca6ea1SDimitry Andric FixedValue += Asm.getSymbolOffset(A); 88906c3fb27SDimitry Andric // Technically, we should do the final adjustments of FixedValue (below) 89006c3fb27SDimitry Andric // before picking an offset symbol, otherwise we might choose one which 89106c3fb27SDimitry Andric // is slightly too far away. The relocations where it really matters 89206c3fb27SDimitry Andric // (arm64 adrp relocations) don't get any offset though. 89306c3fb27SDimitry Andric if (UseOffsetLabels && !Section->OffsetSymbols.empty()) { 89406c3fb27SDimitry Andric uint64_t LabelIndex = FixedValue >> OffsetLabelIntervalBits; 89506c3fb27SDimitry Andric if (LabelIndex > 0) { 89606c3fb27SDimitry Andric if (LabelIndex <= Section->OffsetSymbols.size()) 89706c3fb27SDimitry Andric Reloc.Symb = Section->OffsetSymbols[LabelIndex - 1]; 89806c3fb27SDimitry Andric else 89906c3fb27SDimitry Andric Reloc.Symb = Section->OffsetSymbols.back(); 90006c3fb27SDimitry Andric FixedValue -= Reloc.Symb->Data.Value; 90106c3fb27SDimitry Andric } 90206c3fb27SDimitry Andric } 90306c3fb27SDimitry Andric } else { 90406c3fb27SDimitry Andric assert( 90506c3fb27SDimitry Andric SymbolMap.contains(&A) && 90606c3fb27SDimitry Andric "Symbol must already have been defined in executePostLayoutBinding!"); 90706c3fb27SDimitry Andric Reloc.Symb = SymbolMap[&A]; 90806c3fb27SDimitry Andric } 90906c3fb27SDimitry Andric 91006c3fb27SDimitry Andric ++Reloc.Symb->Relocations; 91106c3fb27SDimitry Andric 91206c3fb27SDimitry Andric Reloc.Data.VirtualAddress += Fixup.getOffset(); 91306c3fb27SDimitry Andric Reloc.Data.Type = OWriter.TargetObjectWriter->getRelocType( 91406c3fb27SDimitry Andric Asm.getContext(), Target, Fixup, SymB, Asm.getBackend()); 91506c3fb27SDimitry Andric 91606c3fb27SDimitry Andric // The *_REL32 relocations are relative to the end of the relocation, 91706c3fb27SDimitry Andric // not to the start. 91806c3fb27SDimitry Andric if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 && 91906c3fb27SDimitry Andric Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) || 92006c3fb27SDimitry Andric (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 && 92106c3fb27SDimitry Andric Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32) || 92206c3fb27SDimitry Andric (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT && 92306c3fb27SDimitry Andric Reloc.Data.Type == COFF::IMAGE_REL_ARM_REL32) || 924*0fca6ea1SDimitry Andric (COFF::isAnyArm64(Header.Machine) && 92506c3fb27SDimitry Andric Reloc.Data.Type == COFF::IMAGE_REL_ARM64_REL32)) 92606c3fb27SDimitry Andric FixedValue += 4; 92706c3fb27SDimitry Andric 92806c3fb27SDimitry Andric if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) { 92906c3fb27SDimitry Andric switch (Reloc.Data.Type) { 93006c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_ABSOLUTE: 93106c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32: 93206c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32NB: 93306c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_TOKEN: 93406c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_SECTION: 93506c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL: 93606c3fb27SDimitry Andric break; 93706c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH11: 93806c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BLX11: 93906c3fb27SDimitry Andric // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for 94006c3fb27SDimitry Andric // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid 94106c3fb27SDimitry Andric // for Windows CE). 94206c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH24: 94306c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BLX24: 94406c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_MOV32A: 94506c3fb27SDimitry Andric // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are 94606c3fb27SDimitry Andric // only used for ARM mode code, which is documented as being unsupported 94706c3fb27SDimitry Andric // by Windows on ARM. Empirical proof indicates that masm is able to 94806c3fb27SDimitry Andric // generate the relocations however the rest of the MSVC toolchain is 94906c3fb27SDimitry Andric // unable to handle it. 95006c3fb27SDimitry Andric llvm_unreachable("unsupported relocation"); 95106c3fb27SDimitry Andric break; 95206c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_MOV32T: 95306c3fb27SDimitry Andric break; 95406c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH20T: 95506c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BRANCH24T: 95606c3fb27SDimitry Andric case COFF::IMAGE_REL_ARM_BLX23T: 95706c3fb27SDimitry Andric // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all 95806c3fb27SDimitry Andric // perform a 4 byte adjustment to the relocation. Relative branches are 95906c3fb27SDimitry Andric // offset by 4 on ARM, however, because there is no RELA relocations, all 96006c3fb27SDimitry Andric // branches are offset by 4. 96106c3fb27SDimitry Andric FixedValue = FixedValue + 4; 96206c3fb27SDimitry Andric break; 96306c3fb27SDimitry Andric } 96406c3fb27SDimitry Andric } 96506c3fb27SDimitry Andric 96606c3fb27SDimitry Andric // The fixed value never makes sense for section indices, ignore it. 96706c3fb27SDimitry Andric if (Fixup.getKind() == FK_SecRel_2) 96806c3fb27SDimitry Andric FixedValue = 0; 96906c3fb27SDimitry Andric 97006c3fb27SDimitry Andric if (OWriter.TargetObjectWriter->recordRelocation(Fixup)) 97106c3fb27SDimitry Andric Sec->Relocations.push_back(Reloc); 97206c3fb27SDimitry Andric } 97306c3fb27SDimitry Andric 97406c3fb27SDimitry Andric static std::time_t getTime() { 97506c3fb27SDimitry Andric std::time_t Now = time(nullptr); 97606c3fb27SDimitry Andric if (Now < 0 || !isUInt<32>(Now)) 97706c3fb27SDimitry Andric return UINT32_MAX; 97806c3fb27SDimitry Andric return Now; 97906c3fb27SDimitry Andric } 98006c3fb27SDimitry Andric 981*0fca6ea1SDimitry Andric uint64_t WinCOFFWriter::writeObject(MCAssembler &Asm) { 9820b57cec5SDimitry Andric uint64_t StartOffset = W.OS.tell(); 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric if (Sections.size() > INT32_MAX) 9850b57cec5SDimitry Andric report_fatal_error( 9860b57cec5SDimitry Andric "PE COFF object files can't have more than 2147483647 sections"); 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric UseBigObj = Sections.size() > COFF::MaxNumberOfSections16; 9890b57cec5SDimitry Andric Header.NumberOfSections = Sections.size(); 9900b57cec5SDimitry Andric Header.NumberOfSymbols = 0; 9910b57cec5SDimitry Andric 9925ffd83dbSDimitry Andric setWeakDefaultNames(); 9930b57cec5SDimitry Andric assignSectionNumbers(); 99406c3fb27SDimitry Andric if (Mode != DwoOnly) 9950b57cec5SDimitry Andric createFileSymbols(Asm); 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric for (auto &Symbol : Symbols) { 9980b57cec5SDimitry Andric // Update section number & offset for symbols that have them. 9990b57cec5SDimitry Andric if (Symbol->Section) 10000b57cec5SDimitry Andric Symbol->Data.SectionNumber = Symbol->Section->Number; 10010b57cec5SDimitry Andric Symbol->setIndex(Header.NumberOfSymbols++); 10020b57cec5SDimitry Andric // Update auxiliary symbol info. 10030b57cec5SDimitry Andric Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size(); 10040b57cec5SDimitry Andric Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols; 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric // Build string table. 10080b57cec5SDimitry Andric for (const auto &S : Sections) 10090b57cec5SDimitry Andric if (S->Name.size() > COFF::NameSize) 10100b57cec5SDimitry Andric Strings.add(S->Name); 10110b57cec5SDimitry Andric for (const auto &S : Symbols) 10120b57cec5SDimitry Andric if (S->Name.size() > COFF::NameSize) 10130b57cec5SDimitry Andric Strings.add(S->Name); 10140b57cec5SDimitry Andric Strings.finalize(); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric // Set names. 10170b57cec5SDimitry Andric for (const auto &S : Sections) 10180b57cec5SDimitry Andric SetSectionName(*S); 10190b57cec5SDimitry Andric for (auto &S : Symbols) 10200b57cec5SDimitry Andric SetSymbolName(*S); 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric // Fixup weak external references. 10230b57cec5SDimitry Andric for (auto &Symbol : Symbols) { 10240b57cec5SDimitry Andric if (Symbol->Other) { 10250b57cec5SDimitry Andric assert(Symbol->getIndex() != -1); 10260b57cec5SDimitry Andric assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!"); 10270b57cec5SDimitry Andric assert(Symbol->Aux[0].AuxType == ATWeakExternal && 10280b57cec5SDimitry Andric "Symbol's aux symbol must be a Weak External!"); 10290b57cec5SDimitry Andric Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex(); 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric // Fixup associative COMDAT sections. 10340b57cec5SDimitry Andric for (auto &Section : Sections) { 10350b57cec5SDimitry Andric if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection != 10360b57cec5SDimitry Andric COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) 10370b57cec5SDimitry Andric continue; 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric const MCSectionCOFF &MCSec = *Section->MCSection; 10400b57cec5SDimitry Andric const MCSymbol *AssocMCSym = MCSec.getCOMDATSymbol(); 10410b57cec5SDimitry Andric assert(AssocMCSym); 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric // It's an error to try to associate with an undefined symbol or a symbol 10440b57cec5SDimitry Andric // without a section. 10450b57cec5SDimitry Andric if (!AssocMCSym->isInSection()) { 10460b57cec5SDimitry Andric Asm.getContext().reportError( 10475ffd83dbSDimitry Andric SMLoc(), Twine("cannot make section ") + MCSec.getName() + 10480b57cec5SDimitry Andric Twine(" associative with sectionless symbol ") + 10490b57cec5SDimitry Andric AssocMCSym->getName()); 10500b57cec5SDimitry Andric continue; 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric const auto *AssocMCSec = cast<MCSectionCOFF>(&AssocMCSym->getSection()); 10540b57cec5SDimitry Andric assert(SectionMap.count(AssocMCSec)); 10550b57cec5SDimitry Andric COFFSection *AssocSec = SectionMap[AssocMCSec]; 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric // Skip this section if the associated section is unused. 10580b57cec5SDimitry Andric if (AssocSec->Number == -1) 10590b57cec5SDimitry Andric continue; 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric Section->Symbol->Aux[0].Aux.SectionDefinition.Number = AssocSec->Number; 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric // Create the contents of the .llvm_addrsig section. 1065*0fca6ea1SDimitry Andric if (Mode != DwoOnly && OWriter.getEmitAddrsigSection()) { 1066*0fca6ea1SDimitry Andric auto *Sec = Asm.getContext().getCOFFSection( 1067*0fca6ea1SDimitry Andric ".llvm_addrsig", COFF::IMAGE_SCN_LNK_REMOVE); 1068*0fca6ea1SDimitry Andric auto *Frag = cast<MCDataFragment>(Sec->curFragList()->Head); 10690b57cec5SDimitry Andric raw_svector_ostream OS(Frag->getContents()); 107006c3fb27SDimitry Andric for (const MCSymbol *S : OWriter.AddrsigSyms) { 1071bdd1243dSDimitry Andric if (!S->isRegistered()) 1072bdd1243dSDimitry Andric continue; 10730b57cec5SDimitry Andric if (!S->isTemporary()) { 10740b57cec5SDimitry Andric encodeULEB128(S->getIndex(), OS); 10750b57cec5SDimitry Andric continue; 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric MCSection *TargetSection = &S->getSection(); 107906c3fb27SDimitry Andric assert(SectionMap.contains(TargetSection) && 10800b57cec5SDimitry Andric "Section must already have been defined in " 10810b57cec5SDimitry Andric "executePostLayoutBinding!"); 10820b57cec5SDimitry Andric encodeULEB128(SectionMap[TargetSection]->Symbol->getIndex(), OS); 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric 10865ffd83dbSDimitry Andric // Create the contents of the .llvm.call-graph-profile section. 1087*0fca6ea1SDimitry Andric if (Mode != DwoOnly && !OWriter.getCGProfile().empty()) { 1088*0fca6ea1SDimitry Andric auto *Sec = Asm.getContext().getCOFFSection( 1089*0fca6ea1SDimitry Andric ".llvm.call-graph-profile", COFF::IMAGE_SCN_LNK_REMOVE); 1090*0fca6ea1SDimitry Andric auto *Frag = cast<MCDataFragment>(Sec->curFragList()->Head); 10915ffd83dbSDimitry Andric raw_svector_ostream OS(Frag->getContents()); 1092*0fca6ea1SDimitry Andric for (const auto &CGPE : OWriter.getCGProfile()) { 10935ffd83dbSDimitry Andric uint32_t FromIndex = CGPE.From->getSymbol().getIndex(); 10945ffd83dbSDimitry Andric uint32_t ToIndex = CGPE.To->getSymbol().getIndex(); 10955ffd83dbSDimitry Andric support::endian::write(OS, FromIndex, W.Endian); 10965ffd83dbSDimitry Andric support::endian::write(OS, ToIndex, W.Endian); 10975ffd83dbSDimitry Andric support::endian::write(OS, CGPE.Count, W.Endian); 10985ffd83dbSDimitry Andric } 10995ffd83dbSDimitry Andric } 11005ffd83dbSDimitry Andric 1101*0fca6ea1SDimitry Andric assignFileOffsets(Asm); 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric // MS LINK expects to be able to use this timestamp to implement their 11040b57cec5SDimitry Andric // /INCREMENTAL feature. 1105*0fca6ea1SDimitry Andric if (OWriter.IncrementalLinkerCompatible) { 11060b57cec5SDimitry Andric Header.TimeDateStamp = getTime(); 11070b57cec5SDimitry Andric } else { 11080b57cec5SDimitry Andric // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU. 11090b57cec5SDimitry Andric Header.TimeDateStamp = 0; 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric // Write it all to disk... 11130b57cec5SDimitry Andric WriteFileHeader(Header); 11140b57cec5SDimitry Andric writeSectionHeaders(); 11150b57cec5SDimitry Andric 111606c3fb27SDimitry Andric #ifndef NDEBUG 11170b57cec5SDimitry Andric sections::iterator I = Sections.begin(); 11180b57cec5SDimitry Andric sections::iterator IE = Sections.end(); 1119*0fca6ea1SDimitry Andric auto J = Asm.begin(); 1120*0fca6ea1SDimitry Andric auto JE = Asm.end(); 112106c3fb27SDimitry Andric for (; I != IE && J != JE; ++I, ++J) { 112206c3fb27SDimitry Andric while (J != JE && ((Mode == NonDwoOnly && isDwoSection(*J)) || 112306c3fb27SDimitry Andric (Mode == DwoOnly && !isDwoSection(*J)))) 112406c3fb27SDimitry Andric ++J; 112506c3fb27SDimitry Andric assert(J != JE && (**I).MCSection == &*J && "Wrong bound MCSection"); 112606c3fb27SDimitry Andric } 112706c3fb27SDimitry Andric #endif 112806c3fb27SDimitry Andric 112906c3fb27SDimitry Andric // Write section contents. 113006c3fb27SDimitry Andric for (std::unique_ptr<COFFSection> &Sec : Sections) 1131*0fca6ea1SDimitry Andric writeSection(Asm, *Sec); 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric assert(W.OS.tell() == Header.PointerToSymbolTable && 11340b57cec5SDimitry Andric "Header::PointerToSymbolTable is insane!"); 11350b57cec5SDimitry Andric 11360b57cec5SDimitry Andric // Write a symbol table. 11370b57cec5SDimitry Andric for (auto &Symbol : Symbols) 11380b57cec5SDimitry Andric if (Symbol->getIndex() != -1) 11390b57cec5SDimitry Andric WriteSymbol(*Symbol); 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric // Write a string table, which completes the entire COFF file. 11420b57cec5SDimitry Andric Strings.write(W.OS); 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric return W.OS.tell() - StartOffset; 11450b57cec5SDimitry Andric } 11460b57cec5SDimitry Andric 114706c3fb27SDimitry Andric //------------------------------------------------------------------------------ 114806c3fb27SDimitry Andric // WinCOFFObjectWriter class implementation 114906c3fb27SDimitry Andric 115006c3fb27SDimitry Andric //////////////////////////////////////////////////////////////////////////////// 115106c3fb27SDimitry Andric // MCObjectWriter interface implementations 115206c3fb27SDimitry Andric 115306c3fb27SDimitry Andric void WinCOFFObjectWriter::reset() { 1154*0fca6ea1SDimitry Andric IncrementalLinkerCompatible = false; 115506c3fb27SDimitry Andric ObjWriter->reset(); 115606c3fb27SDimitry Andric if (DwoWriter) 115706c3fb27SDimitry Andric DwoWriter->reset(); 115806c3fb27SDimitry Andric MCObjectWriter::reset(); 115906c3fb27SDimitry Andric } 116006c3fb27SDimitry Andric 116106c3fb27SDimitry Andric bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( 116206c3fb27SDimitry Andric const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, 116306c3fb27SDimitry Andric bool InSet, bool IsPCRel) const { 116406c3fb27SDimitry Andric // Don't drop relocations between functions, even if they are in the same text 116506c3fb27SDimitry Andric // section. Multiple Visual C++ linker features depend on having the 116606c3fb27SDimitry Andric // relocations present. The /INCREMENTAL flag will cause these relocations to 116706c3fb27SDimitry Andric // point to thunks, and the /GUARD:CF flag assumes that it can use relocations 116806c3fb27SDimitry Andric // to approximate the set of all address taken functions. LLD's implementation 116906c3fb27SDimitry Andric // of /GUARD:CF also relies on the existance of these relocations. 117006c3fb27SDimitry Andric uint16_t Type = cast<MCSymbolCOFF>(SymA).getType(); 117106c3fb27SDimitry Andric if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION) 117206c3fb27SDimitry Andric return false; 1173*0fca6ea1SDimitry Andric return &SymA.getSection() == FB.getParent(); 117406c3fb27SDimitry Andric } 117506c3fb27SDimitry Andric 1176*0fca6ea1SDimitry Andric void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm) { 1177*0fca6ea1SDimitry Andric ObjWriter->executePostLayoutBinding(Asm); 117806c3fb27SDimitry Andric if (DwoWriter) 1179*0fca6ea1SDimitry Andric DwoWriter->executePostLayoutBinding(Asm); 118006c3fb27SDimitry Andric } 118106c3fb27SDimitry Andric 118206c3fb27SDimitry Andric void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm, 118306c3fb27SDimitry Andric const MCFragment *Fragment, 118406c3fb27SDimitry Andric const MCFixup &Fixup, MCValue Target, 118506c3fb27SDimitry Andric uint64_t &FixedValue) { 118606c3fb27SDimitry Andric assert(!isDwoSection(*Fragment->getParent()) && 118706c3fb27SDimitry Andric "No relocation in Dwo sections"); 1188*0fca6ea1SDimitry Andric ObjWriter->recordRelocation(Asm, Fragment, Fixup, Target, FixedValue); 118906c3fb27SDimitry Andric } 119006c3fb27SDimitry Andric 1191*0fca6ea1SDimitry Andric uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm) { 1192*0fca6ea1SDimitry Andric uint64_t TotalSize = ObjWriter->writeObject(Asm); 119306c3fb27SDimitry Andric if (DwoWriter) 1194*0fca6ea1SDimitry Andric TotalSize += DwoWriter->writeObject(Asm); 119506c3fb27SDimitry Andric return TotalSize; 119606c3fb27SDimitry Andric } 119706c3fb27SDimitry Andric 11980b57cec5SDimitry Andric MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) 11990b57cec5SDimitry Andric : Machine(Machine_) {} 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andric // Pin the vtable to this file. 12020b57cec5SDimitry Andric void MCWinCOFFObjectTargetWriter::anchor() {} 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric //------------------------------------------------------------------------------ 12050b57cec5SDimitry Andric // WinCOFFObjectWriter factory function 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter( 12080b57cec5SDimitry Andric std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) { 12098bcb0991SDimitry Andric return std::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS); 12100b57cec5SDimitry Andric } 121106c3fb27SDimitry Andric 121206c3fb27SDimitry Andric std::unique_ptr<MCObjectWriter> llvm::createWinCOFFDwoObjectWriter( 121306c3fb27SDimitry Andric std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS, 121406c3fb27SDimitry Andric raw_pwrite_stream &DwoOS) { 121506c3fb27SDimitry Andric return std::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS, DwoOS); 121606c3fb27SDimitry Andric } 1217