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