[PECOFF] Fix section header.
authorRui Ueyama <ruiu@google.com>
Thu, 31 Jul 2014 22:40:35 +0000 (22:40 +0000)
committerRui Ueyama <ruiu@google.com>
Thu, 31 Jul 2014 22:40:35 +0000 (22:40 +0000)
The PE/COFF spec says that SizeOfRawData field in the section
header must be a multiple of FileAlignment from the optional
header. LLD emits 512 as FileAlignment, so it must have been
a multiple of 512.

LLD did not follow that. It emitted the actual section size
without the last padding as the SizeOfRawData. Although it's
not correct as per the spec, the Windows loader doesn't seem
to actually bother to check that. Executables created by LLD
worked fine.

However, tools dealing with executalbe files may expect it
to be the correct value, and one instance of it is mt.exe
tool distributed as a part of Windows SDK.

If CMake is invoked with "-E vs_link_exe" option, it silently
run mt.exe to embed a resource file to the resulting file.
And mt.exe sometimes breaks an input file if it's section
header does not follow the standard. That caused a misterous
error that CMake with Ninja occasionally produces a broken
executable.

This patch fixes the section header to make mt.exe and
other tools happy.

llvm-svn: 214453

12 files changed:
lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
lld/test/pecoff/alignment.test
lld/test/pecoff/associative.test
lld/test/pecoff/base-reloc.test
lld/test/pecoff/bss-section.test
lld/test/pecoff/hello.test
lld/test/pecoff/merge-largest.test
lld/test/pecoff/merge-same-size.test
lld/test/pecoff/nonstandard-sections.test
lld/test/pecoff/pe32plus.test
lld/test/pecoff/section-renaming.test
lld/test/pecoff/trivial.test

index 22dd2f0..07642db 100644 (file)
@@ -75,6 +75,7 @@ public:
   virtual ~Chunk() {}
   virtual void write(uint8_t *buffer) = 0;
   virtual uint64_t size() const { return _size; }
+  virtual uint64_t onDiskSize() const { return size(); }
   virtual uint64_t align() const { return 1; }
 
   uint64_t fileOffset() const { return _fileOffset; }
@@ -175,6 +176,12 @@ private:
 
 class SectionChunk : public Chunk {
 public:
+  uint64_t onDiskSize() const override {
+    if (_characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+      return 0;
+    return llvm::RoundUpToAlignment(size(), SECTOR_SIZE);
+  }
+
   uint64_t align() const override { return SECTOR_SIZE; }
   uint32_t getCharacteristics() const { return _characteristics; }
   StringRef getSectionName() const { return _sectionName; }
@@ -730,19 +737,18 @@ SectionHeaderTableChunk::createSectionHeader(SectionChunk *chunk) {
                std::min(sizeof(header.Name), sectionName.size()));
 
   uint32_t characteristics = chunk->getCharacteristics();
+  header.VirtualSize = chunk->size();
   header.VirtualAddress = chunk->getVirtualAddress();
+  header.SizeOfRawData = chunk->onDiskSize();
   header.PointerToRelocations = 0;
   header.PointerToLinenumbers = 0;
   header.NumberOfRelocations = 0;
   header.NumberOfLinenumbers = 0;
-  header.SizeOfRawData = chunk->size();
   header.Characteristics = characteristics;
 
   if (characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
-    header.VirtualSize = 0;
     header.PointerToRawData = 0;
   } else {
-    header.VirtualSize = chunk->size();
     header.PointerToRawData = chunk->fileOffset();
   }
   return header;
@@ -1018,7 +1024,8 @@ std::error_code PECOFFWriter::writeFile(const File &linkedFile,
     this->build<llvm::object::pe32_header>(linkedFile);
   }
 
-  uint64_t totalSize = _chunks.back()->fileOffset() + _chunks.back()->size();
+  uint64_t totalSize =
+      _chunks.back()->fileOffset() + _chunks.back()->onDiskSize();
   std::unique_ptr<llvm::FileOutputBuffer> buffer;
   std::error_code ec = llvm::FileOutputBuffer::create(
       path, totalSize, buffer, llvm::FileOutputBuffer::F_executable);
@@ -1144,7 +1151,7 @@ void PECOFFWriter::setImageSizeOnDisk() {
     _imageSizeOnDisk =
         llvm::RoundUpToAlignment(_imageSizeOnDisk, chunk->align());
     chunk->setFileOffset(_imageSizeOnDisk);
-    _imageSizeOnDisk += chunk->size();
+    _imageSizeOnDisk += chunk->onDiskSize();
   }
 }
 
@@ -1154,7 +1161,7 @@ uint64_t PECOFFWriter::calcSectionSize(
   for (auto &cp : _chunks)
     if (SectionChunk *chunk = dyn_cast<SectionChunk>(&*cp))
       if (chunk->getCharacteristics() & sectionType)
-        ret += chunk->size();
+        ret += chunk->onDiskSize();
   return ret;
 }
 
index f3d8d06..78f1c97 100644 (file)
@@ -5,7 +5,7 @@
 # RUN: llvm-readobj -sections %t.exe | FileCheck %s
 
 CHECK: Name: .bss (2E 62 73 73 00 00 00 00)
-CHECK: RawDataSize: 18
+CHECK: RawDataSize: 0
 
 CHECK:      Name: .data (2E 64 61 74 61 00 00 00)
 CHECK-NEXT: VirtualSize: 0x6
index f998bef..6c4eaf0 100644 (file)
@@ -7,4 +7,4 @@
 # RUN: obj2yaml %t.exe | FileCheck %s
 
 CHECK: - Name: .CRT
-CHECK:   SectionData: '77777777'
+CHECK:   SectionData: '777777770000
index 15c3a02..8b2246f 100644 (file)
@@ -38,7 +38,7 @@ BASEREL-HEADER:     BaseRelocationTableSize: 0xC
 BASEREL-HEADER:     Name: .reloc (2E 72 65 6C 6F 63 00 00)
 BASEREL-HEADER-NEXT:     VirtualSize: 0xC
 BASEREL-HEADER-NEXT:     VirtualAddress: 0x3000
-BASEREL-HEADER-NEXT:     RawDataSize: 12
+BASEREL-HEADER-NEXT:     RawDataSize: 512
 BASEREL-HEADER-NEXT:     PointerToRawData: 0x600
 BASEREL-HEADER-NEXT:     PointerToRelocations: 0x0
 BASEREL-HEADER-NEXT:     PointerToLineNumbers: 0x0
index d45baab..4181e99 100644 (file)
@@ -5,9 +5,9 @@
 CHECK:       Section {
 CHECK:         Number: 1
 CHECK-NEXT:    Name: .bss
-CHECK-NEXT:    VirtualSize: 0x0
+CHECK-NEXT:    VirtualSize: 0x320
 CHECK-NEXT:    VirtualAddress: 0x1000
-CHECK-NEXT:    RawDataSize: 800
+CHECK-NEXT:    RawDataSize: 0
 CHECK-NEXT:    PointerToRawData: 0x0
 CHECK-NEXT:    PointerToRelocations: 0x0
 CHECK-NEXT:    PointerToLineNumbers: 0x0
index 3760fd5..679b8b3 100644 (file)
@@ -4,7 +4,7 @@
 # RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=FILE %s
 
 FILE: ImageOptionalHeader {
-FILE:   SizeOfInitializedData: 30
+FILE:   SizeOfInitializedData: 1024
 FILE:   SizeOfHeaders: 512
 FILE: }
 
@@ -20,7 +20,7 @@ SECTIONS-NEXT:     Number: 1
 SECTIONS-NEXT:     Name: .data
 SECTIONS-NEXT:     VirtualSize: 0x12
 SECTIONS-NEXT:     VirtualAddress: 0x1000
-SECTIONS-NEXT:     RawDataSize: 18
+SECTIONS-NEXT:     RawDataSize: 512
 SECTIONS-NEXT:     PointerToRawData: 0x200
 SECTIONS-NEXT:     PointerToRelocations: 0x0
 SECTIONS-NEXT:     PointerToLineNumbers: 0x0
@@ -37,7 +37,7 @@ SECTIONS-NEXT:     Number: 2
 SECTIONS-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
 SECTIONS-NEXT:     VirtualSize: 0x1C
 SECTIONS-NEXT:     VirtualAddress: 0x2000
-SECTIONS-NEXT:     RawDataSize: 28
+SECTIONS-NEXT:     RawDataSize: 512
 SECTIONS-NEXT:     PointerToRawData: 0x400
 SECTIONS-NEXT:     PointerToRelocations: 0x0
 SECTIONS-NEXT:     PointerToLineNumbers: 0x0
index 73d2d94..c3ee96c 100644 (file)
@@ -21,4 +21,4 @@ READOBJ-NEXT:     Number: 1
 READOBJ-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
 READOBJ-NEXT:     VirtualSize: 0x8
 READOBJ-NEXT:     VirtualAddress: 0x1000
-READOBJ-NEXT:     RawDataSize: 8
+READOBJ-NEXT:     RawDataSize: 512
index a7c8c9f..c2918a2 100644 (file)
@@ -29,4 +29,4 @@ READOBJ-NEXT:     Number: 1
 READOBJ-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
 READOBJ-NEXT:     VirtualSize: 0x7
 READOBJ-NEXT:     VirtualAddress: 0x1000
-READOBJ-NEXT:     RawDataSize: 7
+READOBJ-NEXT:     RawDataSize: 512
index 27c5fb3..2ca1816 100644 (file)
@@ -10,7 +10,7 @@ CHECK-NEXT:     Number: 1
 CHECK-NEXT:     Name: .bar (2E 62 61 72 00 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x4
 CHECK-NEXT:     VirtualAddress: 0x1000
-CHECK-NEXT:     RawDataSize: 4
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0x400
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
@@ -26,7 +26,7 @@ CHECK-NEXT:     Number: 2
 CHECK-NEXT:     Name: .data (2E 64 61 74 61 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x4
 CHECK-NEXT:     VirtualAddress: 0x2000
-CHECK-NEXT:     RawDataSize: 4
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0x600
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
@@ -43,7 +43,7 @@ CHECK-NEXT:     Number: 3
 CHECK-NEXT:     Name: .foo (2E 66 6F 6F 00 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x4
 CHECK-NEXT:     VirtualAddress: 0x3000
-CHECK-NEXT:     RawDataSize: 4
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0x800
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
@@ -60,7 +60,7 @@ CHECK-NEXT:     Number: 4
 CHECK-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x4
 CHECK-NEXT:     VirtualAddress: 0x4000
-CHECK-NEXT:     RawDataSize: 4
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0xA00
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
index fcd14aa..652e647 100644 (file)
@@ -22,7 +22,7 @@ CHECK-NEXT: }
 CHECK-NEXT: ImageOptionalHeader {
 CHECK-NEXT:   MajorLinkerVersion: 0
 CHECK-NEXT:   MinorLinkerVersion: 0
-CHECK-NEXT:   SizeOfCode: 1
+CHECK-NEXT:   SizeOfCode: 512
 CHECK-NEXT:   SizeOfInitializedData: 0
 CHECK-NEXT:   SizeOfUninitializedData: 0
 CHECK-NEXT:   AddressOfEntryPoint: 0x1000
index 6b84a0d..d4fc154 100644 (file)
@@ -12,7 +12,7 @@ CHECK-NEXT:     Number: 1
 CHECK-NEXT:     Name: .data (2E 64 61 74 61 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x4
 CHECK-NEXT:     VirtualAddress: 0x1000
-CHECK-NEXT:     RawDataSize: 4
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0x200
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
@@ -29,7 +29,7 @@ CHECK-NEXT:     Number: 2
 CHECK-NEXT:     Name: .hoge (2E 68 6F 67 65 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x4
 CHECK-NEXT:     VirtualAddress: 0x2000
-CHECK-NEXT:     RawDataSize: 4
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0x400
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
@@ -46,7 +46,7 @@ CHECK-NEXT:     Number: 3
 CHECK-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
 CHECK-NEXT:     VirtualSize: 0x8
 CHECK-NEXT:     VirtualAddress: 0x3000
-CHECK-NEXT:     RawDataSize: 8
+CHECK-NEXT:     RawDataSize: 512
 CHECK-NEXT:     PointerToRawData: 0x600
 CHECK-NEXT:     PointerToRelocations: 0x0
 CHECK-NEXT:     PointerToLineNumbers: 0x0
index 6f149d0..b9e3bcb 100644 (file)
@@ -30,7 +30,7 @@ FILE-NEXT: }
 FILE-NEXT: ImageOptionalHeader {
 FILE-NEXT:   MajorLinkerVersion: 0
 FILE-NEXT:   MinorLinkerVersion: 0
-FILE-NEXT:   SizeOfCode: 6
+FILE-NEXT:   SizeOfCode: 512
 FILE-NEXT:   SizeOfInitializedData: 0
 FILE-NEXT:   SizeOfUninitializedData: 0
 FILE-NEXT:   AddressOfEntryPoint: 0x1000
@@ -69,7 +69,7 @@ SECTIONS-NEXT:     Number: 1
 SECTIONS-NEXT:     Name: .text (2E 74 65 78 74 00 00 00)
 SECTIONS-NEXT:     VirtualSize: 0x6
 SECTIONS-NEXT:     VirtualAddress: 0x1000
-SECTIONS-NEXT:     RawDataSize: 6
+SECTIONS-NEXT:     RawDataSize: 512
 SECTIONS-NEXT:     PointerToRawData: 0x200
 SECTIONS-NEXT:     PointerToRelocations: 0x0
 SECTIONS-NEXT:     PointerToLineNumbers: 0x0