LCOV - code coverage report
Current view: top level - lib/MC - WinCOFFObjectWriter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 387 453 85.4 %
Date: 2018-06-17 00:07:59 Functions: 34 35 97.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- llvm/MC/WinCOFFObjectWriter.cpp ------------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // This file contains an implementation of a Win32 COFF object file writer.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/ADT/DenseMap.h"
      15             : #include "llvm/ADT/STLExtras.h"
      16             : #include "llvm/ADT/SmallString.h"
      17             : #include "llvm/ADT/SmallVector.h"
      18             : #include "llvm/ADT/StringRef.h"
      19             : #include "llvm/ADT/Twine.h"
      20             : #include "llvm/BinaryFormat/COFF.h"
      21             : #include "llvm/MC/MCAsmLayout.h"
      22             : #include "llvm/MC/MCAssembler.h"
      23             : #include "llvm/MC/MCContext.h"
      24             : #include "llvm/MC/MCExpr.h"
      25             : #include "llvm/MC/MCFixup.h"
      26             : #include "llvm/MC/MCFragment.h"
      27             : #include "llvm/MC/MCObjectWriter.h"
      28             : #include "llvm/MC/MCSection.h"
      29             : #include "llvm/MC/MCSectionCOFF.h"
      30             : #include "llvm/MC/MCSymbol.h"
      31             : #include "llvm/MC/MCSymbolCOFF.h"
      32             : #include "llvm/MC/MCValue.h"
      33             : #include "llvm/MC/MCWinCOFFObjectWriter.h"
      34             : #include "llvm/MC/StringTableBuilder.h"
      35             : #include "llvm/Support/Casting.h"
      36             : #include "llvm/Support/Endian.h"
      37             : #include "llvm/Support/ErrorHandling.h"
      38             : #include "llvm/Support/JamCRC.h"
      39             : #include "llvm/Support/MathExtras.h"
      40             : #include "llvm/Support/raw_ostream.h"
      41             : #include <algorithm>
      42             : #include <cassert>
      43             : #include <cstddef>
      44             : #include <cstdint>
      45             : #include <cstring>
      46             : #include <ctime>
      47             : #include <memory>
      48             : #include <string>
      49             : #include <vector>
      50             : 
      51             : using namespace llvm;
      52             : using llvm::support::endian::write32le;
      53             : 
      54             : #define DEBUG_TYPE "WinCOFFObjectWriter"
      55             : 
      56             : namespace {
      57             : 
      58             : using name = SmallString<COFF::NameSize>;
      59             : 
      60             : enum AuxiliaryType {
      61             :   ATFunctionDefinition,
      62             :   ATbfAndefSymbol,
      63             :   ATWeakExternal,
      64             :   ATFile,
      65             :   ATSectionDefinition
      66             : };
      67             : 
      68             : struct AuxSymbol {
      69             :   AuxiliaryType AuxType;
      70             :   COFF::Auxiliary Aux;
      71             : };
      72             : 
      73             : class COFFSection;
      74             : 
      75        6672 : class COFFSymbol {
      76             : public:
      77             :   COFF::symbol Data = {};
      78             : 
      79             :   using AuxiliarySymbols = SmallVector<AuxSymbol, 1>;
      80             : 
      81             :   name Name;
      82             :   int Index;
      83             :   AuxiliarySymbols Aux;
      84             :   COFFSymbol *Other = nullptr;
      85             :   COFFSection *Section = nullptr;
      86             :   int Relocations = 0;
      87             :   const MCSymbol *MC = nullptr;
      88             : 
      89        6704 :   COFFSymbol(StringRef Name) : Name(Name) {}
      90             : 
      91             :   void set_name_offset(uint32_t Offset);
      92             : 
      93             :   int64_t getIndex() const { return Index; }
      94             :   void setIndex(int Value) {
      95        3336 :     Index = Value;
      96        3336 :     if (MC)
      97             :       MC->setIndex(static_cast<uint32_t>(Value));
      98             :   }
      99             : };
     100             : 
     101             : // This class contains staging data for a COFF relocation entry.
     102             : struct COFFRelocation {
     103             :   COFF::relocation Data;
     104             :   COFFSymbol *Symb = nullptr;
     105             : 
     106        2352 :   COFFRelocation() = default;
     107             : 
     108             :   static size_t size() { return COFF::RelocationSize; }
     109             : };
     110             : 
     111             : using relocations = std::vector<COFFRelocation>;
     112             : 
     113        4138 : class COFFSection {
     114             : public:
     115             :   COFF::section Header = {};
     116             : 
     117             :   std::string Name;
     118             :   int Number;
     119             :   MCSectionCOFF const *MCSection = nullptr;
     120             :   COFFSymbol *Symbol = nullptr;
     121             :   relocations Relocations;
     122             : 
     123        6246 :   COFFSection(StringRef Name) : Name(Name) {}
     124             : };
     125             : 
     126        3728 : class WinCOFFObjectWriter : public MCObjectWriter {
     127             : public:
     128             :   support::endian::Writer W;
     129             : 
     130             :   using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
     131             :   using sections = std::vector<std::unique_ptr<COFFSection>>;
     132             : 
     133             :   using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>;
     134             :   using section_map = DenseMap<MCSection const *, COFFSection *>;
     135             : 
     136             :   std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
     137             : 
     138             :   // Root level file contents.
     139             :   COFF::header Header = {};
     140             :   sections Sections;
     141             :   symbols Symbols;
     142             :   StringTableBuilder Strings{StringTableBuilder::WinCOFF};
     143             : 
     144             :   // Maps used during object file creation.
     145             :   section_map SectionMap;
     146             :   symbol_map SymbolMap;
     147             : 
     148             :   bool UseBigObj;
     149             : 
     150             :   WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
     151             :                       raw_pwrite_stream &OS);
     152             : 
     153         182 :   void reset() override {
     154         182 :     memset(&Header, 0, sizeof(Header));
     155         182 :     Header.Machine = TargetObjectWriter->getMachine();
     156             :     Sections.clear();
     157             :     Symbols.clear();
     158         182 :     Strings.clear();
     159         182 :     SectionMap.clear();
     160         182 :     SymbolMap.clear();
     161             :     MCObjectWriter::reset();
     162         182 :   }
     163             : 
     164             :   COFFSymbol *createSymbol(StringRef Name);
     165             :   COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol *Symbol);
     166             :   COFFSection *createSection(StringRef Name);
     167             : 
     168             :   void defineSection(MCSectionCOFF const &Sec);
     169             : 
     170             :   COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
     171             :   void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
     172             :                     const MCAsmLayout &Layout);
     173             : 
     174             :   void SetSymbolName(COFFSymbol &S);
     175             :   void SetSectionName(COFFSection &S);
     176             : 
     177             :   bool IsPhysicalSection(COFFSection *S);
     178             : 
     179             :   // Entity writing methods.
     180             : 
     181             :   void WriteFileHeader(const COFF::header &Header);
     182             :   void WriteSymbol(const COFFSymbol &S);
     183             :   void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
     184             :   void writeSectionHeaders();
     185             :   void WriteRelocation(const COFF::relocation &R);
     186             :   uint32_t writeSectionContents(MCAssembler &Asm, const MCAsmLayout &Layout,
     187             :                                 const MCSection &MCSec);
     188             :   void writeSection(MCAssembler &Asm, const MCAsmLayout &Layout,
     189             :                     const COFFSection &Sec, const MCSection &MCSec);
     190             : 
     191             :   // MCObjectWriter interface implementation.
     192             : 
     193             :   void executePostLayoutBinding(MCAssembler &Asm,
     194             :                                 const MCAsmLayout &Layout) override;
     195             : 
     196             :   bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
     197             :                                               const MCSymbol &SymA,
     198             :                                               const MCFragment &FB, bool InSet,
     199             :                                               bool IsPCRel) const override;
     200             : 
     201             :   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
     202             :                         const MCFragment *Fragment, const MCFixup &Fixup,
     203             :                         MCValue Target, uint64_t &FixedValue) override;
     204             : 
     205             :   void createFileSymbols(MCAssembler &Asm);
     206             :   void assignSectionNumbers();
     207             :   void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
     208             : 
     209             :   uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
     210             : };
     211             : 
     212             : } // end anonymous namespace
     213             : 
     214             : //------------------------------------------------------------------------------
     215             : // Symbol class implementation
     216             : 
     217             : // In the case that the name does not fit within 8 bytes, the offset
     218             : // into the string table is stored in the last 4 bytes instead, leaving
     219             : // the first 4 bytes as 0.
     220             : void COFFSymbol::set_name_offset(uint32_t Offset) {
     221             :   write32le(Data.Name + 0, 0);
     222             :   write32le(Data.Name + 4, Offset);
     223             : }
     224             : 
     225             : //------------------------------------------------------------------------------
     226             : // WinCOFFObjectWriter class implementation
     227             : 
     228         939 : WinCOFFObjectWriter::WinCOFFObjectWriter(
     229         939 :     std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
     230        3756 :     : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {
     231         939 :   Header.Machine = TargetObjectWriter->getMachine();
     232         939 : }
     233             : 
     234        3352 : COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) {
     235        6704 :   Symbols.push_back(make_unique<COFFSymbol>(Name));
     236        3352 :   return Symbols.back().get();
     237             : }
     238             : 
     239        1619 : COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) {
     240        1619 :   COFFSymbol *&Ret = SymbolMap[Symbol];
     241        1619 :   if (!Ret)
     242        2490 :     Ret = createSymbol(Symbol->getName());
     243        1619 :   return Ret;
     244             : }
     245             : 
     246        2082 : COFFSection *WinCOFFObjectWriter::createSection(StringRef Name) {
     247        2082 :   Sections.emplace_back(make_unique<COFFSection>(Name));
     248        2082 :   return Sections.back().get();
     249             : }
     250             : 
     251        2081 : static uint32_t getAlignment(const MCSectionCOFF &Sec) {
     252        2081 :   switch (Sec.getAlignment()) {
     253             :   case 1:
     254             :     return COFF::IMAGE_SCN_ALIGN_1BYTES;
     255           3 :   case 2:
     256           3 :     return COFF::IMAGE_SCN_ALIGN_2BYTES;
     257        1397 :   case 4:
     258        1397 :     return COFF::IMAGE_SCN_ALIGN_4BYTES;
     259          39 :   case 8:
     260          39 :     return COFF::IMAGE_SCN_ALIGN_8BYTES;
     261         271 :   case 16:
     262         271 :     return COFF::IMAGE_SCN_ALIGN_16BYTES;
     263           1 :   case 32:
     264           1 :     return COFF::IMAGE_SCN_ALIGN_32BYTES;
     265           0 :   case 64:
     266           0 :     return COFF::IMAGE_SCN_ALIGN_64BYTES;
     267           0 :   case 128:
     268           0 :     return COFF::IMAGE_SCN_ALIGN_128BYTES;
     269           0 :   case 256:
     270           0 :     return COFF::IMAGE_SCN_ALIGN_256BYTES;
     271           0 :   case 512:
     272           0 :     return COFF::IMAGE_SCN_ALIGN_512BYTES;
     273           0 :   case 1024:
     274           0 :     return COFF::IMAGE_SCN_ALIGN_1024BYTES;
     275           0 :   case 2048:
     276           0 :     return COFF::IMAGE_SCN_ALIGN_2048BYTES;
     277           0 :   case 4096:
     278           0 :     return COFF::IMAGE_SCN_ALIGN_4096BYTES;
     279           0 :   case 8192:
     280           0 :     return COFF::IMAGE_SCN_ALIGN_8192BYTES;
     281             :   }
     282           0 :   llvm_unreachable("unsupported section alignment");
     283             : }
     284             : 
     285             : /// This function takes a section data object from the assembler
     286             : /// and creates the associated COFF section staging object.
     287        2082 : void WinCOFFObjectWriter::defineSection(const MCSectionCOFF &MCSec) {
     288        2082 :   COFFSection *Section = createSection(MCSec.getSectionName());
     289        2082 :   COFFSymbol *Symbol = createSymbol(MCSec.getSectionName());
     290        2082 :   Section->Symbol = Symbol;
     291        2082 :   Symbol->Section = Section;
     292        2082 :   Symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
     293             : 
     294             :   // Create a COMDAT symbol if needed.
     295        2082 :   if (MCSec.getSelection() != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
     296        1966 :     if (const MCSymbol *S = MCSec.getCOMDATSymbol()) {
     297         260 :       COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
     298         260 :       if (COMDATSymbol->Section)
     299           1 :         report_fatal_error("two sections have the same comdat");
     300         259 :       COMDATSymbol->Section = Section;
     301             :     }
     302             :   }
     303             : 
     304             :   // In this case the auxiliary symbol is a Section Definition.
     305        2081 :   Symbol->Aux.resize(1);
     306        2081 :   Symbol->Aux[0] = {};
     307        2081 :   Symbol->Aux[0].AuxType = ATSectionDefinition;
     308        4162 :   Symbol->Aux[0].Aux.SectionDefinition.Selection = MCSec.getSelection();
     309             : 
     310             :   // Set section alignment.
     311        2081 :   Section->Header.Characteristics = MCSec.getCharacteristics();
     312        2081 :   Section->Header.Characteristics |= getAlignment(MCSec);
     313             : 
     314             :   // Bind internal COFF section to MC section.
     315        2081 :   Section->MCSection = &MCSec;
     316        4162 :   SectionMap[&MCSec] = Section;
     317        2081 : }
     318             : 
     319        1240 : static uint64_t getSymbolValue(const MCSymbol &Symbol,
     320             :                                const MCAsmLayout &Layout) {
     321        1259 :   if (Symbol.isCommon() && Symbol.isExternal())
     322          19 :     return Symbol.getCommonSize();
     323             : 
     324             :   uint64_t Res;
     325        1221 :   if (!Layout.getSymbolOffset(Symbol, Res))
     326             :     return 0;
     327             : 
     328        1031 :   return Res;
     329             : }
     330             : 
     331           8 : COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
     332           8 :   if (!Symbol.isVariable())
     333             :     return nullptr;
     334             : 
     335             :   const MCSymbolRefExpr *SymRef =
     336             :       dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
     337             :   if (!SymRef)
     338             :     return nullptr;
     339             : 
     340           4 :   const MCSymbol &Aliasee = SymRef->getSymbol();
     341           4 :   if (!Aliasee.isUndefined())
     342             :     return nullptr;
     343           1 :   return GetOrCreateCOFFSymbol(&Aliasee);
     344             : }
     345             : 
     346             : /// This function takes a symbol data object from the assembler
     347             : /// and creates the associated COFF symbol staging object.
     348        1242 : void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym,
     349             :                                        MCAssembler &Assembler,
     350             :                                        const MCAsmLayout &Layout) {
     351        1242 :   COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym);
     352        1242 :   const MCSymbol *Base = Layout.getBaseSymbol(MCSym);
     353             :   COFFSection *Sec = nullptr;
     354        1242 :   if (Base && Base->getFragment()) {
     355        1896 :     Sec = SectionMap[Base->getFragment()->getParent()];
     356         948 :     if (Sym->Section && Sym->Section != Sec)
     357           1 :       report_fatal_error("conflicting sections for symbol");
     358             :   }
     359             : 
     360             :   COFFSymbol *Local = nullptr;
     361        1241 :   if (cast<MCSymbolCOFF>(MCSym).isWeakExternal()) {
     362           8 :     Sym->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
     363             : 
     364           8 :     COFFSymbol *WeakDefault = getLinkedSymbol(MCSym);
     365           8 :     if (!WeakDefault) {
     366          14 :       std::string WeakName = (".weak." + MCSym.getName() + ".default").str();
     367           7 :       WeakDefault = createSymbol(WeakName);
     368           7 :       if (!Sec)
     369           3 :         WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
     370             :       else
     371           4 :         WeakDefault->Section = Sec;
     372             :       Local = WeakDefault;
     373             :     }
     374             : 
     375           8 :     Sym->Other = WeakDefault;
     376             : 
     377             :     // Setup the Weak External auxiliary symbol.
     378           8 :     Sym->Aux.resize(1);
     379           8 :     memset(&Sym->Aux[0], 0, sizeof(Sym->Aux[0]));
     380           8 :     Sym->Aux[0].AuxType = ATWeakExternal;
     381           8 :     Sym->Aux[0].Aux.WeakExternal.TagIndex = 0;
     382           8 :     Sym->Aux[0].Aux.WeakExternal.Characteristics =
     383             :         COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
     384             :   } else {
     385        1233 :     if (!Base)
     386          84 :       Sym->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
     387             :     else
     388        1149 :       Sym->Section = Sec;
     389             :     Local = Sym;
     390             :   }
     391             : 
     392        1241 :   if (Local) {
     393        1240 :     Local->Data.Value = getSymbolValue(MCSym, Layout);
     394             : 
     395             :     const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(MCSym);
     396        1240 :     Local->Data.Type = SymbolCOFF.getType();
     397        1240 :     Local->Data.StorageClass = SymbolCOFF.getClass();
     398             : 
     399             :     // If no storage class was specified in the streamer, define it here.
     400        1240 :     if (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
     401        1302 :       bool IsExternal = MCSym.isExternal() ||
     402         667 :                         (!MCSym.getFragment() && !MCSym.isVariable());
     403             : 
     404         818 :       Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
     405             :                                             : COFF::IMAGE_SYM_CLASS_STATIC;
     406             :     }
     407             :   }
     408             : 
     409        1241 :   Sym->MC = &MCSym;
     410        1241 : }
     411             : 
     412             : // Maximum offsets for different string table entry encodings.
     413             : enum : unsigned { Max7DecimalOffset = 9999999U };
     414             : enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0
     415             : 
     416             : // Encode a string table entry offset in base 64, padded to 6 chars, and
     417             : // prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
     418             : // Buffer must be at least 8 bytes large. No terminating null appended.
     419             : static void encodeBase64StringEntry(char *Buffer, uint64_t Value) {
     420             :   assert(Value > Max7DecimalOffset && Value <= MaxBase64Offset &&
     421             :          "Illegal section name encoding for value");
     422             : 
     423             :   static const char Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     424             :                                  "abcdefghijklmnopqrstuvwxyz"
     425             :                                  "0123456789+/";
     426             : 
     427           1 :   Buffer[0] = '/';
     428           1 :   Buffer[1] = '/';
     429             : 
     430           1 :   char *Ptr = Buffer + 7;
     431          13 :   for (unsigned i = 0; i < 6; ++i) {
     432           6 :     unsigned Rem = Value % 64;
     433           6 :     Value /= 64;
     434           6 :     *(Ptr--) = Alphabet[Rem];
     435             :   }
     436             : }
     437             : 
     438        2069 : void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
     439        2069 :   if (S.Name.size() <= COFF::NameSize) {
     440        1877 :     std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
     441        1877 :     return;
     442             :   }
     443             : 
     444         384 :   uint64_t StringTableEntry = Strings.getOffset(S.Name);
     445         192 :   if (StringTableEntry <= Max7DecimalOffset) {
     446             :     SmallVector<char, COFF::NameSize> Buffer;
     447         191 :     Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer);
     448             :     assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2);
     449         191 :     std::memcpy(S.Header.Name, Buffer.data(), Buffer.size());
     450             :     return;
     451             :   }
     452           1 :   if (StringTableEntry <= MaxBase64Offset) {
     453             :     // Starting with 10,000,000, offsets are encoded as base64.
     454             :     encodeBase64StringEntry(S.Header.Name, StringTableEntry);
     455             :     return;
     456             :   }
     457           0 :   report_fatal_error("COFF string table is greater than 64 GB.");
     458             : }
     459             : 
     460        3336 : void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
     461        3336 :   if (S.Name.size() > COFF::NameSize)
     462         649 :     S.set_name_offset(Strings.getOffset(S.Name));
     463             :   else
     464        2687 :     std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
     465        3336 : }
     466             : 
     467             : bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
     468        2069 :   return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==
     469             :          0;
     470             : }
     471             : 
     472             : //------------------------------------------------------------------------------
     473             : // entity writing methods
     474             : 
     475         374 : void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
     476         374 :   if (UseBigObj) {
     477             :     W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
     478             :     W.write<uint16_t>(0xFFFF);
     479             :     W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion);
     480           0 :     W.write<uint16_t>(Header.Machine);
     481           0 :     W.write<uint32_t>(Header.TimeDateStamp);
     482           0 :     W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
     483           0 :     W.write<uint32_t>(0);
     484           0 :     W.write<uint32_t>(0);
     485           0 :     W.write<uint32_t>(0);
     486           0 :     W.write<uint32_t>(0);
     487           0 :     W.write<uint32_t>(Header.NumberOfSections);
     488           0 :     W.write<uint32_t>(Header.PointerToSymbolTable);
     489           0 :     W.write<uint32_t>(Header.NumberOfSymbols);
     490             :   } else {
     491         374 :     W.write<uint16_t>(Header.Machine);
     492         374 :     W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections));
     493         374 :     W.write<uint32_t>(Header.TimeDateStamp);
     494         374 :     W.write<uint32_t>(Header.PointerToSymbolTable);
     495         374 :     W.write<uint32_t>(Header.NumberOfSymbols);
     496         374 :     W.write<uint16_t>(Header.SizeOfOptionalHeader);
     497         374 :     W.write<uint16_t>(Header.Characteristics);
     498             :   }
     499         374 : }
     500             : 
     501        3336 : void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
     502        3336 :   W.OS.write(S.Data.Name, COFF::NameSize);
     503        3336 :   W.write<uint32_t>(S.Data.Value);
     504        3336 :   if (UseBigObj)
     505           0 :     W.write<uint32_t>(S.Data.SectionNumber);
     506             :   else
     507        3336 :     W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber));
     508        3336 :   W.write<uint16_t>(S.Data.Type);
     509        3336 :   W.OS << char(S.Data.StorageClass);
     510        3336 :   W.OS << char(S.Data.NumberOfAuxSymbols);
     511        3336 :   WriteAuxiliarySymbols(S.Aux);
     512        3336 : }
     513             : 
     514        3336 : void WinCOFFObjectWriter::WriteAuxiliarySymbols(
     515             :     const COFFSymbol::AuxiliarySymbols &S) {
     516        7544 :   for (const AuxSymbol &i : S) {
     517        2104 :     switch (i.AuxType) {
     518           0 :     case ATFunctionDefinition:
     519           0 :       W.write<uint32_t>(i.Aux.FunctionDefinition.TagIndex);
     520           0 :       W.write<uint32_t>(i.Aux.FunctionDefinition.TotalSize);
     521           0 :       W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToLinenumber);
     522           0 :       W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToNextFunction);
     523           0 :       W.OS.write_zeros(sizeof(i.Aux.FunctionDefinition.unused));
     524           0 :       if (UseBigObj)
     525           0 :         W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
     526             :       break;
     527           0 :     case ATbfAndefSymbol:
     528           0 :       W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused1));
     529           0 :       W.write<uint16_t>(i.Aux.bfAndefSymbol.Linenumber);
     530           0 :       W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused2));
     531           0 :       W.write<uint32_t>(i.Aux.bfAndefSymbol.PointerToNextFunction);
     532           0 :       W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused3));
     533           0 :       if (UseBigObj)
     534           0 :         W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
     535             :       break;
     536           8 :     case ATWeakExternal:
     537           8 :       W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
     538           8 :       W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
     539           8 :       W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused));
     540           8 :       if (UseBigObj)
     541           0 :         W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
     542             :       break;
     543          27 :     case ATFile:
     544          54 :       W.OS.write(reinterpret_cast<const char *>(&i.Aux),
     545          27 :                         UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size);
     546          27 :       break;
     547        2069 :     case ATSectionDefinition:
     548        2069 :       W.write<uint32_t>(i.Aux.SectionDefinition.Length);
     549        2069 :       W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
     550        2069 :       W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
     551        2069 :       W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum);
     552        2069 :       W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
     553        2069 :       W.OS << char(i.Aux.SectionDefinition.Selection);
     554        2069 :       W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused));
     555        2069 :       W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
     556        2069 :       if (UseBigObj)
     557           0 :         W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
     558             :       break;
     559             :     }
     560             :   }
     561        3336 : }
     562             : 
     563             : // Write the section header.
     564         374 : void WinCOFFObjectWriter::writeSectionHeaders() {
     565             :   // Section numbers must be monotonically increasing in the section
     566             :   // header, but our Sections array is not sorted by section number,
     567             :   // so make a copy of Sections and sort it.
     568             :   std::vector<COFFSection *> Arr;
     569        2443 :   for (auto &Section : Sections)
     570        4138 :     Arr.push_back(Section.get());
     571             :   llvm::sort(Arr.begin(), Arr.end(),
     572             :              [](const COFFSection *A, const COFFSection *B) {
     573             :                return A->Number < B->Number;
     574             :              });
     575             : 
     576        2443 :   for (auto &Section : Arr) {
     577        2069 :     if (Section->Number == -1)
     578           0 :       continue;
     579             : 
     580             :     COFF::section &S = Section->Header;
     581        4138 :     if (Section->Relocations.size() >= 0xffff)
     582           0 :       S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
     583        2069 :     W.OS.write(S.Name, COFF::NameSize);
     584        2069 :     W.write<uint32_t>(S.VirtualSize);
     585        2069 :     W.write<uint32_t>(S.VirtualAddress);
     586        2069 :     W.write<uint32_t>(S.SizeOfRawData);
     587        2069 :     W.write<uint32_t>(S.PointerToRawData);
     588        2069 :     W.write<uint32_t>(S.PointerToRelocations);
     589        2069 :     W.write<uint32_t>(S.PointerToLineNumbers);
     590        2069 :     W.write<uint16_t>(S.NumberOfRelocations);
     591        2069 :     W.write<uint16_t>(S.NumberOfLineNumbers);
     592        2069 :     W.write<uint32_t>(S.Characteristics);
     593             :   }
     594         374 : }
     595             : 
     596        2340 : void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
     597        2340 :   W.write<uint32_t>(R.VirtualAddress);
     598        2340 :   W.write<uint32_t>(R.SymbolTableIndex);
     599        2340 :   W.write<uint16_t>(R.Type);
     600        2340 : }
     601             : 
     602             : // Write MCSec's contents. What this function does is essentially
     603             : // "Asm.writeSectionData(&MCSec, Layout)", but it's a bit complicated
     604             : // because it needs to compute a CRC.
     605        1691 : uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
     606             :                                                    const MCAsmLayout &Layout,
     607             :                                                    const MCSection &MCSec) {
     608             :   // Save the contents of the section to a temporary buffer, we need this
     609             :   // to CRC the data before we dump it into the object file.
     610             :   SmallVector<char, 128> Buf;
     611             :   raw_svector_ostream VecOS(Buf);
     612        1691 :   Asm.writeSectionData(VecOS, &MCSec, Layout);
     613             : 
     614             :   // Write the section contents to the object file.
     615        1691 :   W.OS << Buf;
     616             : 
     617             :   // Calculate our CRC with an initial value of '0', this is not how
     618             :   // JamCRC is specified but it aligns with the expected output.
     619             :   JamCRC JC(/*Init=*/0);
     620        1691 :   JC.update(Buf);
     621        1691 :   return JC.getCRC();
     622             : }
     623             : 
     624        2069 : void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
     625             :                                        const MCAsmLayout &Layout,
     626             :                                        const COFFSection &Sec,
     627             :                                        const MCSection &MCSec) {
     628        2069 :   if (Sec.Number == -1)
     629             :     return;
     630             : 
     631             :   // Write the section contents.
     632        2069 :   if (Sec.Header.PointerToRawData != 0) {
     633             :     assert(W.OS.tell() <= Sec.Header.PointerToRawData &&
     634             :            "Section::PointerToRawData is insane!");
     635             : 
     636        3382 :     unsigned PaddingSize = Sec.Header.PointerToRawData - W.OS.tell();
     637             :     assert(PaddingSize < 4 &&
     638             :            "Should only need at most three bytes of padding!");
     639        1691 :     W.OS.write_zeros(PaddingSize);
     640             : 
     641        1691 :     uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
     642             : 
     643             :     // Update the section definition auxiliary symbol to record the CRC.
     644        3382 :     COFFSection *Sec = SectionMap[&MCSec];
     645        1691 :     COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux;
     646             :     assert(AuxSyms.size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition);
     647             :     AuxSymbol &SecDef = AuxSyms[0];
     648        1691 :     SecDef.Aux.SectionDefinition.CheckSum = CRC;
     649             :   }
     650             : 
     651             :   // Write relocations for this section.
     652        2069 :   if (Sec.Relocations.empty()) {
     653             :     assert(Sec.Header.PointerToRelocations == 0 &&
     654             :            "Section::PointerToRelocations is insane!");
     655             :     return;
     656             :   }
     657             : 
     658             :   assert(W.OS.tell() == Sec.Header.PointerToRelocations &&
     659             :          "Section::PointerToRelocations is insane!");
     660             : 
     661         561 :   if (Sec.Relocations.size() >= 0xffff) {
     662             :     // In case of overflow, write actual relocation count as first
     663             :     // relocation. Including the synthetic reloc itself (+ 1).
     664             :     COFF::relocation R;
     665           0 :     R.VirtualAddress = Sec.Relocations.size() + 1;
     666           0 :     R.SymbolTableIndex = 0;
     667           0 :     R.Type = 0;
     668           0 :     WriteRelocation(R);
     669             :   }
     670             : 
     671         561 :   for (const auto &Relocation : Sec.Relocations)
     672        2340 :     WriteRelocation(Relocation.Data);
     673             : }
     674             : 
     675             : ////////////////////////////////////////////////////////////////////////////////
     676             : // MCObjectWriter interface implementations
     677             : 
     678         377 : void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
     679             :                                                    const MCAsmLayout &Layout) {
     680             :   // "Define" each section & symbol. This creates section & symbol
     681             :   // entries in the staging area.
     682        2458 :   for (const auto &Section : Asm)
     683        2082 :     defineSection(static_cast<const MCSectionCOFF &>(Section));
     684             : 
     685        6635 :   for (const MCSymbol &Symbol : Asm.symbols())
     686        6260 :     if (!Symbol.isTemporary())
     687        1242 :       DefineSymbol(Symbol, Asm, Layout);
     688         375 : }
     689             : 
     690        3453 : bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
     691             :     const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
     692             :     bool InSet, bool IsPCRel) const {
     693             :   // Don't drop relocations between functions, even if they are in the same text
     694             :   // section. Multiple Visual C++ linker features depend on having the
     695             :   // relocations present. The /INCREMENTAL flag will cause these relocations to
     696             :   // point to thunks, and the /GUARD:CF flag assumes that it can use relocations
     697             :   // to approximate the set of all address taken functions. LLD's implementation
     698             :   // of /GUARD:CF also relies on the existance of these relocations.
     699        3453 :   uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
     700        3453 :   if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
     701             :     return false;
     702        3391 :   return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
     703        3391 :                                                                 InSet, IsPCRel);
     704             : }
     705             : 
     706        2355 : void WinCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
     707             :                                            const MCAsmLayout &Layout,
     708             :                                            const MCFragment *Fragment,
     709             :                                            const MCFixup &Fixup, MCValue Target,
     710             :                                            uint64_t &FixedValue) {
     711             :   assert(Target.getSymA() && "Relocation must reference a symbol!");
     712             : 
     713        2355 :   const MCSymbol &A = Target.getSymA()->getSymbol();
     714        2355 :   if (!A.isRegistered()) {
     715           0 :     Asm.getContext().reportError(Fixup.getLoc(),
     716           0 :                                       Twine("symbol '") + A.getName() +
     717           0 :                                           "' can not be undefined");
     718           3 :     return;
     719             :   }
     720        3127 :   if (A.isTemporary() && A.isUndefined()) {
     721           4 :     Asm.getContext().reportError(Fixup.getLoc(),
     722           4 :                                       Twine("assembler label '") + A.getName() +
     723           2 :                                           "' can not be undefined");
     724           2 :     return;
     725             :   }
     726             : 
     727        2353 :   MCSection *MCSec = Fragment->getParent();
     728             : 
     729             :   // Mark this symbol as requiring an entry in the symbol table.
     730             :   assert(SectionMap.find(MCSec) != SectionMap.end() &&
     731             :          "Section must already have been defined in executePostLayoutBinding!");
     732             : 
     733        4706 :   COFFSection *Sec = SectionMap[MCSec];
     734        2353 :   const MCSymbolRefExpr *SymB = Target.getSymB();
     735             : 
     736        2353 :   if (SymB) {
     737          10 :     const MCSymbol *B = &SymB->getSymbol();
     738          10 :     if (!B->getFragment()) {
     739           2 :       Asm.getContext().reportError(
     740             :           Fixup.getLoc(),
     741           2 :           Twine("symbol '") + B->getName() +
     742           1 :               "' can not be undefined in a subtraction expression");
     743           1 :       return;
     744             :     }
     745             : 
     746             :     // Offset of the symbol in the section
     747           9 :     int64_t OffsetOfB = Layout.getSymbolOffset(*B);
     748             : 
     749             :     // Offset of the relocation in the section
     750             :     int64_t OffsetOfRelocation =
     751           9 :         Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
     752             : 
     753           9 :     FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.getConstant();
     754             :   } else {
     755        2343 :     FixedValue = Target.getConstant();
     756             :   }
     757             : 
     758             :   COFFRelocation Reloc;
     759             : 
     760        2352 :   Reloc.Data.SymbolTableIndex = 0;
     761        2352 :   Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
     762             : 
     763             :   // Turn relocations for temporary symbols into section relocations.
     764        2352 :   if (A.isTemporary()) {
     765             :     MCSection *TargetSection = &A.getSection();
     766             :     assert(
     767             :         SectionMap.find(TargetSection) != SectionMap.end() &&
     768             :         "Section must already have been defined in executePostLayoutBinding!");
     769        1540 :     Reloc.Symb = SectionMap[TargetSection]->Symbol;
     770         770 :     FixedValue += Layout.getSymbolOffset(A);
     771             :   } else {
     772             :     assert(
     773             :         SymbolMap.find(&A) != SymbolMap.end() &&
     774             :         "Symbol must already have been defined in executePostLayoutBinding!");
     775        3164 :     Reloc.Symb = SymbolMap[&A];
     776             :   }
     777             : 
     778        2352 :   ++Reloc.Symb->Relocations;
     779             : 
     780        2352 :   Reloc.Data.VirtualAddress += Fixup.getOffset();
     781        2352 :   Reloc.Data.Type = TargetObjectWriter->getRelocType(
     782        2352 :       Asm.getContext(), Target, Fixup, SymB, Asm.getBackend());
     783             : 
     784             :   // FIXME: Can anyone explain what this does other than adjust for the size
     785             :   // of the offset?
     786        2351 :   if ((Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 &&
     787        2111 :        Reloc.Data.Type == COFF::IMAGE_REL_AMD64_REL32) ||
     788         821 :       (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386 &&
     789             :        Reloc.Data.Type == COFF::IMAGE_REL_I386_REL32))
     790         340 :     FixedValue += 4;
     791             : 
     792        2351 :   if (Header.Machine == COFF::IMAGE_FILE_MACHINE_ARMNT) {
     793             :     switch (Reloc.Data.Type) {
     794             :     case COFF::IMAGE_REL_ARM_ABSOLUTE:
     795             :     case COFF::IMAGE_REL_ARM_ADDR32:
     796             :     case COFF::IMAGE_REL_ARM_ADDR32NB:
     797             :     case COFF::IMAGE_REL_ARM_TOKEN:
     798             :     case COFF::IMAGE_REL_ARM_SECTION:
     799             :     case COFF::IMAGE_REL_ARM_SECREL:
     800             :       break;
     801           0 :     case COFF::IMAGE_REL_ARM_BRANCH11:
     802             :     case COFF::IMAGE_REL_ARM_BLX11:
     803             :     // IMAGE_REL_ARM_BRANCH11 and IMAGE_REL_ARM_BLX11 are only used for
     804             :     // pre-ARMv7, which implicitly rules it out of ARMNT (it would be valid
     805             :     // for Windows CE).
     806             :     case COFF::IMAGE_REL_ARM_BRANCH24:
     807             :     case COFF::IMAGE_REL_ARM_BLX24:
     808             :     case COFF::IMAGE_REL_ARM_MOV32A:
     809             :       // IMAGE_REL_ARM_BRANCH24, IMAGE_REL_ARM_BLX24, IMAGE_REL_ARM_MOV32A are
     810             :       // only used for ARM mode code, which is documented as being unsupported
     811             :       // by Windows on ARM.  Empirical proof indicates that masm is able to
     812             :       // generate the relocations however the rest of the MSVC toolchain is
     813             :       // unable to handle it.
     814           0 :       llvm_unreachable("unsupported relocation");
     815             :       break;
     816             :     case COFF::IMAGE_REL_ARM_MOV32T:
     817             :       break;
     818           9 :     case COFF::IMAGE_REL_ARM_BRANCH20T:
     819             :     case COFF::IMAGE_REL_ARM_BRANCH24T:
     820             :     case COFF::IMAGE_REL_ARM_BLX23T:
     821             :       // IMAGE_REL_BRANCH20T, IMAGE_REL_ARM_BRANCH24T, IMAGE_REL_ARM_BLX23T all
     822             :       // perform a 4 byte adjustment to the relocation.  Relative branches are
     823             :       // offset by 4 on ARM, however, because there is no RELA relocations, all
     824             :       // branches are offset by 4.
     825           9 :       FixedValue = FixedValue + 4;
     826           9 :       break;
     827             :     }
     828             :   }
     829             : 
     830             :   // The fixed value never makes sense for section indices, ignore it.
     831        2351 :   if (Fixup.getKind() == FK_SecRel_2)
     832         517 :     FixedValue = 0;
     833             : 
     834        2351 :   if (TargetObjectWriter->recordRelocation(Fixup))
     835        2340 :     Sec->Relocations.push_back(Reloc);
     836             : }
     837             : 
     838             : static std::time_t getTime() {
     839          20 :   std::time_t Now = time(nullptr);
     840          20 :   if (Now < 0 || !isUInt<32>(Now))
     841             :     return UINT32_MAX;
     842             :   return Now;
     843             : }
     844             : 
     845             : // Create .file symbols.
     846         374 : void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
     847         410 :   for (const std::string &Name : Asm.getFileNames()) {
     848             :     // round up to calculate the number of auxiliary symbols required
     849          18 :     unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
     850          18 :     unsigned Count = (Name.size() + SymbolSize - 1) / SymbolSize;
     851             : 
     852          18 :     COFFSymbol *File = createSymbol(".file");
     853          18 :     File->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG;
     854          18 :     File->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
     855          18 :     File->Aux.resize(Count);
     856             : 
     857             :     unsigned Offset = 0;
     858          18 :     unsigned Length = Name.size();
     859          36 :     for (auto &Aux : File->Aux) {
     860          27 :       Aux.AuxType = ATFile;
     861             : 
     862          27 :       if (Length > SymbolSize) {
     863           9 :         memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize);
     864           9 :         Length = Length - SymbolSize;
     865             :       } else {
     866          36 :         memcpy(&Aux.Aux, Name.c_str() + Offset, Length);
     867          18 :         memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length);
     868          18 :         break;
     869             :       }
     870             : 
     871           9 :       Offset += SymbolSize;
     872             :     }
     873             :   }
     874         374 : }
     875             : 
     876             : static bool isAssociative(const COFFSection &Section) {
     877        4138 :   return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection ==
     878             :          COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
     879             : }
     880             : 
     881         374 : void WinCOFFObjectWriter::assignSectionNumbers() {
     882         374 :   size_t I = 1;
     883             :   auto Assign = [&](COFFSection &Section) {
     884        2069 :     Section.Number = I;
     885        2069 :     Section.Symbol->Data.SectionNumber = I;
     886        4138 :     Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I;
     887        2069 :     ++I;
     888             :   };
     889             : 
     890             :   // Although it is not explicitly requested by the Microsoft COFF spec,
     891             :   // we should avoid emitting forward associative section references,
     892             :   // because MSVC link.exe as of 2017 cannot handle that.
     893        2443 :   for (const std::unique_ptr<COFFSection> &Section : Sections)
     894        4138 :     if (!isAssociative(*Section))
     895             :       Assign(*Section);
     896        2443 :   for (const std::unique_ptr<COFFSection> &Section : Sections)
     897        4138 :     if (isAssociative(*Section))
     898             :       Assign(*Section);
     899         374 : }
     900             : 
     901             : // Assign file offsets to COFF object file structures.
     902         374 : void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
     903             :                                             const MCAsmLayout &Layout) {
     904         748 :   unsigned Offset = W.OS.tell();
     905             : 
     906         374 :   Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size;
     907         374 :   Offset += COFF::SectionSize * Header.NumberOfSections;
     908             : 
     909        2443 :   for (const auto &Section : Asm) {
     910        4138 :     COFFSection *Sec = SectionMap[&Section];
     911             : 
     912        2069 :     if (Sec->Number == -1)
     913           0 :       continue;
     914             : 
     915        2069 :     Sec->Header.SizeOfRawData = Layout.getSectionAddressSize(&Section);
     916             : 
     917        4138 :     if (IsPhysicalSection(Sec)) {
     918             :       // Align the section data to a four byte boundary.
     919        3382 :       Offset = alignTo(Offset, 4);
     920        1691 :       Sec->Header.PointerToRawData = Offset;
     921             : 
     922        1691 :       Offset += Sec->Header.SizeOfRawData;
     923             :     }
     924             : 
     925        2069 :     if (!Sec->Relocations.empty()) {
     926             :       bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
     927             : 
     928         561 :       if (RelocationsOverflow) {
     929             :         // Signal overflow by setting NumberOfRelocations to max value. Actual
     930             :         // size is found in reloc #0. Microsoft tools understand this.
     931           0 :         Sec->Header.NumberOfRelocations = 0xffff;
     932             :       } else {
     933         561 :         Sec->Header.NumberOfRelocations = Sec->Relocations.size();
     934             :       }
     935         561 :       Sec->Header.PointerToRelocations = Offset;
     936             : 
     937         561 :       if (RelocationsOverflow) {
     938             :         // Reloc #0 will contain actual count, so make room for it.
     939           0 :         Offset += COFF::RelocationSize;
     940             :       }
     941             : 
     942         561 :       Offset += COFF::RelocationSize * Sec->Relocations.size();
     943             : 
     944        2901 :       for (auto &Relocation : Sec->Relocations) {
     945             :         assert(Relocation.Symb->getIndex() != -1);
     946        2340 :         Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
     947             :       }
     948             :     }
     949             : 
     950             :     assert(Sec->Symbol->Aux.size() == 1 &&
     951             :            "Section's symbol must have one aux!");
     952        2069 :     AuxSymbol &Aux = Sec->Symbol->Aux[0];
     953             :     assert(Aux.AuxType == ATSectionDefinition &&
     954             :            "Section's symbol's aux symbol must be a Section Definition!");
     955        2069 :     Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
     956        2069 :     Aux.Aux.SectionDefinition.NumberOfRelocations =
     957        2069 :         Sec->Header.NumberOfRelocations;
     958        2069 :     Aux.Aux.SectionDefinition.NumberOfLinenumbers =
     959        2069 :         Sec->Header.NumberOfLineNumbers;
     960             :   }
     961             : 
     962         374 :   Header.PointerToSymbolTable = Offset;
     963         374 : }
     964             : 
     965         374 : uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
     966             :                                           const MCAsmLayout &Layout) {
     967         374 :   uint64_t StartOffset = W.OS.tell();
     968             : 
     969         748 :   if (Sections.size() > INT32_MAX)
     970           0 :     report_fatal_error(
     971             :         "PE COFF object files can't have more than 2147483647 sections");
     972             : 
     973         374 :   UseBigObj = Sections.size() > COFF::MaxNumberOfSections16;
     974         374 :   Header.NumberOfSections = Sections.size();
     975         374 :   Header.NumberOfSymbols = 0;
     976             : 
     977         374 :   assignSectionNumbers();
     978         374 :   createFileSymbols(Asm);
     979             : 
     980        3710 :   for (auto &Symbol : Symbols) {
     981             :     // Update section number & offset for symbols that have them.
     982        3336 :     if (Symbol->Section)
     983        3017 :       Symbol->Data.SectionNumber = Symbol->Section->Number;
     984        3336 :     Symbol->setIndex(Header.NumberOfSymbols++);
     985             :     // Update auxiliary symbol info.
     986        3336 :     Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
     987        3336 :     Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
     988             :   }
     989             : 
     990             :   // Build string table.
     991        2443 :   for (const auto &S : Sections)
     992        2069 :     if (S->Name.size() > COFF::NameSize)
     993         384 :       Strings.add(S->Name);
     994        3710 :   for (const auto &S : Symbols)
     995        3336 :     if (S->Name.size() > COFF::NameSize)
     996         649 :       Strings.add(S->Name);
     997         374 :   Strings.finalize();
     998             : 
     999             :   // Set names.
    1000        2443 :   for (const auto &S : Sections)
    1001        2069 :     SetSectionName(*S);
    1002        3710 :   for (auto &S : Symbols)
    1003        3336 :     SetSymbolName(*S);
    1004             : 
    1005             :   // Fixup weak external references.
    1006        3710 :   for (auto &Symbol : Symbols) {
    1007        3336 :     if (Symbol->Other) {
    1008             :       assert(Symbol->getIndex() != -1);
    1009             :       assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!");
    1010             :       assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
    1011             :              "Symbol's aux symbol must be a Weak External!");
    1012          16 :       Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex();
    1013             :     }
    1014             :   }
    1015             : 
    1016             :   // Fixup associative COMDAT sections.
    1017        2443 :   for (auto &Section : Sections) {
    1018        4138 :     if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
    1019             :         COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
    1020        1953 :       continue;
    1021             : 
    1022         116 :     const MCSectionCOFF &MCSec = *Section->MCSection;
    1023             : 
    1024         116 :     const MCSymbol *COMDAT = MCSec.getCOMDATSymbol();
    1025             :     assert(COMDAT);
    1026         116 :     COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT);
    1027             :     assert(COMDATSymbol);
    1028         116 :     COFFSection *Assoc = COMDATSymbol->Section;
    1029         116 :     if (!Assoc)
    1030           0 :       report_fatal_error(
    1031             :           Twine("Missing associated COMDAT section for section ") +
    1032           0 :           MCSec.getSectionName());
    1033             : 
    1034             :     // Skip this section if the associated section is unused.
    1035         116 :     if (Assoc->Number == -1)
    1036           0 :       continue;
    1037             : 
    1038         232 :     Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
    1039             :   }
    1040             : 
    1041         374 :   assignFileOffsets(Asm, Layout);
    1042             : 
    1043             :   // MS LINK expects to be able to use this timestamp to implement their
    1044             :   // /INCREMENTAL feature.
    1045         374 :   if (Asm.isIncrementalLinkerCompatible()) {
    1046          20 :     Header.TimeDateStamp = getTime();
    1047             :   } else {
    1048             :     // Have deterministic output if /INCREMENTAL isn't needed. Also matches GNU.
    1049         354 :     Header.TimeDateStamp = 0;
    1050             :   }
    1051             : 
    1052             :   // Write it all to disk...
    1053         374 :   WriteFileHeader(Header);
    1054         374 :   writeSectionHeaders();
    1055             : 
    1056             :   // Write section contents.
    1057             :   sections::iterator I = Sections.begin();
    1058             :   sections::iterator IE = Sections.end();
    1059             :   MCAssembler::iterator J = Asm.begin();
    1060             :   MCAssembler::iterator JE = Asm.end();
    1061        2443 :   for (; I != IE && J != JE; ++I, ++J)
    1062        2069 :     writeSection(Asm, Layout, **I, *J);
    1063             : 
    1064             :   assert(W.OS.tell() == Header.PointerToSymbolTable &&
    1065             :          "Header::PointerToSymbolTable is insane!");
    1066             : 
    1067             :   // Write a symbol table.
    1068        3710 :   for (auto &Symbol : Symbols)
    1069        3336 :     if (Symbol->getIndex() != -1)
    1070        3336 :       WriteSymbol(*Symbol);
    1071             : 
    1072             :   // Write a string table, which completes the entire COFF file.
    1073         374 :   Strings.write(W.OS);
    1074             : 
    1075         748 :   return W.OS.tell() - StartOffset;
    1076             : }
    1077             : 
    1078         939 : MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)
    1079         939 :     : Machine(Machine_) {}
    1080             : 
    1081             : // Pin the vtable to this file.
    1082           0 : void MCWinCOFFObjectTargetWriter::anchor() {}
    1083             : 
    1084             : //------------------------------------------------------------------------------
    1085             : // WinCOFFObjectWriter factory function
    1086             : 
    1087         939 : std::unique_ptr<MCObjectWriter> llvm::createWinCOFFObjectWriter(
    1088             :     std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS) {
    1089        1878 :   return llvm::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
    1090             : }

Generated by: LCOV version 1.13