WinCOFFObjectWriter.cpp revision 212904
11590Srgrimes//===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===//
21590Srgrimes//
31590Srgrimes//                     The LLVM Compiler Infrastructure
41590Srgrimes//
51590Srgrimes// This file is distributed under the University of Illinois Open Source
61590Srgrimes// License. See LICENSE.TXT for details.
71590Srgrimes//
81590Srgrimes//===----------------------------------------------------------------------===//
91590Srgrimes//
101590Srgrimes// This file contains an implementation of a Win32 COFF object file writer.
111590Srgrimes//
121590Srgrimes//===----------------------------------------------------------------------===//
131590Srgrimes
141590Srgrimes#define DEBUG_TYPE "WinCOFFObjectWriter"
151590Srgrimes
161590Srgrimes#include "llvm/MC/MCObjectWriter.h"
171590Srgrimes#include "llvm/MC/MCSection.h"
181590Srgrimes#include "llvm/MC/MCContext.h"
191590Srgrimes#include "llvm/MC/MCSymbol.h"
201590Srgrimes#include "llvm/MC/MCExpr.h"
211590Srgrimes#include "llvm/MC/MCValue.h"
221590Srgrimes#include "llvm/MC/MCAssembler.h"
231590Srgrimes#include "llvm/MC/MCAsmLayout.h"
241590Srgrimes#include "llvm/MC/MCSectionCOFF.h"
251590Srgrimes
261590Srgrimes#include "llvm/ADT/DenseMap.h"
271590Srgrimes#include "llvm/ADT/StringMap.h"
281590Srgrimes#include "llvm/ADT/StringRef.h"
291590Srgrimes
301590Srgrimes#include "llvm/Support/COFF.h"
311590Srgrimes#include "llvm/Support/Debug.h"
321590Srgrimes#include "llvm/Support/ErrorHandling.h"
331590Srgrimes
341590Srgrimes#include "llvm/System/TimeValue.h"
3574769Smikeh
3688150Smikeh#include "../Target/X86/X86FixupKinds.h"
3774769Smikeh
381590Srgrimes#include <cstdio>
3999112Sobrien
4099112Sobrienusing namespace llvm;
411590Srgrimes
421590Srgrimesnamespace {
431590Srgrimestypedef llvm::SmallString<COFF::NameSize> name;
441590Srgrimes
451590Srgrimesenum AuxiliaryType {
461590Srgrimes  ATFunctionDefinition,
471590Srgrimes  ATbfAndefSymbol,
481590Srgrimes  ATWeakExternal,
491590Srgrimes  ATFile,
501590Srgrimes  ATSectionDefinition
511590Srgrimes};
521590Srgrimes
531590Srgrimesstruct AuxSymbol {
541590Srgrimes  AuxiliaryType   AuxType;
551590Srgrimes  COFF::Auxiliary Aux;
561590Srgrimes};
571590Srgrimes
581590Srgrimesclass COFFSymbol {
591590Srgrimespublic:
601590Srgrimes  COFF::symbol Data;
611590Srgrimes
621590Srgrimes  typedef llvm::SmallVector<AuxSymbol, 1> AuxiliarySymbols;
6377274Smikeh
6477274Smikeh  name             Name;
651590Srgrimes  size_t           Index;
661590Srgrimes  AuxiliarySymbols Aux;
671590Srgrimes  COFFSymbol      *Other;
6877274Smikeh
691590Srgrimes  MCSymbolData const *MCData;
701590Srgrimes
7177274Smikeh  COFFSymbol(llvm::StringRef name, size_t index);
721590Srgrimes  size_t size() const;
731590Srgrimes  void set_name_offset(uint32_t Offset);
741590Srgrimes};
751590Srgrimes
761590Srgrimes// This class contains staging data for a COFF relocation entry.
7777274Smikehstruct COFFRelocation {
781590Srgrimes  COFF::relocation Data;
791590Srgrimes  COFFSymbol          *Symb;
801590Srgrimes
811590Srgrimes  COFFRelocation() : Symb(NULL) {}
821590Srgrimes  static size_t size() { return COFF::RelocationSize; }
831590Srgrimes};
841590Srgrimes
851590Srgrimestypedef std::vector<COFFRelocation> relocations;
861590Srgrimes
871590Srgrimesclass COFFSection {
881590Srgrimespublic:
891590Srgrimes  COFF::section Header;
901590Srgrimes
911590Srgrimes  std::string          Name;
921590Srgrimes  size_t               Number;
931590Srgrimes  MCSectionData const *MCData;
941590Srgrimes  COFFSymbol              *Symb;
951590Srgrimes  relocations          Relocations;
961590Srgrimes
971590Srgrimes  COFFSection(llvm::StringRef name, size_t Index);
981590Srgrimes  static size_t size();
991590Srgrimes};
1001590Srgrimes
1011590Srgrimes// This class holds the COFF string table.
1021590Srgrimesclass StringTable {
1031590Srgrimes  typedef llvm::StringMap<size_t> map;
1041590Srgrimes  map Map;
1051590Srgrimes
1061590Srgrimes  void update_length();
10777274Smikehpublic:
10877274Smikeh  std::vector<char> Data;
10977274Smikeh
11077274Smikeh  StringTable();
11177274Smikeh  size_t size() const;
11277274Smikeh  size_t insert(llvm::StringRef String);
1131590Srgrimes};
1141590Srgrimes
1151590Srgrimesclass WinCOFFObjectWriter : public MCObjectWriter {
1161590Srgrimespublic:
1171590Srgrimes
1181590Srgrimes  typedef std::vector<COFFSymbol*>  symbols;
1191590Srgrimes  typedef std::vector<COFFSection*> sections;
1201590Srgrimes
1211590Srgrimes  typedef StringMap<COFFSymbol *>  name_symbol_map;
12277274Smikeh  typedef StringMap<COFFSection *> name_section_map;
12377274Smikeh
12477274Smikeh  typedef DenseMap<MCSymbolData const *, COFFSymbol *>   symbol_map;
1251590Srgrimes  typedef DenseMap<MCSectionData const *, COFFSection *> section_map;
1261590Srgrimes
1271590Srgrimes  // Root level file contents.
1281590Srgrimes  bool Is64Bit;
1291590Srgrimes  COFF::header Header;
1301590Srgrimes  sections     Sections;
1311590Srgrimes  symbols      Symbols;
1321590Srgrimes  StringTable  Strings;
1331590Srgrimes
1341590Srgrimes  // Maps used during object file creation.
1351590Srgrimes  section_map SectionMap;
1361590Srgrimes  symbol_map  SymbolMap;
1371590Srgrimes
1381590Srgrimes  WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit);
1391590Srgrimes  ~WinCOFFObjectWriter();
1401590Srgrimes
1411590Srgrimes  COFFSymbol *createSymbol(llvm::StringRef Name);
1421590Srgrimes  COFFSection *createSection(llvm::StringRef Name);
1431590Srgrimes
1441590Srgrimes  void InitCOFFEntity(COFFSymbol &Symbol);
1451590Srgrimes  void InitCOFFEntity(COFFSection &Section);
14677274Smikeh
1471590Srgrimes  template <typename object_t, typename list_t>
1481590Srgrimes  object_t *createCOFFEntity(llvm::StringRef Name, list_t &List);
1491590Srgrimes
1501590Srgrimes  void DefineSection(MCSectionData const &SectionData);
1511590Srgrimes  void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler);
15277274Smikeh
1531590Srgrimes  bool ExportSection(COFFSection *S);
1541590Srgrimes  bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm);
1551590Srgrimes
1561590Srgrimes  // Entity writing methods.
1571590Srgrimes
1581590Srgrimes  void WriteFileHeader(const COFF::header &Header);
1591590Srgrimes  void WriteSymbol(const COFFSymbol *S);
1601590Srgrimes  void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
16177274Smikeh  void WriteSectionHeader(const COFF::section &S);
1621590Srgrimes  void WriteRelocation(const COFF::relocation &R);
1631590Srgrimes
1641590Srgrimes  // MCObjectWriter interface implementation.
1651590Srgrimes
1661590Srgrimes  void ExecutePostLayoutBinding(MCAssembler &Asm);
1671590Srgrimes
1681590Srgrimes  void RecordRelocation(const MCAssembler &Asm,
1691590Srgrimes                        const MCAsmLayout &Layout,
1701590Srgrimes                        const MCFragment *Fragment,
1711590Srgrimes                        const MCFixup &Fixup,
1721590Srgrimes                        MCValue Target,
17377274Smikeh                        uint64_t &FixedValue);
1741590Srgrimes
1751590Srgrimes  void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout);
1761590Srgrimes};
1771590Srgrimes}
1781590Srgrimes
1791590Srgrimesstatic inline void write_uint32_le(void *Data, uint32_t const &Value) {
18077274Smikeh  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data);
1811590Srgrimes  Ptr[0] = (Value & 0x000000FF) >>  0;
1821590Srgrimes  Ptr[1] = (Value & 0x0000FF00) >>  8;
1831590Srgrimes  Ptr[2] = (Value & 0x00FF0000) >> 16;
1841590Srgrimes  Ptr[3] = (Value & 0xFF000000) >> 24;
1851590Srgrimes}
1861590Srgrimes
1871590Srgrimesstatic inline void write_uint16_le(void *Data, uint16_t const &Value) {
1881590Srgrimes  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data);
1891590Srgrimes  Ptr[0] = (Value & 0x00FF) >> 0;
1901590Srgrimes  Ptr[1] = (Value & 0xFF00) >> 8;
1911590Srgrimes}
1921590Srgrimes
19377274Smikehstatic inline void write_uint8_le(void *Data, uint8_t const &Value) {
1941590Srgrimes  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data);
1951590Srgrimes  Ptr[0] = (Value & 0xFF) >> 0;
1961590Srgrimes}
1971590Srgrimes
1981590Srgrimes//------------------------------------------------------------------------------
1991590Srgrimes// Symbol class implementation
2001590Srgrimes
2011590SrgrimesCOFFSymbol::COFFSymbol(llvm::StringRef name, size_t index)
2021590Srgrimes      : Name(name.begin(), name.end()), Index(-1)
20377274Smikeh      , Other(NULL), MCData(NULL) {
2041590Srgrimes  memset(&Data, 0, sizeof(Data));
2051590Srgrimes}
2061590Srgrimes
2071590Srgrimessize_t COFFSymbol::size() const {
2081590Srgrimes  return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize);
2091590Srgrimes}
2101590Srgrimes
21177274Smikeh// In the case that the name does not fit within 8 bytes, the offset
2121590Srgrimes// into the string table is stored in the last 4 bytes instead, leaving
2131590Srgrimes// the first 4 bytes as 0.
2141590Srgrimesvoid COFFSymbol::set_name_offset(uint32_t Offset) {
2151590Srgrimes  write_uint32_le(Data.Name + 0, 0);
2161590Srgrimes  write_uint32_le(Data.Name + 4, Offset);
2171590Srgrimes}
2181590Srgrimes
2191590Srgrimes//------------------------------------------------------------------------------
2201590Srgrimes// Section class implementation
2211590Srgrimes
2221590SrgrimesCOFFSection::COFFSection(llvm::StringRef name, size_t Index)
2231590Srgrimes       : Name(name), Number(Index + 1)
22477274Smikeh       , MCData(NULL), Symb(NULL) {
2251590Srgrimes  memset(&Header, 0, sizeof(Header));
2261590Srgrimes}
2271590Srgrimes
2281590Srgrimessize_t COFFSection::size() {
2291590Srgrimes  return COFF::SectionSize;
23077274Smikeh}
2311590Srgrimes
2321590Srgrimes//------------------------------------------------------------------------------
2331590Srgrimes// StringTable class implementation
2341590Srgrimes
2351590Srgrimes/// Write the length of the string table into Data.
23677274Smikeh/// The length of the string table includes uint32 length header.
2371590Srgrimesvoid StringTable::update_length() {
2381590Srgrimes  write_uint32_le(&Data.front(), Data.size());
2391590Srgrimes}
2401590Srgrimes
24177274SmikehStringTable::StringTable() {
2421590Srgrimes  // The string table data begins with the length of the entire string table
2431590Srgrimes  // including the length header. Allocate space for this header.
2441590Srgrimes  Data.resize(4);
2451590Srgrimes}
2461590Srgrimes
2471590Srgrimessize_t StringTable::size() const {
2481590Srgrimes  return Data.size();
2491590Srgrimes}
2501590Srgrimes
25177274Smikeh/// Add String to the table iff it is not already there.
2521590Srgrimes/// @returns the index into the string table where the string is now located.
25377274Smikehsize_t StringTable::insert(llvm::StringRef String) {
2541590Srgrimes  map::iterator i = Map.find(String);
2551590Srgrimes
2561590Srgrimes  if (i != Map.end())
2571590Srgrimes    return i->second;
2581590Srgrimes
2591590Srgrimes  size_t Offset = Data.size();
2601590Srgrimes
2611590Srgrimes  // Insert string data into string table.
2621590Srgrimes  Data.insert(Data.end(), String.begin(), String.end());
2631590Srgrimes  Data.push_back('\0');
2641590Srgrimes
2651590Srgrimes  // Put a reference to it in the map.
2661590Srgrimes  Map[String] = Offset;
2671590Srgrimes
2681590Srgrimes  // Update the internal length field.
2691590Srgrimes  update_length();
2701590Srgrimes
2711590Srgrimes  return Offset;
2721590Srgrimes}
2731590Srgrimes
27477274Smikeh//------------------------------------------------------------------------------
2751590Srgrimes// WinCOFFObjectWriter class implementation
27698803Smikeh
2771590SrgrimesWinCOFFObjectWriter::WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit)
2781590Srgrimes  : MCObjectWriter(OS, true)
2791590Srgrimes  , Is64Bit(is64Bit) {
2801590Srgrimes  memset(&Header, 0, sizeof(Header));
2811590Srgrimes
2821590Srgrimes  Is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64
2831590Srgrimes          : Header.Machine = COFF::IMAGE_FILE_MACHINE_I386;
2841590Srgrimes}
2851590Srgrimes
2861590SrgrimesWinCOFFObjectWriter::~WinCOFFObjectWriter() {
2871590Srgrimes  for (symbols::iterator I = Symbols.begin(), E = Symbols.end(); I != E; ++I)
2881590Srgrimes    delete *I;
2891590Srgrimes  for (sections::iterator I = Sections.begin(), E = Sections.end(); I != E; ++I)
2901590Srgrimes    delete *I;
2911590Srgrimes}
2921590Srgrimes
2931590SrgrimesCOFFSymbol *WinCOFFObjectWriter::createSymbol(llvm::StringRef Name) {
2941590Srgrimes  return createCOFFEntity<COFFSymbol>(Name, Symbols);
2951590Srgrimes}
2961590Srgrimes
2971590SrgrimesCOFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) {
2981590Srgrimes  return createCOFFEntity<COFFSection>(Name, Sections);
2991590Srgrimes}
3001590Srgrimes
3011590Srgrimes/// This function initializes a symbol by entering its name into the string
3021590Srgrimes/// table if it is too long to fit in the symbol table header.
3031590Srgrimesvoid WinCOFFObjectWriter::InitCOFFEntity(COFFSymbol &S) {
30477274Smikeh  if (S.Name.size() > COFF::NameSize) {
3051590Srgrimes    size_t StringTableEntry = Strings.insert(S.Name.c_str());
3061590Srgrimes
30777274Smikeh    S.set_name_offset(StringTableEntry);
3081590Srgrimes  } else
3091590Srgrimes    memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
3101590Srgrimes}
3111590Srgrimes
3121590Srgrimes/// This function initializes a section by entering its name into the string
3131590Srgrimes/// table if it is too long to fit in the section table header.
3141590Srgrimesvoid WinCOFFObjectWriter::InitCOFFEntity(COFFSection &S) {
3151590Srgrimes  if (S.Name.size() > COFF::NameSize) {
3161590Srgrimes    size_t StringTableEntry = Strings.insert(S.Name.c_str());
3171590Srgrimes
31877274Smikeh    // FIXME: Why is this number 999999? This number is never mentioned in the
3191590Srgrimes    // spec. I'm assuming this is due to the printed value needing to fit into
3201590Srgrimes    // the S.Header.Name field. In which case why not 9999999 (7 9's instead of
32177274Smikeh    // 6)? The spec does not state if this entry should be null terminated in
3221590Srgrimes    // this case, and thus this seems to be the best way to do it. I think I
3231590Srgrimes    // just solved my own FIXME...
3241590Srgrimes    if (StringTableEntry > 999999)
3251590Srgrimes      report_fatal_error("COFF string table is greater than 999999 bytes.");
3268874Srgrimes
3271590Srgrimes    sprintf(S.Header.Name, "/%d", (unsigned)StringTableEntry);
3281590Srgrimes  } else
3291590Srgrimes    memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
3301590Srgrimes}
3311590Srgrimes
33277274Smikeh/// A template used to lookup or create a symbol/section, and initialize it if
3331590Srgrimes/// needed.
3341590Srgrimestemplate <typename object_t, typename list_t>
33577274Smikehobject_t *WinCOFFObjectWriter::createCOFFEntity(llvm::StringRef Name,
3361590Srgrimes                                                list_t &List) {
3371590Srgrimes  object_t *Object = new object_t(Name, List.size());
3381590Srgrimes
33977274Smikeh  InitCOFFEntity(*Object);
3401590Srgrimes
3411590Srgrimes  List.push_back(Object);
34277274Smikeh
3431590Srgrimes  return Object;
3441590Srgrimes}
3451590Srgrimes
3461590Srgrimes/// This function takes a section data object from the assembler
3471590Srgrimes/// and creates the associated COFF section staging object.
3481590Srgrimesvoid WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) {
3491590Srgrimes  // FIXME: Not sure how to verify this (at least in a debug build).
3501590Srgrimes  MCSectionCOFF const &Sec =
3511590Srgrimes    static_cast<MCSectionCOFF const &>(SectionData.getSection());
3521590Srgrimes
35377274Smikeh  COFFSection *coff_section = createSection(Sec.getSectionName());
3541590Srgrimes  COFFSymbol  *coff_symbol = createSymbol(Sec.getSectionName());
3551590Srgrimes
35677274Smikeh  coff_section->Symb = coff_symbol;
35777274Smikeh  coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
3581590Srgrimes  coff_symbol->Data.SectionNumber = coff_section->Number;
35977274Smikeh
36077274Smikeh  // In this case the auxiliary symbol is a Section Definition.
3611590Srgrimes  coff_symbol->Aux.resize(1);
3621590Srgrimes  memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
3631590Srgrimes  coff_symbol->Aux[0].AuxType = ATSectionDefinition;
3641590Srgrimes  coff_symbol->Aux[0].Aux.SectionDefinition.Number = coff_section->Number;
3651590Srgrimes  coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection();
3661590Srgrimes
3671590Srgrimes  coff_section->Header.Characteristics = Sec.getCharacteristics();
3681590Srgrimes
3691590Srgrimes  uint32_t &Characteristics = coff_section->Header.Characteristics;
3701590Srgrimes  switch (SectionData.getAlignment()) {
3711590Srgrimes  case 1:    Characteristics |= COFF::IMAGE_SCN_ALIGN_1BYTES;    break;
37277274Smikeh  case 2:    Characteristics |= COFF::IMAGE_SCN_ALIGN_2BYTES;    break;
3731590Srgrimes  case 4:    Characteristics |= COFF::IMAGE_SCN_ALIGN_4BYTES;    break;
3741590Srgrimes  case 8:    Characteristics |= COFF::IMAGE_SCN_ALIGN_8BYTES;    break;
3751590Srgrimes  case 16:   Characteristics |= COFF::IMAGE_SCN_ALIGN_16BYTES;   break;
37677274Smikeh  case 32:   Characteristics |= COFF::IMAGE_SCN_ALIGN_32BYTES;   break;
3771590Srgrimes  case 64:   Characteristics |= COFF::IMAGE_SCN_ALIGN_64BYTES;   break;
3781590Srgrimes  case 128:  Characteristics |= COFF::IMAGE_SCN_ALIGN_128BYTES;  break;
3791590Srgrimes  case 256:  Characteristics |= COFF::IMAGE_SCN_ALIGN_256BYTES;  break;
3801590Srgrimes  case 512:  Characteristics |= COFF::IMAGE_SCN_ALIGN_512BYTES;  break;
38177274Smikeh  case 1024: Characteristics |= COFF::IMAGE_SCN_ALIGN_1024BYTES; break;
3821590Srgrimes  case 2048: Characteristics |= COFF::IMAGE_SCN_ALIGN_2048BYTES; break;
38377274Smikeh  case 4096: Characteristics |= COFF::IMAGE_SCN_ALIGN_4096BYTES; break;
3841590Srgrimes  case 8192: Characteristics |= COFF::IMAGE_SCN_ALIGN_8192BYTES; break;
3851590Srgrimes  default:
3861590Srgrimes    llvm_unreachable("unsupported section alignment");
3871590Srgrimes  }
3881590Srgrimes
3891590Srgrimes  // Bind internal COFF section to MC section.
3901590Srgrimes  coff_section->MCData = &SectionData;
3911590Srgrimes  SectionMap[&SectionData] = coff_section;
3921590Srgrimes}
3931590Srgrimes
3941590Srgrimes/// This function takes a section data object from the assembler
3951590Srgrimes/// and creates the associated COFF symbol staging object.
39677274Smikehvoid WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData,
3971590Srgrimes                                        MCAssembler &Assembler) {
39874769Smikeh  COFFSymbol *coff_symbol = createSymbol(SymbolData.getSymbol().getName());
39974769Smikeh
4001590Srgrimes  coff_symbol->Data.Type         = (SymbolData.getFlags() & 0x0000FFFF) >>  0;
40177274Smikeh  coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16;
40274769Smikeh
40374769Smikeh  // If no storage class was specified in the streamer, define it here.
4041590Srgrimes  if (coff_symbol->Data.StorageClass == 0) {
4051590Srgrimes    bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL);
4061590Srgrimes
4071590Srgrimes    coff_symbol->Data.StorageClass =
4081590Srgrimes      external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC;
4091590Srgrimes  }
4101590Srgrimes
4111590Srgrimes  if (SymbolData.getFlags() & COFF::SF_WeakReference) {
4121590Srgrimes    coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
4131590Srgrimes
4141590Srgrimes    const MCExpr *Value = SymbolData.getSymbol().getVariableValue();
4151590Srgrimes
4161590Srgrimes    // FIXME: This assert message isn't very good.
4171590Srgrimes    assert(Value->getKind() == MCExpr::SymbolRef &&
4181590Srgrimes           "Value must be a SymbolRef!");
41974769Smikeh
42074769Smikeh    const MCSymbolRefExpr *SymbolRef =
42174769Smikeh      static_cast<const MCSymbolRefExpr *>(Value);
42274769Smikeh
42374769Smikeh    const MCSymbolData &OtherSymbolData =
42474769Smikeh      Assembler.getSymbolData(SymbolRef->getSymbol());
42574769Smikeh
4261590Srgrimes    // FIXME: This assert message isn't very good.
4271590Srgrimes    assert(SymbolMap.find(&OtherSymbolData) != SymbolMap.end() &&
4281590Srgrimes           "OtherSymbolData must be in the symbol map!");
4291590Srgrimes
4301590Srgrimes    coff_symbol->Other = SymbolMap[&OtherSymbolData];
4311590Srgrimes
4321590Srgrimes    // Setup the Weak External auxiliary symbol.
4331590Srgrimes    coff_symbol->Aux.resize(1);
4341590Srgrimes    memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
4351590Srgrimes    coff_symbol->Aux[0].AuxType = ATWeakExternal;
4361590Srgrimes    coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
4371590Srgrimes    coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
4381590Srgrimes                                        COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
4391590Srgrimes  }
4401590Srgrimes
4411590Srgrimes  // Bind internal COFF symbol to MC symbol.
4421590Srgrimes  coff_symbol->MCData = &SymbolData;
4431590Srgrimes  SymbolMap[&SymbolData] = coff_symbol;
4441590Srgrimes}
4451590Srgrimes
4461590Srgrimesbool WinCOFFObjectWriter::ExportSection(COFFSection *S) {
4471590Srgrimes  return (S->Header.Characteristics
4481590Srgrimes         & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0;
4491590Srgrimes}
4501590Srgrimes
4511590Srgrimesbool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData,
4521590Srgrimes                                       MCAssembler &Asm) {
4531590Srgrimes  // This doesn't seem to be right. Strings referred to from the .data section
4541590Srgrimes  // need symbols so they can be linked to code in the .text section right?
4551590Srgrimes
4561590Srgrimes  // return Asm.isSymbolLinkerVisible (&SymbolData);
4571590Srgrimes
4581590Srgrimes  // For now, all symbols are exported, the linker will sort it out for us.
4591590Srgrimes  return true;
4601590Srgrimes}
4611590Srgrimes
4621590Srgrimes//------------------------------------------------------------------------------
4631590Srgrimes// entity writing methods
4641590Srgrimes
4651590Srgrimesvoid WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
4661590Srgrimes  WriteLE16(Header.Machine);
4671590Srgrimes  WriteLE16(Header.NumberOfSections);
4681590Srgrimes  WriteLE32(Header.TimeDateStamp);
4691590Srgrimes  WriteLE32(Header.PointerToSymbolTable);
4701590Srgrimes  WriteLE32(Header.NumberOfSymbols);
47177274Smikeh  WriteLE16(Header.SizeOfOptionalHeader);
47277274Smikeh  WriteLE16(Header.Characteristics);
4731590Srgrimes}
4741590Srgrimes
4751590Srgrimesvoid WinCOFFObjectWriter::WriteSymbol(const COFFSymbol *S) {
4761590Srgrimes  WriteBytes(StringRef(S->Data.Name, COFF::NameSize));
4771590Srgrimes  WriteLE32(S->Data.Value);
4781590Srgrimes  WriteLE16(S->Data.SectionNumber);
4791590Srgrimes  WriteLE16(S->Data.Type);
4801590Srgrimes  Write8(S->Data.StorageClass);
4811590Srgrimes  Write8(S->Data.NumberOfAuxSymbols);
4821590Srgrimes  WriteAuxiliarySymbols(S->Aux);
4831590Srgrimes}
4841590Srgrimes
4851590Srgrimesvoid WinCOFFObjectWriter::WriteAuxiliarySymbols(
4861590Srgrimes                                        const COFFSymbol::AuxiliarySymbols &S) {
4871590Srgrimes  for(COFFSymbol::AuxiliarySymbols::const_iterator i = S.begin(), e = S.end();
4881590Srgrimes      i != e; ++i) {
4891590Srgrimes    switch(i->AuxType) {
49077274Smikeh    case ATFunctionDefinition:
49177274Smikeh      WriteLE32(i->Aux.FunctionDefinition.TagIndex);
49277274Smikeh      WriteLE32(i->Aux.FunctionDefinition.TotalSize);
4931590Srgrimes      WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber);
4941590Srgrimes      WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction);
4951590Srgrimes      WriteZeros(sizeof(i->Aux.FunctionDefinition.unused));
4961590Srgrimes      break;
4971590Srgrimes    case ATbfAndefSymbol:
4981590Srgrimes      WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1));
4991590Srgrimes      WriteLE16(i->Aux.bfAndefSymbol.Linenumber);
5001590Srgrimes      WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2));
5011590Srgrimes      WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction);
5021590Srgrimes      WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3));
5031590Srgrimes      break;
5041590Srgrimes    case ATWeakExternal:
5051590Srgrimes      WriteLE32(i->Aux.WeakExternal.TagIndex);
50677274Smikeh      WriteLE32(i->Aux.WeakExternal.Characteristics);
50777274Smikeh      WriteZeros(sizeof(i->Aux.WeakExternal.unused));
50877274Smikeh      break;
50977274Smikeh    case ATFile:
51077274Smikeh      WriteBytes(StringRef(reinterpret_cast<const char *>(i->Aux.File.FileName),
51177274Smikeh                 sizeof(i->Aux.File.FileName)));
51277274Smikeh      break;
51377274Smikeh    case ATSectionDefinition:
51477274Smikeh      WriteLE32(i->Aux.SectionDefinition.Length);
5151590Srgrimes      WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations);
5161590Srgrimes      WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers);
5171590Srgrimes      WriteLE32(i->Aux.SectionDefinition.CheckSum);
5181590Srgrimes      WriteLE16(i->Aux.SectionDefinition.Number);
5191590Srgrimes      Write8(i->Aux.SectionDefinition.Selection);
5201590Srgrimes      WriteZeros(sizeof(i->Aux.SectionDefinition.unused));
52177274Smikeh      break;
52277274Smikeh    }
52377274Smikeh  }
5241590Srgrimes}
5251590Srgrimes
5261590Srgrimesvoid WinCOFFObjectWriter::WriteSectionHeader(const COFF::section &S) {
5271590Srgrimes  WriteBytes(StringRef(S.Name, COFF::NameSize));
5281590Srgrimes
52977274Smikeh  WriteLE32(S.VirtualSize);
5301590Srgrimes  WriteLE32(S.VirtualAddress);
5311590Srgrimes  WriteLE32(S.SizeOfRawData);
5321590Srgrimes  WriteLE32(S.PointerToRawData);
5331590Srgrimes  WriteLE32(S.PointerToRelocations);
5341590Srgrimes  WriteLE32(S.PointerToLineNumbers);
5351590Srgrimes  WriteLE16(S.NumberOfRelocations);
5361590Srgrimes  WriteLE16(S.NumberOfLineNumbers);
5371590Srgrimes  WriteLE32(S.Characteristics);
5381590Srgrimes}
5391590Srgrimes
5401590Srgrimesvoid WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
5411590Srgrimes  WriteLE32(R.VirtualAddress);
5421590Srgrimes  WriteLE32(R.SymbolTableIndex);
5431590Srgrimes  WriteLE16(R.Type);
5441590Srgrimes}
5451590Srgrimes
5461590Srgrimes////////////////////////////////////////////////////////////////////////////////
5471590Srgrimes// MCObjectWriter interface implementations
5481590Srgrimes
54977274Smikehvoid WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) {
5501590Srgrimes  // "Define" each section & symbol. This creates section & symbol
5511590Srgrimes  // entries in the staging area and gives them their final indexes.
5521590Srgrimes
5531590Srgrimes  for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++)
5541590Srgrimes    DefineSection(*i);
5551590Srgrimes
5561590Srgrimes  for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(),
5571590Srgrimes                                          e = Asm.symbol_end(); i != e; i++) {
55888227Sache    if (ExportSymbol(*i, Asm))
5591590Srgrimes      DefineSymbol(*i, Asm);
56088227Sache  }
5611590Srgrimes}
5621590Srgrimes
5631590Srgrimesvoid WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
5641590Srgrimes                                           const MCAsmLayout &Layout,
5651590Srgrimes                                           const MCFragment *Fragment,
5661590Srgrimes                                           const MCFixup &Fixup,
56777274Smikeh                                           MCValue Target,
5681590Srgrimes                                           uint64_t &FixedValue) {
5691590Srgrimes  assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");
5701590Srgrimes
5711590Srgrimes  const MCSymbol *A = &Target.getSymA()->getSymbol();
5721590Srgrimes  MCSymbolData &A_SD = Asm.getSymbolData(*A);
5731590Srgrimes
5741590Srgrimes  MCSectionData const *SectionData = Fragment->getParent();
57577274Smikeh
5761590Srgrimes  // Mark this symbol as requiring an entry in the symbol table.
5771590Srgrimes  assert(SectionMap.find(SectionData) != SectionMap.end() &&
5781590Srgrimes         "Section must already have been defined in ExecutePostLayoutBinding!");
5791590Srgrimes  assert(SymbolMap.find(&A_SD) != SymbolMap.end() &&
58077274Smikeh         "Symbol must already have been defined in ExecutePostLayoutBinding!");
5811590Srgrimes
5821590Srgrimes  COFFSection *coff_section = SectionMap[SectionData];
5831590Srgrimes  COFFSymbol *coff_symbol = SymbolMap[&A_SD];
5841590Srgrimes
5851590Srgrimes  if (Target.getSymB()) {
5861590Srgrimes    const MCSymbol *B = &Target.getSymB()->getSymbol();
5871590Srgrimes    MCSymbolData &B_SD = Asm.getSymbolData(*B);
5881590Srgrimes
5891590Srgrimes    FixedValue = Layout.getSymbolAddress(&A_SD) - Layout.getSymbolAddress(&B_SD);
5901590Srgrimes
5911590Srgrimes    // In the case where we have SymbA and SymB, we just need to store the delta
5921590Srgrimes    // between the two symbols.  Update FixedValue to account for the delta, and
5931590Srgrimes    // skip recording the relocation.
5941590Srgrimes    return;
5951590Srgrimes  } else {
5961590Srgrimes    FixedValue = Target.getConstant();
5971590Srgrimes  }
5981590Srgrimes
5991590Srgrimes  COFFRelocation Reloc;
6001590Srgrimes
6011590Srgrimes  Reloc.Data.SymbolTableIndex = 0;
6021590Srgrimes  Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
6031590Srgrimes  Reloc.Symb = coff_symbol;
6041590Srgrimes
6051590Srgrimes  Reloc.Data.VirtualAddress += Fixup.getOffset();
6061590Srgrimes
60777274Smikeh  switch (Fixup.getKind()) {
6081590Srgrimes  case X86::reloc_pcrel_4byte:
60977274Smikeh  case X86::reloc_riprel_4byte:
6101590Srgrimes  case X86::reloc_riprel_4byte_movq_load:
6111590Srgrimes    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_REL32
6121590Srgrimes                              : COFF::IMAGE_REL_I386_REL32;
61377274Smikeh    // FIXME: Can anyone explain what this does other than adjust for the size
6141590Srgrimes    // of the offset?
6151590Srgrimes    FixedValue += 4;
6161590Srgrimes    break;
6171590Srgrimes  case FK_Data_4:
6181590Srgrimes    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32
6191590Srgrimes                              : COFF::IMAGE_REL_I386_DIR32;
6201590Srgrimes    break;
6211590Srgrimes  case FK_Data_8:
6221590Srgrimes    if (Is64Bit)
6231590Srgrimes      Reloc.Data.Type = COFF::IMAGE_REL_AMD64_ADDR64;
62474769Smikeh    else
6251590Srgrimes      llvm_unreachable("unsupported relocation type");
6261590Srgrimes    break;
6271590Srgrimes  default:
6281590Srgrimes    llvm_unreachable("unsupported relocation type");
6291590Srgrimes  }
6301590Srgrimes
6311590Srgrimes  coff_section->Relocations.push_back(Reloc);
6321590Srgrimes}
6331590Srgrimes
6341590Srgrimesvoid WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm,
6351590Srgrimes                                      const MCAsmLayout &Layout) {
6361590Srgrimes  // Assign symbol and section indexes and offsets.
6371590Srgrimes
6381590Srgrimes  Header.NumberOfSymbols = 0;
6391590Srgrimes
6401590Srgrimes  for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) {
6411590Srgrimes    COFFSymbol *coff_symbol = *i;
6421590Srgrimes    MCSymbolData const *SymbolData = coff_symbol->MCData;
6431590Srgrimes
6441590Srgrimes    coff_symbol->Index = Header.NumberOfSymbols++;
6451590Srgrimes
6461590Srgrimes    // Update section number & offset for symbols that have them.
6471590Srgrimes    if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) {
64877274Smikeh      COFFSection *coff_section = SectionMap[SymbolData->Fragment->getParent()];
6491590Srgrimes
6501590Srgrimes      coff_symbol->Data.SectionNumber = coff_section->Number;
65177274Smikeh      coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment)
6521590Srgrimes                              + SymbolData->Offset;
6531590Srgrimes    }
6541590Srgrimes
6551590Srgrimes    // Update auxiliary symbol info.
65677274Smikeh    coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size();
6571590Srgrimes    Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols;
6581590Srgrimes  }
65977274Smikeh
66077274Smikeh  // Fixup weak external references.
6611590Srgrimes  for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) {
6621590Srgrimes    COFFSymbol *symb = *i;
6631590Srgrimes
6641590Srgrimes    if (symb->Other != NULL) {
6651590Srgrimes      assert(symb->Aux.size() == 1 &&
6661590Srgrimes             "Symbol must contain one aux symbol!");
6671590Srgrimes      assert(symb->Aux[0].AuxType == ATWeakExternal &&
6681590Srgrimes             "Symbol's aux symbol must be a Weak External!");
6691590Srgrimes      symb->Aux[0].Aux.WeakExternal.TagIndex = symb->Other->Index;
6701590Srgrimes    }
6711590Srgrimes  }
67298804Smikeh
6731590Srgrimes  // Assign file offsets to COFF object file structures.
67498804Smikeh
67598804Smikeh  unsigned offset = 0;
67677274Smikeh
67798804Smikeh  offset += COFF::HeaderSize;
67898804Smikeh  offset += COFF::SectionSize * Asm.size();
67998804Smikeh
6801590Srgrimes  Header.NumberOfSections = Sections.size();
6811590Srgrimes
6821590Srgrimes  for (MCAssembler::const_iterator i = Asm.begin(),
68388150Smikeh                                   e = Asm.end();
68488150Smikeh                                   i != e; i++) {
68588150Smikeh    COFFSection *Sec = SectionMap[i];
68688150Smikeh
68788150Smikeh    Sec->Header.SizeOfRawData = Layout.getSectionFileSize(i);
68888150Smikeh
68988150Smikeh    if (ExportSection(Sec)) {
69088150Smikeh      Sec->Header.PointerToRawData = offset;
69188150Smikeh
69288150Smikeh      offset += Sec->Header.SizeOfRawData;
69388150Smikeh    }
69488150Smikeh
69598804Smikeh    if (Sec->Relocations.size() > 0) {
69688150Smikeh      Sec->Header.NumberOfRelocations = Sec->Relocations.size();
69788150Smikeh      Sec->Header.PointerToRelocations = offset;
69888150Smikeh
69988150Smikeh      offset += COFF::RelocationSize * Sec->Relocations.size();
70088150Smikeh
70188150Smikeh      for (relocations::iterator cr = Sec->Relocations.begin(),
70288150Smikeh                                 er = Sec->Relocations.end();
70388150Smikeh                                 cr != er; cr++) {
70488150Smikeh        (*cr).Data.SymbolTableIndex = (*cr).Symb->Index;
70588150Smikeh      }
70698804Smikeh    }
70798804Smikeh
70898804Smikeh    assert(Sec->Symb->Aux.size() == 1 && "Section's symbol must have one aux!");
70988150Smikeh    AuxSymbol &Aux = Sec->Symb->Aux[0];
71088150Smikeh    assert(Aux.AuxType == ATSectionDefinition &&
71188150Smikeh           "Section's symbol's aux symbol must be a Section Definition!");
71288150Smikeh    Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
71388150Smikeh    Aux.Aux.SectionDefinition.NumberOfRelocations =
71498803Smikeh                                                Sec->Header.NumberOfRelocations;
71598803Smikeh    Aux.Aux.SectionDefinition.NumberOfLinenumbers =
71698803Smikeh                                                Sec->Header.NumberOfLineNumbers;
71798803Smikeh  }
71898803Smikeh
71998803Smikeh  Header.PointerToSymbolTable = offset;
72098803Smikeh
72198803Smikeh  Header.TimeDateStamp = sys::TimeValue::now().toEpochTime();
72298803Smikeh
72398803Smikeh  // Write it all to disk...
7241590Srgrimes  WriteFileHeader(Header);
7251590Srgrimes
72674769Smikeh  {
7271590Srgrimes    sections::iterator i, ie;
72898803Smikeh    MCAssembler::const_iterator j, je;
7291590Srgrimes
7301590Srgrimes    for (i = Sections.begin(), ie = Sections.end(); i != ie; i++)
7311590Srgrimes      WriteSectionHeader((*i)->Header);
73277274Smikeh
73398804Smikeh    for (i = Sections.begin(), ie = Sections.end(),
7341590Srgrimes         j = Asm.begin(), je = Asm.end();
7351590Srgrimes         (i != ie) && (j != je); i++, j++) {
73674769Smikeh      if ((*i)->Header.PointerToRawData != 0) {
7371590Srgrimes        assert(OS.tell() == (*i)->Header.PointerToRawData &&
7381590Srgrimes               "Section::PointerToRawData is insane!");
73974769Smikeh
7401590Srgrimes        Asm.WriteSectionData(j, Layout, this);
7418874Srgrimes      }
7421590Srgrimes
7431590Srgrimes      if ((*i)->Relocations.size() > 0) {
7441590Srgrimes        assert(OS.tell() == (*i)->Header.PointerToRelocations &&
7451590Srgrimes               "Section::PointerToRelocations is insane!");
74677274Smikeh
74798803Smikeh        for (relocations::const_iterator k = (*i)->Relocations.begin(),
74898803Smikeh                                               ke = (*i)->Relocations.end();
74988150Smikeh                                               k != ke; k++) {
7501590Srgrimes          WriteRelocation(k->Data);
75188150Smikeh        }
7521590Srgrimes      } else
7531590Srgrimes        assert((*i)->Header.PointerToRelocations == 0 &&
75498804Smikeh               "Section::PointerToRelocations is insane!");
75598804Smikeh    }
75698804Smikeh  }
75798804Smikeh
75898804Smikeh  assert(OS.tell() == Header.PointerToSymbolTable &&
75977274Smikeh         "Header::PointerToSymbolTable is insane!");
76098804Smikeh
76198804Smikeh  for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++)
7621590Srgrimes    WriteSymbol(*i);
7631590Srgrimes
7641590Srgrimes  OS.write((char const *)&Strings.Data.front(), Strings.Data.size());
7651590Srgrimes}
7661590Srgrimes
7671590Srgrimes//------------------------------------------------------------------------------
7681590Srgrimes// WinCOFFObjectWriter factory function
7691590Srgrimes
7701590Srgrimesnamespace llvm {
77177274Smikeh  MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit) {
7721590Srgrimes    return new WinCOFFObjectWriter(OS, is64Bit);
7731590Srgrimes  }
7741590Srgrimes}
77574769Smikeh