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);
}
}
-void WinCOFFObjectWriter::writeSectionHeader(const COFF::section &S) {
- 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);
+// 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<COFFSection *> 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;
+ });
+
+ 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) {
}
}
+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<COFFSection> &Section : Sections)
+ if (!isAssociative(*Section))
+ Assign(*Section);
+ for (const std::unique_ptr<COFFSection> &Section : Sections)
+ if (isAssociative(*Section))
+ Assign(*Section);
}
// Assign file offsets to COFF object file structures.
// 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();
// CHECK: }
// CHECK: Symbol {
// CHECK: Name: SecName
-// CHECK: Section: SecName (9)
+// CHECK: Section: SecName (11)
// CHECK: AuxSectionDef {
// CHECK: Selection: Associative
// CHECK: AssocSection: assocSec (4)
// 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
// CHECK: }
// CHECK: Symbol {
// CHECK: Name: Symbol5
-// CHECK: Section: SecName (9)
+// CHECK: Section: SecName (11)
// CHECK: }
// CHECK: Symbol {
// CHECK: Name: Symbol8