summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2014-07-31 22:40:35 +0000
committerRui Ueyama <ruiu@google.com>2014-07-31 22:40:35 +0000
commit140f6029ced5a1df254ea53435104a0e97069994 (patch)
treea6cfa9e4b48a6b6c04e4b95f178e9fd7adc7ff61 /lld/lib
parent9e5298549eeaf117a46757070086c023a81033e9 (diff)
downloadbcm5719-llvm-140f6029ced5a1df254ea53435104a0e97069994.tar.gz
bcm5719-llvm-140f6029ced5a1df254ea53435104a0e97069994.zip
[PECOFF] Fix section header.
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
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp19
1 files changed, 13 insertions, 6 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
index 22dd2f01ca9..07642dbc510 100644
--- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -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;
}
OpenPOWER on IntegriCloud