]> granicus.if.org Git - llvm/commitdiff
MC/COFF: Do not emit forward associative section referenceds.
authorRui Ueyama <ruiu@google.com>
Fri, 17 Feb 2017 17:32:54 +0000 (17:32 +0000)
committerRui Ueyama <ruiu@google.com>
Fri, 17 Feb 2017 17:32:54 +0000 (17:32 +0000)
MSVC link.exe cannot handle associative sections that refer later
sections in the section header. Technically, such COFF object doesn't
violate the Microsoft COFF spec, as the spec doesn't say anything
about that, but still we should avoid doing that to make it compatible
with MS tools.

This patch assigns smaller section numbers to non-associative sections
and larger numbers to associative sections. This should resolve the
compatibility issue.

Differential Revision: https://reviews.llvm.org/D30080

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295464 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/WinCOFFObjectWriter.cpp
test/DebugInfo/COFF/globals.ll
test/DebugInfo/COFF/types-data-members.ll
test/MC/COFF/section-comdat.s

index ce8b2005e869daee794b6b2043ed38527f3a3488..e1fde90af7dd1b0bd62e24bd140495e244eebc7d 100644 (file)
@@ -177,7 +177,7 @@ public:
   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::WriteAuxiliarySymbols(
   }
 }
 
-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) {
@@ -895,14 +914,29 @@ void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
   }
 }
 
+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.
@@ -1056,14 +1090,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
 
   // 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 e560e4f9806f19992b5ba91abd8816dae404ca86..aadf6ab557f9b1cf4b53b59f39fd24da7cc6ced4 100644 (file)
@@ -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 9276b962ac8cf39b3229ccd16db31ee247097929..275af969a48e9a4b475fee6b66e66d56333d39c0 100644 (file)
@@ -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 e7052d8f5ae3f98fd4285205c21076ad428d6be4..7669ffbadc3aee82fc7ed75cdf463b319f7fa682 100644 (file)
@@ -161,7 +161,7 @@ Symbol8:
 // 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 @@ Symbol8:
 // 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 @@ Symbol8:
 // CHECK:   }
 // CHECK:   Symbol {
 // CHECK:     Name: Symbol5
-// CHECK:     Section: SecName (9)
+// CHECK:     Section: SecName (11)
 // CHECK:   }
 // CHECK:   Symbol {
 // CHECK:     Name: Symbol8