llvm.org GIT mirror llvm / f1198da
MC: Add support for BigObj Teach WinCOFFObjectWriter how to write -mbig-obj style object files; these object files allow for more sections inside an object file. Our support for BigObj is notably different from binutils and cl: we implicitly upgrade object files to BigObj instead of asking the user to compile the same file *again* but with another flag. This matches up with how LLVM treats ELF variants. This was tested by forcing LLVM to always emit BigObj files and running the entire test suite. A specific test has also been added. I've lowered the maximum number of sections in a normal COFF file, VS "14" CTP 3 supports no more than 65279 sections. This is important otherwise we might not switch to BigObj quickly enough, leaving us with a COFF file that we couldn't link. yaml2obj support is all that remains to implement. Differential Revision: http://reviews.llvm.org/D5349 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217812 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 5 years ago
7 changed file(s) with 143 addition(s) and 91 deletion(s). Raw diff Collapse all Expand all
235235 return A.getRawPtr() < B.getRawPtr();
236236 }
237237
238 bool isBigObj() const {
239 if (CS16)
240 return false;
241 if (CS32)
242 return true;
243 llvm_unreachable("COFFSymbolRef points to nothing!");
244 }
245
238246 const char *getShortName() const {
239247 return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName;
240248 }
360368 support::ulittle16_t NumberOfRelocations;
361369 support::ulittle16_t NumberOfLinenumbers;
362370 support::ulittle32_t CheckSum;
363 support::ulittle16_t Number;
371 support::ulittle16_t NumberLowPart;
364372 uint8_t Selection;
373 uint8_t Unused;
374 support::ulittle16_t NumberHighPart;
375 int32_t getNumber(bool IsBigObj) const {
376 uint32_t Number = static_cast(NumberLowPart);
377 if (IsBigObj)
378 Number |= static_cast(NumberHighPart) << 16;
379 return static_cast(Number);
380 }
365381 };
366382
367383 struct coff_aux_clr_token {
3030 namespace COFF {
3131
3232 // The maximum number of sections that a COFF object can have (inclusive).
33 const uint16_t MaxNumberOfSections16 = 65299;
33 const int32_t MaxNumberOfSections16 = 65279;
3434
3535 // The PE signature bytes that follows the DOS stub header.
3636 static const char PEMagic[] = { 'P', 'E', '\0', '\0' };
4242
4343 // Sizes in bytes of various things in the COFF format.
4444 enum {
45 HeaderSize = 20,
45 Header16Size = 20,
46 Header32Size = 56,
4647 NameSize = 8,
47 SymbolSize = 18,
48 Symbol16Size = 18,
49 Symbol32Size = 20,
4850 SectionSize = 40,
4951 RelocationSize = 10
5052 };
5153
5254 struct header {
5355 uint16_t Machine;
54 uint16_t NumberOfSections;
56 int32_t NumberOfSections;
5557 uint32_t TimeDateStamp;
5658 uint32_t PointerToSymbolTable;
5759 uint32_t NumberOfSymbols;
146148 struct symbol {
147149 char Name[NameSize];
148150 uint32_t Value;
149 uint16_t SectionNumber;
151 int32_t SectionNumber;
150152 uint16_t Type;
151153 uint8_t StorageClass;
152154 uint8_t NumberOfAuxSymbols;
389391 IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3
390392 };
391393
392 struct AuxiliaryFile {
393 uint8_t FileName[18];
394 };
395
396394 struct AuxiliarySectionDefinition {
397395 uint32_t Length;
398396 uint16_t NumberOfRelocations;
399397 uint16_t NumberOfLinenumbers;
400398 uint32_t CheckSum;
401 uint16_t Number;
399 uint32_t Number;
402400 uint8_t Selection;
403 char unused[3];
401 char unused;
404402 };
405403
406404 struct AuxiliaryCLRToken {
414412 AuxiliaryFunctionDefinition FunctionDefinition;
415413 AuxiliarybfAndefSymbol bfAndefSymbol;
416414 AuxiliaryWeakExternal WeakExternal;
417 AuxiliaryFile File;
418415 AuxiliarySectionDefinition SectionDefinition;
419416 };
420417
7070 MCSymbolData const *MCData;
7171
7272 COFFSymbol(StringRef name);
73 size_t size() const;
7473 void set_name_offset(uint32_t Offset);
7574
7675 bool should_keep() const;
135134 // Maps used during object file creation.
136135 section_map SectionMap;
137136 symbol_map SymbolMap;
137
138 bool UseBigObj;
138139
139140 WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS);
140141
198199 memset(&Data, 0, sizeof(Data));
199200 }
200201
201 size_t COFFSymbol::size() const {
202 return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize);
203 }
204
205202 // In the case that the name does not fit within 8 bytes, the offset
206203 // into the string table is stored in the last 4 bytes instead, leaving
207204 // the first 4 bytes as 0.
300297
301298 WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW,
302299 raw_ostream &OS)
303 : MCObjectWriter(OS, true)
304 , TargetObjectWriter(MOTW) {
300 : MCObjectWriter(OS, true), TargetObjectWriter(MOTW) {
305301 memset(&Header, 0, sizeof(Header));
306302
307303 Header.Machine = TargetObjectWriter->getMachine();
577573 // entity writing methods
578574
579575 void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
580 WriteLE16(Header.Machine);
581 WriteLE16(Header.NumberOfSections);
582 WriteLE32(Header.TimeDateStamp);
583 WriteLE32(Header.PointerToSymbolTable);
584 WriteLE32(Header.NumberOfSymbols);
585 WriteLE16(Header.SizeOfOptionalHeader);
586 WriteLE16(Header.Characteristics);
576 if (UseBigObj) {
577 WriteLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
578 WriteLE16(0xFFFF);
579 WriteLE16(COFF::BigObjHeader::MinBigObjectVersion);
580 WriteLE16(Header.Machine);
581 WriteLE32(Header.TimeDateStamp);
582 for (uint8_t MagicChar : COFF::BigObjMagic)
583 Write8(MagicChar);
584 WriteZeros(sizeof(COFF::BigObjHeader::unused1));
585 WriteZeros(sizeof(COFF::BigObjHeader::unused2));
586 WriteZeros(sizeof(COFF::BigObjHeader::unused3));
587 WriteZeros(sizeof(COFF::BigObjHeader::unused4));
588 WriteLE32(Header.NumberOfSections);
589 WriteLE32(Header.PointerToSymbolTable);
590 WriteLE32(Header.NumberOfSymbols);
591 } else {
592 WriteLE16(Header.Machine);
593 WriteLE16(static_cast(Header.NumberOfSections));
594 WriteLE32(Header.TimeDateStamp);
595 WriteLE32(Header.PointerToSymbolTable);
596 WriteLE32(Header.NumberOfSymbols);
597 WriteLE16(Header.SizeOfOptionalHeader);
598 WriteLE16(Header.Characteristics);
599 }
587600 }
588601
589602 void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
590603 WriteBytes(StringRef(S.Data.Name, COFF::NameSize));
591604 WriteLE32(S.Data.Value);
592 WriteLE16(S.Data.SectionNumber);
605 if (UseBigObj)
606 WriteLE32(S.Data.SectionNumber);
607 else
608 WriteLE16(static_cast(S.Data.SectionNumber));
593609 WriteLE16(S.Data.Type);
594610 Write8(S.Data.StorageClass);
595611 Write8(S.Data.NumberOfAuxSymbols);
607623 WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber);
608624 WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction);
609625 WriteZeros(sizeof(i->Aux.FunctionDefinition.unused));
626 if (UseBigObj)
627 WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
610628 break;
611629 case ATbfAndefSymbol:
612630 WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1));
614632 WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2));
615633 WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction);
616634 WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3));
635 if (UseBigObj)
636 WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
617637 break;
618638 case ATWeakExternal:
619639 WriteLE32(i->Aux.WeakExternal.TagIndex);
620640 WriteLE32(i->Aux.WeakExternal.Characteristics);
621641 WriteZeros(sizeof(i->Aux.WeakExternal.unused));
642 if (UseBigObj)
643 WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
622644 break;
623645 case ATFile:
624 WriteBytes(StringRef(reinterpret_cast(i->Aux.File.FileName),
625 sizeof(i->Aux.File.FileName)));
646 WriteBytes(
647 StringRef(reinterpret_cast(&i->Aux),
648 UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size));
626649 break;
627650 case ATSectionDefinition:
628651 WriteLE32(i->Aux.SectionDefinition.Length);
629652 WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations);
630653 WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers);
631654 WriteLE32(i->Aux.SectionDefinition.CheckSum);
632 WriteLE16(i->Aux.SectionDefinition.Number);
655 WriteLE16(static_cast(i->Aux.SectionDefinition.Number));
633656 Write8(i->Aux.SectionDefinition.Selection);
634657 WriteZeros(sizeof(i->Aux.SectionDefinition.unused));
658 WriteLE16(static_cast(i->Aux.SectionDefinition.Number >> 16));
659 if (UseBigObj)
660 WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
635661 break;
636662 }
637663 }
664690 const MCAsmLayout &Layout) {
665691 // "Define" each section & symbol. This creates section & symbol
666692 // entries in the staging area.
667
668 static_assert(sizeof(((COFF::AuxiliaryFile *)nullptr)->FileName) == COFF::SymbolSize,
669 "size mismatch for COFF::AuxiliaryFile::FileName");
670 for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end();
671 FI != FE; ++FI) {
672 // round up to calculate the number of auxiliary symbols required
673 unsigned Count = (FI->size() + COFF::SymbolSize - 1) / COFF::SymbolSize;
674
675 COFFSymbol *file = createSymbol(".file");
676 file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG;
677 file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
678 file->Aux.resize(Count);
679
680 unsigned Offset = 0;
681 unsigned Length = FI->size();
682 for (auto & Aux : file->Aux) {
683 Aux.AuxType = ATFile;
684
685 if (Length > COFF::SymbolSize) {
686 memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, COFF::SymbolSize);
687 Length = Length - COFF::SymbolSize;
688 } else {
689 memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, Length);
690 memset(&Aux.Aux.File.FileName[Length], 0, COFF::SymbolSize - Length);
691 Length = 0;
692 }
693
694 Offset = Offset + COFF::SymbolSize;
695 }
696 }
697
698693 for (const auto & Section : Asm)
699694 DefineSection(Section);
700695
838833
839834 void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm,
840835 const MCAsmLayout &Layout) {
836 size_t SectionsSize = Sections.size();
837 if (SectionsSize > static_cast(INT32_MAX))
838 report_fatal_error(
839 "PE COFF object files can't have more than 2147483647 sections");
840
841841 // Assign symbol and section indexes and offsets.
842 size_t NumberOfSections = 0;
843
844 DenseMap SectionIndices;
842 int32_t NumberOfSections = static_cast(SectionsSize);
843
844 UseBigObj = NumberOfSections > COFF::MaxNumberOfSections16;
845
846 DenseMap SectionIndices(
847 NextPowerOf2(NumberOfSections));
848 size_t Number = 1;
845849 for (const auto &Section : Sections) {
846 size_t Number = ++NumberOfSections;
847 SectionIndices[Section.get()] = static_cast(Number);
850 SectionIndices[Section.get()] = Number;
848851 MakeSectionReal(*Section, Number);
849 }
850
851 if (NumberOfSections > static_cast(COFF::MaxNumberOfSections16))
852 report_fatal_error(
853 "PE COFF object files can't have more than 65,299 sections");
854
855 Header.NumberOfSections = static_cast(NumberOfSections);
852 ++Number;
853 }
854
855 Header.NumberOfSections = NumberOfSections;
856856 Header.NumberOfSymbols = 0;
857
858 for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end();
859 FI != FE; ++FI) {
860 // round up to calculate the number of auxiliary symbols required
861 unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size;
862 unsigned Count = (FI->size() + SymbolSize - 1) / SymbolSize;
863
864 COFFSymbol *file = createSymbol(".file");
865 file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG;
866 file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE;
867 file->Aux.resize(Count);
868
869 unsigned Offset = 0;
870 unsigned Length = FI->size();
871 for (auto & Aux : file->Aux) {
872 Aux.AuxType = ATFile;
873
874 if (Length > SymbolSize) {
875 memcpy(&Aux.Aux, FI->c_str() + Offset, SymbolSize);
876 Length = Length - SymbolSize;
877 } else {
878 memcpy(&Aux.Aux, FI->c_str() + Offset, Length);
879 memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length);
880 break;
881 }
882
883 Offset += SymbolSize;
884 }
885 }
857886
858887 for (auto &Symbol : Symbols) {
859888 // Update section number & offset for symbols that have them.
912941
913942 unsigned offset = 0;
914943
915 offset += COFF::HeaderSize;
944 if (UseBigObj)
945 offset += COFF::Header32Size;
946 else
947 offset += COFF::Header16Size;
916948 offset += COFF::SectionSize * Header.NumberOfSections;
917949
918950 for (const auto & Section : Asm) {
590590 if (error(coff->getAuxSymbol(SI + 1, asd)))
591591 return;
592592
593 int32_t AuxNumber = asd->getNumber(Symbol->isBigObj());
594
593595 outs() << "AUX "
594596 << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x "
595597 , unsigned(asd->Length)
597599 , unsigned(asd->NumberOfLinenumbers)
598600 , unsigned(asd->CheckSum))
599601 << format("assoc %d comdat %d\n"
600 , unsigned(asd->Number)
602 , unsigned(AuxNumber)
601603 , unsigned(asd->Selection));
602604 } else if (Symbol->isFileRecord()) {
603605 const char *FileName;
789789 if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
790790 break;
791791
792 int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
793
792794 DictScope AS(W, "AuxSectionDef");
793795 W.printNumber("Length", Aux->Length);
794796 W.printNumber("RelocationCount", Aux->NumberOfRelocations);
795797 W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
796798 W.printHex("Checksum", Aux->CheckSum);
797 W.printNumber("Number", Aux->Number);
799 W.printNumber("Number", AuxNumber);
798800 W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
799801
800802 if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
802804 const coff_section *Assoc;
803805 StringRef AssocName;
804806 std::error_code EC;
805 if ((EC = Obj->getSection(Aux->Number, Assoc)) ||
807 if ((EC = Obj->getSection(AuxNumber, Assoc)) ||
806808 (EC = Obj->getSectionName(Assoc, AssocName))) {
807809 AssocName = "";
808810 error(EC);
809811 }
810812
811 W.printNumber("AssocSection", AssocName, Aux->Number);
813 W.printNumber("AssocSection", AssocName, AuxNumber);
812814 }
813815 } else if (Symbol.isCLRToken()) {
814816 const coff_aux_clr_token *Aux;
103103
104104 static void
105105 dumpSectionDefinition(COFFYAML::Symbol *Sym,
106 const object::coff_aux_section_definition *ObjSD) {
106 const object::coff_aux_section_definition *ObjSD,
107 bool IsBigObj) {
107108 COFF::AuxiliarySectionDefinition YAMLASD;
109 int32_t AuxNumber = ObjSD->getNumber(IsBigObj);
108110 YAMLASD.Length = ObjSD->Length;
109111 YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations;
110112 YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers;
111113 YAMLASD.CheckSum = ObjSD->CheckSum;
112 YAMLASD.Number = ObjSD->Number;
114 YAMLASD.Number = AuxNumber;
113115 YAMLASD.Selection = ObjSD->Selection;
114116
115117 Sym->SectionDefinition = YAMLASD;
181183 const object::coff_aux_section_definition *ObjSD =
182184 reinterpret_cast(
183185 AuxData.data());
184 dumpSectionDefinition(&Sym, ObjSD);
186 dumpSectionDefinition(&Sym, ObjSD, Symbol.isBigObj());
185187 } else if (Symbol.isCLRToken()) {
186188 // This symbol represents a CLR token definition.
187189 assert(Symbol.getNumberOfAuxSymbols() == 1 &&
120120
121121 // The section table starts immediately after the header, including the
122122 // optional header.
123 SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader;
124 SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size();
123 SectionTableStart = COFF::Header16Size + CP.Obj.Header.SizeOfOptionalHeader;
124 SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size();
125125
126126 uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize;
127127
162162 NumberOfAuxSymbols += 1;
163163 if (!i->File.empty())
164164 NumberOfAuxSymbols +=
165 (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize;
165 (i->File.size() + COFF::Symbol16Size - 1) / COFF::Symbol16Size;
166166 if (i->SectionDefinition)
167167 NumberOfAuxSymbols += 1;
168168 if (i->CLRToken)
223223
224224 bool writeCOFF(COFFParser &CP, raw_ostream &OS) {
225225 OS << binary_le(CP.Obj.Header.Machine)
226 << binary_le(CP.Obj.Header.NumberOfSections)
226 << binary_le(static_cast(CP.Obj.Header.NumberOfSections))
227227 << binary_le(CP.Obj.Header.TimeDateStamp)
228228 << binary_le(CP.Obj.Header.PointerToSymbolTable)
229229 << binary_le(CP.Obj.Header.NumberOfSymbols)
276276 i != e; ++i) {
277277 OS.write(i->Header.Name, COFF::NameSize);
278278 OS << binary_le(i->Header.Value)
279 << binary_le(i->Header.SectionNumber)
279 << binary_le(static_cast(i->Header.SectionNumber))
280280 << binary_le(i->Header.Type)
281281 << binary_le(i->Header.StorageClass)
282282 << binary_le(i->Header.NumberOfAuxSymbols);
299299 << zeros(i->WeakExternal->unused);
300300 if (!i->File.empty()) {
301301 uint32_t NumberOfAuxRecords =
302 (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize;
303 uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::SymbolSize;
302 (i->File.size() + COFF::Symbol16Size - 1) / COFF::Symbol16Size;
303 uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::Symbol16Size;
304304 uint32_t NumZeros = NumberOfAuxBytes - i->File.size();
305305 OS.write(i->File.data(), i->File.size());
306306 for (uint32_t Padding = 0; Padding < NumZeros; ++Padding)
311311 << binary_le(i->SectionDefinition->NumberOfRelocations)
312312 << binary_le(i->SectionDefinition->NumberOfLinenumbers)
313313 << binary_le(i->SectionDefinition->CheckSum)
314 << binary_le(i->SectionDefinition->Number)
314 << binary_le(static_cast(i->SectionDefinition->Number))
315315 << binary_le(i->SectionDefinition->Selection)
316 << zeros(i->SectionDefinition->unused);
316 << zeros(i->SectionDefinition->unused)
317 << binary_le(static_cast(i->SectionDefinition->Number >> 16));
317318 if (i->CLRToken)
318319 OS << binary_le(i->CLRToken->AuxType)
319320 << zeros(i->CLRToken->unused1)