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

Generated by: LCOV version 1.13