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