WinCOFFObjectWriter.cpp revision da0bfcdaf95d95a66e306ef6d45f638939272d34
1//===-- llvm/MC/WinCOFFObjectWriter.cpp -------------------------*- C++ -*-===// 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#define DEBUG_TYPE "WinCOFFObjectWriter" 15 16#include "llvm/MC/MCObjectWriter.h" 17#include "llvm/MC/MCSection.h" 18#include "llvm/MC/MCContext.h" 19#include "llvm/MC/MCSymbol.h" 20#include "llvm/MC/MCExpr.h" 21#include "llvm/MC/MCValue.h" 22#include "llvm/MC/MCAssembler.h" 23#include "llvm/MC/MCAsmLayout.h" 24#include "llvm/MC/MCSectionCOFF.h" 25 26#include "llvm/ADT/DenseMap.h" 27#include "llvm/ADT/StringMap.h" 28#include "llvm/ADT/StringRef.h" 29 30#include "llvm/Support/COFF.h" 31#include "llvm/Support/Debug.h" 32#include "llvm/Support/ErrorHandling.h" 33 34#include "llvm/System/TimeValue.h" 35 36#include "../Target/X86/X86FixupKinds.h" 37 38#include <cstdio> 39 40using namespace llvm; 41 42namespace { 43typedef llvm::SmallString<COFF::NameSize> name; 44 45enum AuxiliaryType { 46 ATFunctionDefinition, 47 ATbfAndefSymbol, 48 ATWeakExternal, 49 ATFile, 50 ATSectionDefinition 51}; 52 53struct AuxSymbol { 54 AuxiliaryType AuxType; 55 COFF::Auxiliary Aux; 56}; 57 58class COFFSymbol { 59public: 60 COFF::symbol Data; 61 62 typedef llvm::SmallVector<AuxSymbol, 1> AuxiliarySymbols; 63 64 name Name; 65 size_t Index; 66 AuxiliarySymbols Aux; 67 COFFSymbol *Other; 68 69 MCSymbolData const *MCData; 70 71 COFFSymbol(llvm::StringRef name, size_t index); 72 size_t size() const; 73 void set_name_offset(uint32_t Offset); 74}; 75 76// This class contains staging data for a COFF relocation entry. 77struct COFFRelocation { 78 COFF::relocation Data; 79 COFFSymbol *Symb; 80 81 COFFRelocation() : Symb(NULL) {} 82 static size_t size() { return COFF::RelocationSize; } 83}; 84 85typedef std::vector<COFFRelocation> relocations; 86 87class COFFSection { 88public: 89 COFF::section Header; 90 91 std::string Name; 92 size_t Number; 93 MCSectionData const *MCData; 94 COFFSymbol *Symb; 95 relocations Relocations; 96 97 COFFSection(llvm::StringRef name, size_t Index); 98 static size_t size(); 99}; 100 101// This class holds the COFF string table. 102class StringTable { 103 typedef llvm::StringMap<size_t> map; 104 map Map; 105 106 void update_length(); 107public: 108 std::vector<char> Data; 109 110 StringTable(); 111 size_t size() const; 112 size_t insert(llvm::StringRef String); 113}; 114 115class WinCOFFObjectWriter : public MCObjectWriter { 116public: 117 118 typedef std::vector<COFFSymbol*> symbols; 119 typedef std::vector<COFFSection*> sections; 120 121 typedef StringMap<COFFSymbol *> name_symbol_map; 122 typedef StringMap<COFFSection *> name_section_map; 123 124 typedef DenseMap<MCSymbolData const *, COFFSymbol *> symbol_map; 125 typedef DenseMap<MCSectionData const *, COFFSection *> section_map; 126 127 // Root level file contents. 128 COFF::header Header; 129 sections Sections; 130 symbols Symbols; 131 StringTable Strings; 132 133 // Maps used during object file creation. 134 section_map SectionMap; 135 symbol_map SymbolMap; 136 137 WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit); 138 ~WinCOFFObjectWriter(); 139 140 COFFSymbol *createSymbol(llvm::StringRef Name); 141 COFFSection *createSection(llvm::StringRef Name); 142 143 void InitCOFFEntity(COFFSymbol &Symbol); 144 void InitCOFFEntity(COFFSection &Section); 145 146 template <typename object_t, typename list_t> 147 object_t *createCOFFEntity(llvm::StringRef Name, list_t &List); 148 149 void DefineSection(MCSectionData const &SectionData); 150 void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler); 151 152 bool ExportSection(COFFSection *S); 153 bool ExportSymbol(MCSymbolData const &SymbolData, MCAssembler &Asm); 154 155 // Entity writing methods. 156 157 void WriteFileHeader(const COFF::header &Header); 158 void WriteSymbol(const COFFSymbol *S); 159 void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); 160 void WriteSectionHeader(const COFF::section &S); 161 void WriteRelocation(const COFF::relocation &R); 162 163 // MCObjectWriter interface implementation. 164 165 void ExecutePostLayoutBinding(MCAssembler &Asm); 166 167 void RecordRelocation(const MCAssembler &Asm, 168 const MCAsmLayout &Layout, 169 const MCFragment *Fragment, 170 const MCFixup &Fixup, 171 MCValue Target, 172 uint64_t &FixedValue); 173 174 void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); 175}; 176} 177 178static inline void write_uint32_le(void *Data, uint32_t const &Value) { 179 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data); 180 Ptr[0] = (Value & 0x000000FF) >> 0; 181 Ptr[1] = (Value & 0x0000FF00) >> 8; 182 Ptr[2] = (Value & 0x00FF0000) >> 16; 183 Ptr[3] = (Value & 0xFF000000) >> 24; 184} 185 186static inline void write_uint16_le(void *Data, uint16_t const &Value) { 187 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data); 188 Ptr[0] = (Value & 0x00FF) >> 0; 189 Ptr[1] = (Value & 0xFF00) >> 8; 190} 191 192static inline void write_uint8_le(void *Data, uint8_t const &Value) { 193 uint8_t *Ptr = reinterpret_cast<uint8_t *>(Data); 194 Ptr[0] = (Value & 0xFF) >> 0; 195} 196 197//------------------------------------------------------------------------------ 198// Symbol class implementation 199 200COFFSymbol::COFFSymbol(llvm::StringRef name, size_t index) 201 : Name(name.begin(), name.end()), Index(-1) 202 , Other(NULL), MCData(NULL) { 203 memset(&Data, 0, sizeof(Data)); 204} 205 206size_t COFFSymbol::size() const { 207 return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize); 208} 209 210// In the case that the name does not fit within 8 bytes, the offset 211// into the string table is stored in the last 4 bytes instead, leaving 212// the first 4 bytes as 0. 213void COFFSymbol::set_name_offset(uint32_t Offset) { 214 write_uint32_le(Data.Name + 0, 0); 215 write_uint32_le(Data.Name + 4, Offset); 216} 217 218//------------------------------------------------------------------------------ 219// Section class implementation 220 221COFFSection::COFFSection(llvm::StringRef name, size_t Index) 222 : Name(name), Number(Index + 1) 223 , MCData(NULL), Symb(NULL) { 224 memset(&Header, 0, sizeof(Header)); 225} 226 227size_t COFFSection::size() { 228 return COFF::SectionSize; 229} 230 231//------------------------------------------------------------------------------ 232// StringTable class implementation 233 234/// Write the length of the string table into Data. 235/// The length of the string table includes uint32 length header. 236void StringTable::update_length() { 237 write_uint32_le(&Data.front(), Data.size()); 238} 239 240StringTable::StringTable() { 241 // The string table data begins with the length of the entire string table 242 // including the length header. Allocate space for this header. 243 Data.resize(4); 244} 245 246size_t StringTable::size() const { 247 return Data.size(); 248} 249 250/// Add String to the table iff it is not already there. 251/// @returns the index into the string table where the string is now located. 252size_t StringTable::insert(llvm::StringRef String) { 253 map::iterator i = Map.find(String); 254 255 if (i != Map.end()) 256 return i->second; 257 258 size_t Offset = Data.size(); 259 260 // Insert string data into string table. 261 Data.insert(Data.end(), String.begin(), String.end()); 262 Data.push_back('\0'); 263 264 // Put a reference to it in the map. 265 Map[String] = Offset; 266 267 // Update the internal length field. 268 update_length(); 269 270 return Offset; 271} 272 273//------------------------------------------------------------------------------ 274// WinCOFFObjectWriter class implementation 275 276WinCOFFObjectWriter::WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit) 277 : MCObjectWriter(OS, true) { 278 memset(&Header, 0, sizeof(Header)); 279 280 is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64 281 : Header.Machine = COFF::IMAGE_FILE_MACHINE_I386; 282} 283 284WinCOFFObjectWriter::~WinCOFFObjectWriter() { 285 for (symbols::iterator I = Symbols.begin(), E = Symbols.end(); I != E; ++I) 286 delete *I; 287 for (sections::iterator I = Sections.begin(), E = Sections.end(); I != E; ++I) 288 delete *I; 289} 290 291COFFSymbol *WinCOFFObjectWriter::createSymbol(llvm::StringRef Name) { 292 return createCOFFEntity<COFFSymbol>(Name, Symbols); 293} 294 295COFFSection *WinCOFFObjectWriter::createSection(llvm::StringRef Name) { 296 return createCOFFEntity<COFFSection>(Name, Sections); 297} 298 299/// This function initializes a symbol by entering its name into the string 300/// table if it is too long to fit in the symbol table header. 301void WinCOFFObjectWriter::InitCOFFEntity(COFFSymbol &S) { 302 if (S.Name.size() > COFF::NameSize) { 303 size_t StringTableEntry = Strings.insert(S.Name.c_str()); 304 305 S.set_name_offset(StringTableEntry); 306 } else 307 memcpy(S.Data.Name, S.Name.c_str(), S.Name.size()); 308} 309 310/// This function initializes a section by entering its name into the string 311/// table if it is too long to fit in the section table header. 312void WinCOFFObjectWriter::InitCOFFEntity(COFFSection &S) { 313 if (S.Name.size() > COFF::NameSize) { 314 size_t StringTableEntry = Strings.insert(S.Name.c_str()); 315 316 // FIXME: Why is this number 999999? This number is never mentioned in the 317 // spec. I'm assuming this is due to the printed value needing to fit into 318 // the S.Header.Name field. In which case why not 9999999 (7 9's instead of 319 // 6)? The spec does not state if this entry should be null terminated in 320 // this case, and thus this seems to be the best way to do it. I think I 321 // just solved my own FIXME... 322 if (StringTableEntry > 999999) 323 report_fatal_error("COFF string table is greater than 999999 bytes."); 324 325 sprintf(S.Header.Name, "/%d", (unsigned)StringTableEntry); 326 } else 327 memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); 328} 329 330/// A template used to lookup or create a symbol/section, and initialize it if 331/// needed. 332template <typename object_t, typename list_t> 333object_t *WinCOFFObjectWriter::createCOFFEntity(llvm::StringRef Name, 334 list_t &List) { 335 object_t *Object = new object_t(Name, List.size()); 336 337 InitCOFFEntity(*Object); 338 339 List.push_back(Object); 340 341 return Object; 342} 343 344/// This function takes a section data object from the assembler 345/// and creates the associated COFF section staging object. 346void WinCOFFObjectWriter::DefineSection(MCSectionData const &SectionData) { 347 // FIXME: Not sure how to verify this (at least in a debug build). 348 MCSectionCOFF const &Sec = 349 static_cast<MCSectionCOFF const &>(SectionData.getSection()); 350 351 COFFSection *coff_section = createSection(Sec.getSectionName()); 352 COFFSymbol *coff_symbol = createSymbol(Sec.getSectionName()); 353 354 coff_section->Symb = coff_symbol; 355 coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_STATIC; 356 coff_symbol->Data.SectionNumber = coff_section->Number; 357 358 // In this case the auxiliary symbol is a Section Definition. 359 coff_symbol->Aux.resize(1); 360 memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); 361 coff_symbol->Aux[0].AuxType = ATSectionDefinition; 362 coff_symbol->Aux[0].Aux.SectionDefinition.Number = coff_section->Number; 363 coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.getSelection(); 364 365 coff_section->Header.Characteristics = Sec.getCharacteristics(); 366 367 uint32_t &Characteristics = coff_section->Header.Characteristics; 368 switch (SectionData.getAlignment()) { 369 case 1: Characteristics |= COFF::IMAGE_SCN_ALIGN_1BYTES; break; 370 case 2: Characteristics |= COFF::IMAGE_SCN_ALIGN_2BYTES; break; 371 case 4: Characteristics |= COFF::IMAGE_SCN_ALIGN_4BYTES; break; 372 case 8: Characteristics |= COFF::IMAGE_SCN_ALIGN_8BYTES; break; 373 case 16: Characteristics |= COFF::IMAGE_SCN_ALIGN_16BYTES; break; 374 case 32: Characteristics |= COFF::IMAGE_SCN_ALIGN_32BYTES; break; 375 case 64: Characteristics |= COFF::IMAGE_SCN_ALIGN_64BYTES; break; 376 case 128: Characteristics |= COFF::IMAGE_SCN_ALIGN_128BYTES; break; 377 case 256: Characteristics |= COFF::IMAGE_SCN_ALIGN_256BYTES; break; 378 case 512: Characteristics |= COFF::IMAGE_SCN_ALIGN_512BYTES; break; 379 case 1024: Characteristics |= COFF::IMAGE_SCN_ALIGN_1024BYTES; break; 380 case 2048: Characteristics |= COFF::IMAGE_SCN_ALIGN_2048BYTES; break; 381 case 4096: Characteristics |= COFF::IMAGE_SCN_ALIGN_4096BYTES; break; 382 case 8192: Characteristics |= COFF::IMAGE_SCN_ALIGN_8192BYTES; break; 383 default: 384 llvm_unreachable("unsupported section alignment"); 385 } 386 387 // Bind internal COFF section to MC section. 388 coff_section->MCData = &SectionData; 389 SectionMap[&SectionData] = coff_section; 390} 391 392/// This function takes a section data object from the assembler 393/// and creates the associated COFF symbol staging object. 394void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, 395 MCAssembler &Assembler) { 396 COFFSymbol *coff_symbol = createSymbol(SymbolData.getSymbol().getName()); 397 398 coff_symbol->Data.Type = (SymbolData.getFlags() & 0x0000FFFF) >> 0; 399 coff_symbol->Data.StorageClass = (SymbolData.getFlags() & 0x00FF0000) >> 16; 400 401 // If no storage class was specified in the streamer, define it here. 402 if (coff_symbol->Data.StorageClass == 0) { 403 bool external = SymbolData.isExternal() || (SymbolData.Fragment == NULL); 404 405 coff_symbol->Data.StorageClass = 406 external ? COFF::IMAGE_SYM_CLASS_EXTERNAL : COFF::IMAGE_SYM_CLASS_STATIC; 407 } 408 409 if (SymbolData.getFlags() & COFF::SF_WeakReference) { 410 coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; 411 412 const MCExpr *Value = SymbolData.getSymbol().getVariableValue(); 413 414 // FIXME: This assert message isn't very good. 415 assert(Value->getKind() == MCExpr::SymbolRef && 416 "Value must be a SymbolRef!"); 417 418 const MCSymbolRefExpr *SymbolRef = 419 static_cast<const MCSymbolRefExpr *>(Value); 420 421 const MCSymbolData &OtherSymbolData = 422 Assembler.getSymbolData(SymbolRef->getSymbol()); 423 424 // FIXME: This assert message isn't very good. 425 assert(SymbolMap.find(&OtherSymbolData) != SymbolMap.end() && 426 "OtherSymbolData must be in the symbol map!"); 427 428 coff_symbol->Other = SymbolMap[&OtherSymbolData]; 429 430 // Setup the Weak External auxiliary symbol. 431 coff_symbol->Aux.resize(1); 432 memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0])); 433 coff_symbol->Aux[0].AuxType = ATWeakExternal; 434 coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0; 435 coff_symbol->Aux[0].Aux.WeakExternal.Characteristics = 436 COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY; 437 } 438 439 // Bind internal COFF symbol to MC symbol. 440 coff_symbol->MCData = &SymbolData; 441 SymbolMap[&SymbolData] = coff_symbol; 442} 443 444bool WinCOFFObjectWriter::ExportSection(COFFSection *S) { 445 return (S->Header.Characteristics 446 & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0; 447} 448 449bool WinCOFFObjectWriter::ExportSymbol(MCSymbolData const &SymbolData, 450 MCAssembler &Asm) { 451 // This doesn't seem to be right. Strings referred to from the .data section 452 // need symbols so they can be linked to code in the .text section right? 453 454 // return Asm.isSymbolLinkerVisible (&SymbolData); 455 456 // For now, all symbols are exported, the linker will sort it out for us. 457 return true; 458} 459 460//------------------------------------------------------------------------------ 461// entity writing methods 462 463void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) { 464 WriteLE16(Header.Machine); 465 WriteLE16(Header.NumberOfSections); 466 WriteLE32(Header.TimeDateStamp); 467 WriteLE32(Header.PointerToSymbolTable); 468 WriteLE32(Header.NumberOfSymbols); 469 WriteLE16(Header.SizeOfOptionalHeader); 470 WriteLE16(Header.Characteristics); 471} 472 473void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol *S) { 474 WriteBytes(StringRef(S->Data.Name, COFF::NameSize)); 475 WriteLE32(S->Data.Value); 476 WriteLE16(S->Data.SectionNumber); 477 WriteLE16(S->Data.Type); 478 Write8(S->Data.StorageClass); 479 Write8(S->Data.NumberOfAuxSymbols); 480 WriteAuxiliarySymbols(S->Aux); 481} 482 483void WinCOFFObjectWriter::WriteAuxiliarySymbols( 484 const COFFSymbol::AuxiliarySymbols &S) { 485 for(COFFSymbol::AuxiliarySymbols::const_iterator i = S.begin(), e = S.end(); 486 i != e; ++i) { 487 switch(i->AuxType) { 488 case ATFunctionDefinition: 489 WriteLE32(i->Aux.FunctionDefinition.TagIndex); 490 WriteLE32(i->Aux.FunctionDefinition.TotalSize); 491 WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber); 492 WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction); 493 WriteZeros(sizeof(i->Aux.FunctionDefinition.unused)); 494 break; 495 case ATbfAndefSymbol: 496 WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1)); 497 WriteLE16(i->Aux.bfAndefSymbol.Linenumber); 498 WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2)); 499 WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction); 500 WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3)); 501 break; 502 case ATWeakExternal: 503 WriteLE32(i->Aux.WeakExternal.TagIndex); 504 WriteLE32(i->Aux.WeakExternal.Characteristics); 505 WriteZeros(sizeof(i->Aux.WeakExternal.unused)); 506 break; 507 case ATFile: 508 WriteBytes(StringRef(reinterpret_cast<const char *>(i->Aux.File.FileName), 509 sizeof(i->Aux.File.FileName))); 510 break; 511 case ATSectionDefinition: 512 WriteLE32(i->Aux.SectionDefinition.Length); 513 WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations); 514 WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers); 515 WriteLE32(i->Aux.SectionDefinition.CheckSum); 516 WriteLE16(i->Aux.SectionDefinition.Number); 517 Write8(i->Aux.SectionDefinition.Selection); 518 WriteZeros(sizeof(i->Aux.SectionDefinition.unused)); 519 break; 520 } 521 } 522} 523 524void WinCOFFObjectWriter::WriteSectionHeader(const COFF::section &S) { 525 WriteBytes(StringRef(S.Name, COFF::NameSize)); 526 527 WriteLE32(S.VirtualSize); 528 WriteLE32(S.VirtualAddress); 529 WriteLE32(S.SizeOfRawData); 530 WriteLE32(S.PointerToRawData); 531 WriteLE32(S.PointerToRelocations); 532 WriteLE32(S.PointerToLineNumbers); 533 WriteLE16(S.NumberOfRelocations); 534 WriteLE16(S.NumberOfLineNumbers); 535 WriteLE32(S.Characteristics); 536} 537 538void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { 539 WriteLE32(R.VirtualAddress); 540 WriteLE32(R.SymbolTableIndex); 541 WriteLE16(R.Type); 542} 543 544//////////////////////////////////////////////////////////////////////////////// 545// MCObjectWriter interface implementations 546 547void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm) { 548 // "Define" each section & symbol. This creates section & symbol 549 // entries in the staging area and gives them their final indexes. 550 551 for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; i++) 552 DefineSection(*i); 553 554 for (MCAssembler::const_symbol_iterator i = Asm.symbol_begin(), 555 e = Asm.symbol_end(); i != e; i++) { 556 if (ExportSymbol(*i, Asm)) 557 DefineSymbol(*i, Asm); 558 } 559} 560 561void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, 562 const MCAsmLayout &Layout, 563 const MCFragment *Fragment, 564 const MCFixup &Fixup, 565 MCValue Target, 566 uint64_t &FixedValue) { 567 assert(Target.getSymA() != NULL && "Relocation must reference a symbol!"); 568 assert(Target.getSymB() == NULL && 569 "Relocation must reference only one symbol!"); 570 571 MCSectionData const *SectionData = Fragment->getParent(); 572 MCSymbolData const *SymbolData = 573 &Asm.getSymbolData(Target.getSymA()->getSymbol()); 574 575 assert(SectionMap.find(SectionData) != SectionMap.end() && 576 "Section must already have been defined in ExecutePostLayoutBinding!"); 577 assert(SymbolMap.find(SymbolData) != SymbolMap.end() && 578 "Symbol must already have been defined in ExecutePostLayoutBinding!"); 579 580 COFFSection *coff_section = SectionMap[SectionData]; 581 COFFSymbol *coff_symbol = SymbolMap[SymbolData]; 582 583 FixedValue = Target.getConstant(); 584 585 COFFRelocation Reloc; 586 587 Reloc.Data.SymbolTableIndex = 0; 588 Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment); 589 Reloc.Symb = coff_symbol; 590 591 Reloc.Data.VirtualAddress += Fixup.getOffset(); 592 593 COFF::RelocationTypeX86 Type; 594 595 if (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386) { 596 switch (Fixup.getKind()) { 597 case X86::reloc_pcrel_4byte: 598 Type = COFF::IMAGE_REL_I386_REL32; 599 FixedValue += 4; 600 break; 601 case FK_Data_4: 602 Type = COFF::IMAGE_REL_I386_DIR32; 603 break; 604 default: 605 llvm_unreachable("unsupported relocation type"); 606 } 607 } else if (Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64) { 608 switch (Fixup.getKind()) { 609 case FK_Data_8: 610 Type = COFF::IMAGE_REL_AMD64_ADDR64; 611 break; 612 case X86::reloc_pcrel_4byte: 613 case X86::reloc_riprel_4byte: 614 Type = COFF::IMAGE_REL_AMD64_REL32; 615 FixedValue += 4; 616 break; 617 case FK_Data_4: 618 Type = COFF::IMAGE_REL_AMD64_ADDR32; 619 break; 620 default: 621 llvm_unreachable("unsupported relocation type"); 622 } 623 } else 624 llvm_unreachable("unknown target architecture"); 625 626 Reloc.Data.Type = Type; 627 628 coff_section->Relocations.push_back(Reloc); 629} 630 631void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm, 632 const MCAsmLayout &Layout) { 633 // Assign symbol and section indexes and offsets. 634 635 Header.NumberOfSymbols = 0; 636 637 for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { 638 COFFSymbol *coff_symbol = *i; 639 MCSymbolData const *SymbolData = coff_symbol->MCData; 640 641 coff_symbol->Index = Header.NumberOfSymbols++; 642 643 // Update section number & offset for symbols that have them. 644 if ((SymbolData != NULL) && (SymbolData->Fragment != NULL)) { 645 COFFSection *coff_section = SectionMap[SymbolData->Fragment->getParent()]; 646 647 coff_symbol->Data.SectionNumber = coff_section->Number; 648 coff_symbol->Data.Value = Layout.getFragmentOffset(SymbolData->Fragment) 649 + SymbolData->Offset; 650 } 651 652 // Update auxiliary symbol info. 653 coff_symbol->Data.NumberOfAuxSymbols = coff_symbol->Aux.size(); 654 Header.NumberOfSymbols += coff_symbol->Data.NumberOfAuxSymbols; 655 } 656 657 // Fixup weak external references. 658 for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) { 659 COFFSymbol *symb = *i; 660 661 if (symb->Other != NULL) { 662 assert(symb->Aux.size() == 1 && 663 "Symbol must contain one aux symbol!"); 664 assert(symb->Aux[0].AuxType == ATWeakExternal && 665 "Symbol's aux symbol must be a Weak External!"); 666 symb->Aux[0].Aux.WeakExternal.TagIndex = symb->Other->Index; 667 } 668 } 669 670 // Assign file offsets to COFF object file structures. 671 672 unsigned offset = 0; 673 674 offset += COFF::HeaderSize; 675 offset += COFF::SectionSize * Asm.size(); 676 677 Header.NumberOfSections = Sections.size(); 678 679 for (MCAssembler::const_iterator i = Asm.begin(), 680 e = Asm.end(); 681 i != e; i++) { 682 COFFSection *Sec = SectionMap[i]; 683 684 Sec->Header.SizeOfRawData = Layout.getSectionFileSize(i); 685 686 if (ExportSection(Sec)) { 687 Sec->Header.PointerToRawData = offset; 688 689 offset += Sec->Header.SizeOfRawData; 690 } 691 692 if (Sec->Relocations.size() > 0) { 693 Sec->Header.NumberOfRelocations = Sec->Relocations.size(); 694 Sec->Header.PointerToRelocations = offset; 695 696 offset += COFF::RelocationSize * Sec->Relocations.size(); 697 698 for (relocations::iterator cr = Sec->Relocations.begin(), 699 er = Sec->Relocations.end(); 700 cr != er; cr++) { 701 (*cr).Data.SymbolTableIndex = (*cr).Symb->Index; 702 } 703 } 704 705 assert(Sec->Symb->Aux.size() == 1 && "Section's symbol must have one aux!"); 706 AuxSymbol &Aux = Sec->Symb->Aux[0]; 707 assert(Aux.AuxType == ATSectionDefinition && 708 "Section's symbol's aux symbol must be a Section Definition!"); 709 Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData; 710 Aux.Aux.SectionDefinition.NumberOfRelocations = 711 Sec->Header.NumberOfRelocations; 712 Aux.Aux.SectionDefinition.NumberOfLinenumbers = 713 Sec->Header.NumberOfLineNumbers; 714 } 715 716 Header.PointerToSymbolTable = offset; 717 718 Header.TimeDateStamp = sys::TimeValue::now().toEpochTime(); 719 720 // Write it all to disk... 721 WriteFileHeader(Header); 722 723 { 724 sections::iterator i, ie; 725 MCAssembler::const_iterator j, je; 726 727 for (i = Sections.begin(), ie = Sections.end(); i != ie; i++) 728 WriteSectionHeader((*i)->Header); 729 730 for (i = Sections.begin(), ie = Sections.end(), 731 j = Asm.begin(), je = Asm.end(); 732 (i != ie) && (j != je); i++, j++) { 733 if ((*i)->Header.PointerToRawData != 0) { 734 assert(OS.tell() == (*i)->Header.PointerToRawData && 735 "Section::PointerToRawData is insane!"); 736 737 Asm.WriteSectionData(j, Layout, this); 738 } 739 740 if ((*i)->Relocations.size() > 0) { 741 assert(OS.tell() == (*i)->Header.PointerToRelocations && 742 "Section::PointerToRelocations is insane!"); 743 744 for (relocations::const_iterator k = (*i)->Relocations.begin(), 745 ke = (*i)->Relocations.end(); 746 k != ke; k++) { 747 WriteRelocation(k->Data); 748 } 749 } else 750 assert((*i)->Header.PointerToRelocations == 0 && 751 "Section::PointerToRelocations is insane!"); 752 } 753 } 754 755 assert(OS.tell() == Header.PointerToSymbolTable && 756 "Header::PointerToSymbolTable is insane!"); 757 758 for (symbols::iterator i = Symbols.begin(), e = Symbols.end(); i != e; i++) 759 WriteSymbol(*i); 760 761 OS.write((char const *)&Strings.Data.front(), Strings.Data.size()); 762} 763 764//------------------------------------------------------------------------------ 765// WinCOFFObjectWriter factory function 766 767namespace llvm { 768 MCObjectWriter *createWinCOFFObjectWriter(raw_ostream &OS, bool is64Bit) { 769 return new WinCOFFObjectWriter(OS, is64Bit); 770 } 771} 772