@@ -192,6 +192,7 @@ class Writer {
192
192
void writeSections ();
193
193
void writeBuildId ();
194
194
void sortExceptionTable ();
195
+ void sortCRTSectionChunks (std::vector<Chunk *> &Chunks);
195
196
196
197
llvm::Optional<coff_symbol16> createSymbol (Defined *D);
197
198
size_t addEntryToStringTable (StringRef Str);
@@ -732,13 +733,18 @@ void Writer::createSections() {
732
733
StringRef Name = getOutputSectionName (Pair.first .first );
733
734
uint32_t OutChars = Pair.first .second ;
734
735
735
- // In link.exe, there is a special case for the I386 target where .CRT
736
- // sections are treated as if they have output characteristics DATA | R if
737
- // their characteristics are DATA | R | W. This implements the same special
738
- // case for all architectures.
739
- if (Name == " .CRT " )
736
+ if (Name == " .CRT" ) {
737
+ // In link.exe, there is a special case for the I386 target where .CRT
738
+ // sections are treated as if they have output characteristics DATA | R if
739
+ // their characteristics are DATA | R | W. This implements the same
740
+ // special case for all architectures.
740
741
OutChars = DATA | R;
741
742
743
+ log (" Processing section " + Pair.first .first + " -> " + Name);
744
+
745
+ sortCRTSectionChunks (Pair.second );
746
+ }
747
+
742
748
OutputSection *Sec = CreateSection (Name, OutChars);
743
749
std::vector<Chunk *> &Chunks = Pair.second ;
744
750
for (Chunk *C : Chunks)
@@ -1577,6 +1583,42 @@ void Writer::sortExceptionTable() {
1577
1583
errs () << " warning: don't know how to handle .pdata.\n " ;
1578
1584
}
1579
1585
1586
+ // The CRT section contains, among other things, the array of function
1587
+ // pointers that initialize every global variable that is not trivially
1588
+ // constructed. The CRT calls them one after the other prior to invoking
1589
+ // main().
1590
+ //
1591
+ // As per C++ spec, 3.6.2/2.3,
1592
+ // "Variables with ordered initialization defined within a single
1593
+ // translation unit shall be initialized in the order of their definitions
1594
+ // in the translation unit"
1595
+ //
1596
+ // It is therefore critical to sort the chunks containing the function
1597
+ // pointers in the order that they are listed in the object file (top to
1598
+ // bottom), otherwise global objects might not be initialized in the
1599
+ // correct order.
1600
+ void Writer::sortCRTSectionChunks (std::vector<Chunk *> &Chunks) {
1601
+ auto SectionChunkOrder = [](const Chunk *A, const Chunk *B) {
1602
+ auto SA = dyn_cast<SectionChunk>(A);
1603
+ auto SB = dyn_cast<SectionChunk>(B);
1604
+ assert (SA && SB && " Non-section chunks in CRT section!" );
1605
+
1606
+ StringRef SAObj = SA->File ->MB .getBufferIdentifier ();
1607
+ StringRef SBObj = SB->File ->MB .getBufferIdentifier ();
1608
+
1609
+ return SAObj == SBObj && SA->getSectionNumber () < SB->getSectionNumber ();
1610
+ };
1611
+ std::stable_sort (Chunks.begin (), Chunks.end (), SectionChunkOrder);
1612
+
1613
+ if (Config->Verbose ) {
1614
+ for (auto &C : Chunks) {
1615
+ auto SC = dyn_cast<SectionChunk>(C);
1616
+ log (" " + SC->File ->MB .getBufferIdentifier ().str () +
1617
+ " , SectionID: " + Twine (SC->getSectionNumber ()));
1618
+ }
1619
+ }
1620
+ }
1621
+
1580
1622
OutputSection *Writer::findSection (StringRef Name) {
1581
1623
for (OutputSection *Sec : OutputSections)
1582
1624
if (Sec->Name == Name)
0 commit comments