Index: llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp =================================================================== --- llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp +++ llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp @@ -177,7 +177,7 @@ void WriteFileHeader(const COFF::header &Header); void WriteSymbol(const COFFSymbol &S); void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S); - void writeSectionHeader(const COFF::section &S); + void writeSectionHeaders(); void WriteRelocation(const COFF::relocation &R); uint32_t writeSectionContents(MCAssembler &Asm, const MCAsmLayout &Layout, const MCSection &MCSec); @@ -560,18 +560,37 @@ } } -void WinCOFFObjectWriter::writeSectionHeader(const COFF::section &S) { - writeBytes(StringRef(S.Name, COFF::NameSize)); +// Write the section header. +void WinCOFFObjectWriter::writeSectionHeaders() { + // Section numbers must be monotonically increasing in the section + // header, but our Sections array is not sorted by section number, + // so make a copy of Sections and sort it. + std::vector Arr; + for (auto &Section : Sections) + Arr.push_back(Section.get()); + std::sort(Arr.begin(), Arr.end(), + [](const COFFSection *A, const COFFSection *B) { + return A->Number < B->Number; + }); - writeLE32(S.VirtualSize); - writeLE32(S.VirtualAddress); - writeLE32(S.SizeOfRawData); - writeLE32(S.PointerToRawData); - writeLE32(S.PointerToRelocations); - writeLE32(S.PointerToLineNumbers); - writeLE16(S.NumberOfRelocations); - writeLE16(S.NumberOfLineNumbers); - writeLE32(S.Characteristics); + for (auto &Section : Arr) { + if (Section->Number == -1) + continue; + + COFF::section &S = Section->Header; + if (Section->Relocations.size() >= 0xffff) + S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; + writeBytes(StringRef(S.Name, COFF::NameSize)); + writeLE32(S.VirtualSize); + writeLE32(S.VirtualAddress); + writeLE32(S.SizeOfRawData); + writeLE32(S.PointerToRawData); + writeLE32(S.PointerToRelocations); + writeLE32(S.PointerToLineNumbers); + writeLE16(S.NumberOfRelocations); + writeLE16(S.NumberOfLineNumbers); + writeLE32(S.Characteristics); + } } void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) { @@ -895,14 +914,29 @@ } } +static bool isAssociative(const COFFSection &Section) { + return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection == + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE; +} + void WinCOFFObjectWriter::assignSectionNumbers() { size_t I = 1; - for (const auto &Section : Sections) { - Section->Number = I; - Section->Symbol->Data.SectionNumber = I; - Section->Symbol->Aux[0].Aux.SectionDefinition.Number = I; + auto Assign = [&](COFFSection &Section) { + Section.Number = I; + Section.Symbol->Data.SectionNumber = I; + Section.Symbol->Aux[0].Aux.SectionDefinition.Number = I; ++I; - } + }; + + // Although it is not explicitly requested by the Microsoft COFF spec, + // we should avoid emitting forward associative section references, + // because MSVC link.exe as of 2017 cannot handle that. + for (const std::unique_ptr &Section : Sections) + if (!isAssociative(*Section)) + Assign(*Section); + for (const std::unique_ptr &Section : Sections) + if (isAssociative(*Section)) + Assign(*Section); } // Assign file offsets to COFF object file structures. @@ -1056,14 +1090,7 @@ // Write it all to disk... WriteFileHeader(Header); - - for (auto &Section : Sections) { - if (Section->Number != -1) { - if (Section->Relocations.size() >= 0xffff) - Section->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; - writeSectionHeader(Section->Header); - } - } + writeSectionHeaders(); // Write section contents. sections::iterator I = Sections.begin(); Index: llvm/trunk/test/DebugInfo/COFF/globals.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/globals.ll +++ llvm/trunk/test/DebugInfo/COFF/globals.ll @@ -96,7 +96,7 @@ ; OBJ: ] ; OBJ: ] ; OBJ: CodeViewDebugInfo [ -; OBJ: Section: .debug$S (7) +; OBJ: Section: .debug$S (8) ; OBJ: Magic: 0x4 ; OBJ: Subsection [ ; OBJ: SubSectionType: Symbols (0xF1) Index: llvm/trunk/test/DebugInfo/COFF/types-data-members.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/types-data-members.ll +++ llvm/trunk/test/DebugInfo/COFF/types-data-members.ll @@ -37,7 +37,7 @@ ; $ clang t.cpp -S -emit-llvm -g -gcodeview -o t.ll ; CHECK: CodeViewTypes [ -; CHECK: Section: .debug$T (10) +; CHECK: Section: .debug$T (8) ; CHECK: Magic: 0x4 ; CHECK: ArgList (0x1000) { ; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) Index: llvm/trunk/test/MC/COFF/section-comdat.s =================================================================== --- llvm/trunk/test/MC/COFF/section-comdat.s +++ llvm/trunk/test/MC/COFF/section-comdat.s @@ -161,7 +161,7 @@ // CHECK: } // CHECK: Symbol { // CHECK: Name: SecName -// CHECK: Section: SecName (9) +// CHECK: Section: SecName (11) // CHECK: AuxSectionDef { // CHECK: Selection: Associative // CHECK: AssocSection: assocSec (4) @@ -169,25 +169,25 @@ // CHECK: } // CHECK: Symbol { // CHECK: Name: SecName -// CHECK: Section: SecName (10) +// CHECK: Section: SecName (9) // CHECK: AuxSectionDef { // CHECK: Selection: Largest // CHECK: } // CHECK: } // CHECK: Symbol { // CHECK: Name: Symbol6 -// CHECK: Section: SecName (10) +// CHECK: Section: SecName (9) // CHECK: } // CHECK: Symbol { // CHECK: Name: SecName -// CHECK: Section: SecName (11) +// CHECK: Section: SecName (10) // CHECK: AuxSectionDef { // CHECK: Selection: Newest (0x7) // CHECK: } // CHECK: } // CHECK: Symbol { // CHECK: Name: Symbol7 -// CHECK: Section: SecName (11) +// CHECK: Section: SecName (10) // CHECK: } // CHECK: Symbol { // CHECK: Name: assocSec @@ -199,7 +199,7 @@ // CHECK: } // CHECK: Symbol { // CHECK: Name: Symbol5 -// CHECK: Section: SecName (9) +// CHECK: Section: SecName (11) // CHECK: } // CHECK: Symbol { // CHECK: Name: Symbol8