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

Generated by: LCOV version 1.13