Index: include/llvm/Object/COFF.h =================================================================== --- include/llvm/Object/COFF.h +++ include/llvm/Object/COFF.h @@ -236,6 +236,14 @@ return A.getRawPtr() < B.getRawPtr(); } + bool isBigObj() const { + if (CS16) + return false; + if (CS32) + return true; + llvm_unreachable("COFFSymbolRef points to nothing!"); + } + const char *getShortName() const { return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; } @@ -361,8 +369,16 @@ support::ulittle16_t NumberOfRelocations; support::ulittle16_t NumberOfLinenumbers; support::ulittle32_t CheckSum; - support::ulittle16_t Number; + support::ulittle16_t NumberLowPart; uint8_t Selection; + uint8_t Unused; + support::ulittle16_t NumberHighPart; + int32_t getNumber(bool IsBigObj) const { + uint32_t Number = static_cast(NumberLowPart); + if (IsBigObj) + Number |= static_cast(NumberHighPart) << 16; + return static_cast(Number); + } }; struct coff_aux_clr_token { Index: include/llvm/Support/COFF.h =================================================================== --- include/llvm/Support/COFF.h +++ include/llvm/Support/COFF.h @@ -31,7 +31,7 @@ namespace COFF { // The maximum number of sections that a COFF object can have (inclusive). - const uint16_t MaxNumberOfSections16 = 65299; + const int32_t MaxNumberOfSections16 = 65279; // The PE signature bytes that follows the DOS stub header. static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; @@ -43,16 +43,18 @@ // Sizes in bytes of various things in the COFF format. enum { - HeaderSize = 20, + Header16Size = 20, + Header32Size = 56, NameSize = 8, - SymbolSize = 18, + Symbol16Size = 18, + Symbol32Size = 20, SectionSize = 40, RelocationSize = 10 }; struct header { uint16_t Machine; - uint16_t NumberOfSections; + int32_t NumberOfSections; uint32_t TimeDateStamp; uint32_t PointerToSymbolTable; uint32_t NumberOfSymbols; @@ -147,7 +149,7 @@ struct symbol { char Name[NameSize]; uint32_t Value; - uint16_t SectionNumber; + int32_t SectionNumber; uint16_t Type; uint8_t StorageClass; uint8_t NumberOfAuxSymbols; @@ -390,16 +392,12 @@ IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 }; - struct AuxiliaryFile { - uint8_t FileName[18]; - }; - struct AuxiliarySectionDefinition { uint32_t Length; uint16_t NumberOfRelocations; uint16_t NumberOfLinenumbers; uint32_t CheckSum; - uint16_t Number; + uint32_t Number; uint8_t Selection; char unused[3]; }; @@ -415,7 +413,6 @@ AuxiliaryFunctionDefinition FunctionDefinition; AuxiliarybfAndefSymbol bfAndefSymbol; AuxiliaryWeakExternal WeakExternal; - AuxiliaryFile File; AuxiliarySectionDefinition SectionDefinition; }; Index: lib/MC/WinCOFFObjectWriter.cpp =================================================================== --- lib/MC/WinCOFFObjectWriter.cpp +++ lib/MC/WinCOFFObjectWriter.cpp @@ -71,7 +71,6 @@ MCSymbolData const *MCData; COFFSymbol(StringRef name); - size_t size() const; void set_name_offset(uint32_t Offset); bool should_keep() const; @@ -137,6 +136,8 @@ section_map SectionMap; symbol_map SymbolMap; + bool UseBigObj; + WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS); COFFSymbol *createSymbol(StringRef Name); @@ -199,10 +200,6 @@ memset(&Data, 0, sizeof(Data)); } -size_t COFFSymbol::size() const { - return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize); -} - // In the case that the name does not fit within 8 bytes, the offset // into the string table is stored in the last 4 bytes instead, leaving // the first 4 bytes as 0. @@ -301,8 +298,7 @@ WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS) - : MCObjectWriter(OS, true) - , TargetObjectWriter(MOTW) { + : MCObjectWriter(OS, true), TargetObjectWriter(MOTW) { memset(&Header, 0, sizeof(Header)); Header.Machine = TargetObjectWriter->getMachine(); @@ -578,19 +574,39 @@ // entity writing methods void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) { - WriteLE16(Header.Machine); - WriteLE16(Header.NumberOfSections); - WriteLE32(Header.TimeDateStamp); - WriteLE32(Header.PointerToSymbolTable); - WriteLE32(Header.NumberOfSymbols); - WriteLE16(Header.SizeOfOptionalHeader); - WriteLE16(Header.Characteristics); + if (UseBigObj) { + WriteLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN); + WriteLE16(0xFFFF); + WriteLE16(COFF::BigObjHeader::MinBigObjectVersion); + WriteLE16(Header.Machine); + WriteLE32(Header.TimeDateStamp); + for (uint8_t MagicChar : COFF::BigObjMagic) + Write8(MagicChar); + WriteZeros(sizeof(COFF::BigObjHeader::unused1)); + WriteZeros(sizeof(COFF::BigObjHeader::unused2)); + WriteZeros(sizeof(COFF::BigObjHeader::unused3)); + WriteZeros(sizeof(COFF::BigObjHeader::unused4)); + WriteLE32(Header.NumberOfSections); + WriteLE32(Header.PointerToSymbolTable); + WriteLE32(Header.NumberOfSymbols); + } else { + WriteLE16(Header.Machine); + WriteLE16(static_cast(Header.NumberOfSections)); + WriteLE32(Header.TimeDateStamp); + WriteLE32(Header.PointerToSymbolTable); + WriteLE32(Header.NumberOfSymbols); + WriteLE16(Header.SizeOfOptionalHeader); + WriteLE16(Header.Characteristics); + } } void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) { WriteBytes(StringRef(S.Data.Name, COFF::NameSize)); WriteLE32(S.Data.Value); - WriteLE16(S.Data.SectionNumber); + if (UseBigObj) + WriteLE32(S.Data.SectionNumber); + else + WriteLE16(static_cast(S.Data.SectionNumber)); WriteLE16(S.Data.Type); Write8(S.Data.StorageClass); Write8(S.Data.NumberOfAuxSymbols); @@ -608,6 +624,8 @@ WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber); WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction); WriteZeros(sizeof(i->Aux.FunctionDefinition.unused)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATbfAndefSymbol: WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1)); @@ -615,24 +633,35 @@ WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2)); WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction); WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATWeakExternal: WriteLE32(i->Aux.WeakExternal.TagIndex); WriteLE32(i->Aux.WeakExternal.Characteristics); WriteZeros(sizeof(i->Aux.WeakExternal.unused)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATFile: - WriteBytes(StringRef(reinterpret_cast(i->Aux.File.FileName), - sizeof(i->Aux.File.FileName))); + WriteBytes( + StringRef(reinterpret_cast(&i->Aux), + UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size)); break; case ATSectionDefinition: WriteLE32(i->Aux.SectionDefinition.Length); WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations); WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers); WriteLE32(i->Aux.SectionDefinition.CheckSum); - WriteLE16(i->Aux.SectionDefinition.Number); + WriteLE16(static_cast(i->Aux.SectionDefinition.Number)); Write8(i->Aux.SectionDefinition.Selection); - WriteZeros(sizeof(i->Aux.SectionDefinition.unused)); + WriteZeros(1); + if (UseBigObj) + WriteLE16(static_cast(i->Aux.SectionDefinition.Number >> 16)); + else + WriteZeros(2); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; } } @@ -665,37 +694,6 @@ const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. - - static_assert(sizeof(((COFF::AuxiliaryFile *)nullptr)->FileName) == COFF::SymbolSize, - "size mismatch for COFF::AuxiliaryFile::FileName"); - for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end(); - FI != FE; ++FI) { - // round up to calculate the number of auxiliary symbols required - unsigned Count = (FI->size() + COFF::SymbolSize - 1) / COFF::SymbolSize; - - COFFSymbol *file = createSymbol(".file"); - file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; - file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; - file->Aux.resize(Count); - - unsigned Offset = 0; - unsigned Length = FI->size(); - for (auto & Aux : file->Aux) { - Aux.AuxType = ATFile; - - if (Length > COFF::SymbolSize) { - memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, COFF::SymbolSize); - Length = Length - COFF::SymbolSize; - } else { - memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, Length); - memset(&Aux.Aux.File.FileName[Length], 0, COFF::SymbolSize - Length); - Length = 0; - } - - Offset = Offset + COFF::SymbolSize; - } - } - for (const auto & Section : Asm) DefineSection(Section); @@ -839,23 +837,57 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { + size_t SectionsSize = Sections.size(); + if (SectionsSize > static_cast(INT32_MAX)) + report_fatal_error( + "PE COFF object files can't have more than 2147483647 sections"); + // Assign symbol and section indexes and offsets. - size_t NumberOfSections = 0; + int32_t NumberOfSections = static_cast(SectionsSize); + + UseBigObj = NumberOfSections > COFF::MaxNumberOfSections16; - DenseMap SectionIndices; + DenseMap SectionIndices( + NextPowerOf2(NumberOfSections)); + size_t Number = 1; for (const auto &Section : Sections) { - size_t Number = ++NumberOfSections; - SectionIndices[Section.get()] = static_cast(Number); + SectionIndices[Section.get()] = Number; MakeSectionReal(*Section, Number); + ++Number; } - if (NumberOfSections > static_cast(COFF::MaxNumberOfSections16)) - report_fatal_error( - "PE COFF object files can't have more than 65,299 sections"); - - Header.NumberOfSections = static_cast(NumberOfSections); + Header.NumberOfSections = NumberOfSections; Header.NumberOfSymbols = 0; + for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end(); + FI != FE; ++FI) { + // round up to calculate the number of auxiliary symbols required + unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size; + unsigned Count = (FI->size() + SymbolSize - 1) / SymbolSize; + + COFFSymbol *file = createSymbol(".file"); + file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; + file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; + file->Aux.resize(Count); + + unsigned Offset = 0; + unsigned Length = FI->size(); + for (auto & Aux : file->Aux) { + Aux.AuxType = ATFile; + + if (Length > SymbolSize) { + memcpy(&Aux.Aux, FI->c_str() + Offset, SymbolSize); + Length = Length - SymbolSize; + } else { + memcpy(&Aux.Aux, FI->c_str() + Offset, Length); + memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length); + Length = 0; + } + + Offset = Offset + SymbolSize; + } + } + for (auto &Symbol : Symbols) { // Update section number & offset for symbols that have them. if (Symbol->Section) @@ -913,7 +945,10 @@ unsigned offset = 0; - offset += COFF::HeaderSize; + if (UseBigObj) + offset += COFF::Header32Size; + else + offset += COFF::Header16Size; offset += COFF::SectionSize * Header.NumberOfSections; for (const auto & Section : Asm) { Index: tools/llvm-objdump/llvm-objdump.cpp =================================================================== --- tools/llvm-objdump/llvm-objdump.cpp +++ tools/llvm-objdump/llvm-objdump.cpp @@ -591,6 +591,8 @@ if (error(coff->getAuxSymbol(SI + 1, asd))) return; + int32_t AuxNumber = asd->getNumber(Symbol->isBigObj()); + outs() << "AUX " << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " , unsigned(asd->Length) @@ -598,7 +600,7 @@ , unsigned(asd->NumberOfLinenumbers) , unsigned(asd->CheckSum)) << format("assoc %d comdat %d\n" - , unsigned(asd->Number) + , unsigned(AuxNumber) , unsigned(asd->Selection)); } else if (Symbol->isFileRecord()) { const char *FileName; Index: tools/llvm-readobj/COFFDumper.cpp =================================================================== --- tools/llvm-readobj/COFFDumper.cpp +++ tools/llvm-readobj/COFFDumper.cpp @@ -790,12 +790,14 @@ if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; + int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj()); + DictScope AS(W, "AuxSectionDef"); W.printNumber("Length", Aux->Length); W.printNumber("RelocationCount", Aux->NumberOfRelocations); W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers); W.printHex("Checksum", Aux->CheckSum); - W.printNumber("Number", Aux->Number); + W.printNumber("Number", AuxNumber); W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect)); if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT @@ -803,13 +805,13 @@ const coff_section *Assoc; StringRef AssocName; std::error_code EC; - if ((EC = Obj->getSection(Aux->Number, Assoc)) || + if ((EC = Obj->getSection(AuxNumber, Assoc)) || (EC = Obj->getSectionName(Assoc, AssocName))) { AssocName = ""; error(EC); } - W.printNumber("AssocSection", AssocName, Aux->Number); + W.printNumber("AssocSection", AssocName, AuxNumber); } } else if (Symbol.isCLRToken()) { const coff_aux_clr_token *Aux; Index: tools/obj2yaml/coff2yaml.cpp =================================================================== --- tools/obj2yaml/coff2yaml.cpp +++ tools/obj2yaml/coff2yaml.cpp @@ -104,13 +104,15 @@ static void dumpSectionDefinition(COFFYAML::Symbol *Sym, - const object::coff_aux_section_definition *ObjSD) { + const object::coff_aux_section_definition *ObjSD, + bool IsBigObj) { COFF::AuxiliarySectionDefinition YAMLASD; + int32_t AuxNumber = ObjSD->getNumber(IsBigObj); YAMLASD.Length = ObjSD->Length; YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations; YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers; YAMLASD.CheckSum = ObjSD->CheckSum; - YAMLASD.Number = ObjSD->Number; + YAMLASD.Number = AuxNumber; YAMLASD.Selection = ObjSD->Selection; Sym->SectionDefinition = YAMLASD; @@ -182,7 +184,7 @@ const object::coff_aux_section_definition *ObjSD = reinterpret_cast( AuxData.data()); - dumpSectionDefinition(&Sym, ObjSD); + dumpSectionDefinition(&Sym, ObjSD, Symbol.isBigObj()); } else if (Symbol.isCLRToken()) { // This symbol represents a CLR token definition. assert(Symbol.getNumberOfAuxSymbols() == 1 && Index: tools/yaml2obj/yaml2coff.cpp =================================================================== --- tools/yaml2obj/yaml2coff.cpp +++ tools/yaml2obj/yaml2coff.cpp @@ -121,8 +121,8 @@ // The section table starts immediately after the header, including the // optional header. - SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader; - SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size(); + SectionTableStart = COFF::Header16Size + CP.Obj.Header.SizeOfOptionalHeader; + SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size(); uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize; @@ -163,7 +163,7 @@ NumberOfAuxSymbols += 1; if (!i->File.empty()) NumberOfAuxSymbols += - (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; + (i->File.size() + COFF::Symbol16Size - 1) / COFF::Symbol16Size; if (i->SectionDefinition) NumberOfAuxSymbols += 1; if (i->CLRToken) @@ -224,7 +224,7 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) { OS << binary_le(CP.Obj.Header.Machine) - << binary_le(CP.Obj.Header.NumberOfSections) + << binary_le(static_cast(CP.Obj.Header.NumberOfSections)) << binary_le(CP.Obj.Header.TimeDateStamp) << binary_le(CP.Obj.Header.PointerToSymbolTable) << binary_le(CP.Obj.Header.NumberOfSymbols) @@ -277,7 +277,7 @@ i != e; ++i) { OS.write(i->Header.Name, COFF::NameSize); OS << binary_le(i->Header.Value) - << binary_le(i->Header.SectionNumber) + << binary_le(static_cast(i->Header.SectionNumber)) << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass) << binary_le(i->Header.NumberOfAuxSymbols); @@ -300,8 +300,8 @@ << zeros(i->WeakExternal->unused); if (!i->File.empty()) { uint32_t NumberOfAuxRecords = - (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; - uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::SymbolSize; + (i->File.size() + COFF::Symbol16Size - 1) / COFF::Symbol16Size; + uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::Symbol16Size; uint32_t NumZeros = NumberOfAuxBytes - i->File.size(); OS.write(i->File.data(), i->File.size()); for (uint32_t Padding = 0; Padding < NumZeros; ++Padding) @@ -312,7 +312,7 @@ << binary_le(i->SectionDefinition->NumberOfRelocations) << binary_le(i->SectionDefinition->NumberOfLinenumbers) << binary_le(i->SectionDefinition->CheckSum) - << binary_le(i->SectionDefinition->Number) + << binary_le(static_cast(i->SectionDefinition->Number)) << binary_le(i->SectionDefinition->Selection) << zeros(i->SectionDefinition->unused); if (i->CLRToken)