[lld] r200128 - [PECOFF] Emit PE32+ file header.
Rui Ueyama
ruiu at google.com
Sat Jan 25 21:34:12 PST 2014
Author: ruiu
Date: Sat Jan 25 23:34:12 2014
New Revision: 200128
URL: http://llvm.org/viewvc/llvm-project?rev=200128&view=rev
Log:
[PECOFF] Emit PE32+ file header.
Added:
lld/trunk/test/pecoff/Inputs/nop64.obj
lld/trunk/test/pecoff/peplus.test
Modified:
lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
Modified: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=200128&r1=200127&r2=200128&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Sat Jan 25 23:34:12 2014
@@ -123,6 +123,7 @@ private:
};
/// A PEHeaderChunk represents PE header including COFF header.
+template <class PEHeader>
class PEHeaderChunk : public HeaderChunk {
public:
explicit PEHeaderChunk(const PECOFFLinkingContext &ctx);
@@ -136,7 +137,7 @@ public:
void setSizeOfCode(uint64_t size) { _peHeader.SizeOfCode = size; }
void setBaseOfCode(uint32_t rva) { _peHeader.BaseOfCode = rva; }
- void setBaseOfData(uint32_t rva) { _peHeader.BaseOfData = rva; }
+ void setBaseOfData(uint32_t rva);
void setSizeOfImage(uint32_t size) { _peHeader.SizeOfImage = size; }
void setSizeOfInitializedData(uint64_t size) {
@@ -155,7 +156,7 @@ public:
private:
llvm::object::coff_file_header _coffHeader;
- llvm::object::pe32_header _peHeader;
+ PEHeader _peHeader;
};
/// A SectionHeaderTableChunk represents Section Table Header of PE/COFF
@@ -310,7 +311,8 @@ private:
std::vector<uint8_t> _contents;
};
-PEHeaderChunk::PEHeaderChunk(const PECOFFLinkingContext &ctx)
+template <class PEHeader>
+PEHeaderChunk<PEHeader>::PEHeaderChunk(const PECOFFLinkingContext &ctx)
: HeaderChunk() {
// Set the size of the chunk and initialize the header with null bytes.
_size = sizeof(llvm::COFF::PEMagic) + sizeof(_coffHeader) + sizeof(_peHeader);
@@ -400,7 +402,18 @@ PEHeaderChunk::PEHeaderChunk(const PECOF
_peHeader.NumberOfRvaAndSize = 16;
}
-void PEHeaderChunk::write(uint8_t *buffer) {
+template <>
+void PEHeaderChunk<llvm::object::pe32_header>::setBaseOfData(uint32_t rva) {
+ _peHeader.BaseOfData = rva;
+}
+
+template <>
+void PEHeaderChunk<llvm::object::pe32plus_header>::setBaseOfData(uint32_t rva) {
+ // BaseOfData field does not exist in PE32+ header.
+}
+
+template <class PEHeader>
+void PEHeaderChunk<PEHeader>::write(uint8_t *buffer) {
std::memcpy(buffer, llvm::COFF::PEMagic, sizeof(llvm::COFF::PEMagic));
buffer += sizeof(llvm::COFF::PEMagic);
std::memcpy(buffer, &_coffHeader, sizeof(_coffHeader));
@@ -742,7 +755,7 @@ public:
: _ctx(context), _numSections(0), _imageSizeInMemory(PAGE_SIZE),
_imageSizeOnDisk(0) {}
- void build(const File &linkedFile);
+ template <class PEHeader> void build(const File &linkedFile);
virtual error_code writeFile(const File &linkedFile, StringRef path);
private:
@@ -751,7 +764,6 @@ private:
void addChunk(Chunk *chunk);
void addSectionChunk(SectionChunk *chunk, SectionHeaderTableChunk *table);
void setImageSizeOnDisk();
- void setAddressOfEntryPoint(AtomChunk *text, PEHeaderChunk *peHeader);
uint64_t
calcSectionSize(llvm::COFF::SectionCharacteristics sectionType) const;
@@ -829,13 +841,14 @@ void groupAtoms(const PECOFFLinkingConte
}
// Create all chunks that consist of the output file.
+template <class PEHeader>
void PECOFFWriter::build(const File &linkedFile) {
AtomVectorMap atoms;
groupAtoms(_ctx, linkedFile, atoms);
// Create file chunks and add them to the list.
auto *dosStub = new DOSStubChunk(_ctx);
- auto *peHeader = new PEHeaderChunk(_ctx);
+ auto *peHeader = new PEHeaderChunk<PEHeader>(_ctx);
auto *dataDirectory = new DataDirectoryChunk();
auto *sectionTable = new SectionHeaderTableChunk();
addChunk(dosStub);
@@ -871,7 +884,19 @@ void PECOFFWriter::build(const File &lin
continue;
if (section->getSectionName() == ".text") {
peHeader->setBaseOfCode(section->getVirtualAddress());
- setAddressOfEntryPoint(dyn_cast<AtomChunk>(section), peHeader);
+
+ // Find the virtual address of the entry point symbol if any. PECOFF spec
+ // says that entry point for dll images is optional, in which case it must
+ // be set to 0.
+ if (_ctx.entrySymbolName().empty() && _ctx.isDll()) {
+ peHeader->setAddressOfEntryPoint(0);
+ } else {
+ uint64_t entryPointAddress =
+ dyn_cast<AtomChunk>(section)
+ ->getAtomVirtualAddress(_ctx.entrySymbolName());
+ if (entryPointAddress != 0)
+ peHeader->setAddressOfEntryPoint(entryPointAddress);
+ }
}
if (section->getSectionName() == ".data")
peHeader->setBaseOfData(section->getVirtualAddress());
@@ -897,7 +922,11 @@ void PECOFFWriter::build(const File &lin
}
error_code PECOFFWriter::writeFile(const File &linkedFile, StringRef path) {
- this->build(linkedFile);
+ if (_ctx.is64Bit()) {
+ this->build<llvm::object::pe32plus_header>(linkedFile);
+ } else {
+ this->build<llvm::object::pe32_header>(linkedFile);
+ }
uint64_t totalSize = _chunks.back()->fileOffset() + _chunks.back()->size();
OwningPtr<llvm::FileOutputBuffer> buffer;
@@ -977,21 +1006,6 @@ void PECOFFWriter::setImageSizeOnDisk()
}
}
-void PECOFFWriter::setAddressOfEntryPoint(AtomChunk *text,
- PEHeaderChunk *peHeader) {
- // Find the virtual address of the entry point symbol if any.
- // PECOFF spec says that entry point for dll images is optional, in which
- // case it must be set to 0.
- if (_ctx.entrySymbolName().empty() && _ctx.isDll()) {
- peHeader->setAddressOfEntryPoint(0);
- } else {
- uint64_t entryPointAddress =
- text->getAtomVirtualAddress(_ctx.entrySymbolName());
- if (entryPointAddress != 0)
- peHeader->setAddressOfEntryPoint(entryPointAddress);
- }
-}
-
uint64_t PECOFFWriter::calcSectionSize(
llvm::COFF::SectionCharacteristics sectionType) const {
uint64_t ret = 0;
Added: lld/trunk/test/pecoff/Inputs/nop64.obj
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/nop64.obj?rev=200128&view=auto
==============================================================================
Binary files lld/trunk/test/pecoff/Inputs/nop64.obj (added) and lld/trunk/test/pecoff/Inputs/nop64.obj Sat Jan 25 23:34:12 2014 differ
Added: lld/trunk/test/pecoff/peplus.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/peplus.test?rev=200128&view=auto
==============================================================================
--- lld/trunk/test/pecoff/peplus.test (added)
+++ lld/trunk/test/pecoff/peplus.test Sat Jan 25 23:34:12 2014
@@ -0,0 +1,85 @@
+# RUN: lld -flavor link /out:%t.exe /subsystem:console /machine:x64 \
+# RUN: /entry:start -- %p/Inputs/nop64.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+CHECK: Format: COFF-x86-64
+CHECK-NEXT: Arch: x86_64
+CHECK-NEXT: AddressSize: 64bit
+CHECK-NEXT: ImageFileHeader {
+CHECK-NEXT: Machine: IMAGE_FILE_MACHINE_AMD64 (0x8664)
+CHECK-NEXT: SectionCount: 3
+CHECK-NEXT: TimeDateStamp:
+CHECK-NEXT: PointerToSymbolTable: 0x0
+CHECK-NEXT: SymbolCount: 0
+CHECK-NEXT: OptionalHeaderSize: 224
+CHECK-NEXT: Characteristics [ (0x102)
+CHECK-NEXT: IMAGE_FILE_32BIT_MACHINE (0x100)
+CHECK-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
+CHECK-NEXT: ]
+CHECK-NEXT: }
+CHECK-NEXT: ImageOptionalHeader {
+CHECK-NEXT: MajorLinkerVersion: 0
+CHECK-NEXT: MinorLinkerVersion: 0
+CHECK-NEXT: SizeOfCode: 1
+CHECK-NEXT: SizeOfInitializedData: 108
+CHECK-NEXT: SizeOfUninitializedData: 0
+CHECK-NEXT: AddressOfEntryPoint: 0x2000
+CHECK-NEXT: BaseOfCode: 0x2000
+CHECK-NEXT: ImageBase: 0x400000
+CHECK-NEXT: SectionAlignment: 4096
+CHECK-NEXT: FileAlignment: 512
+CHECK-NEXT: MajorOperatingSystemVersion: 6
+CHECK-NEXT: MinorOperatingSystemVersion: 0
+CHECK-NEXT: MajorImageVersion: 0
+CHECK-NEXT: MinorImageVersion: 0
+CHECK-NEXT: MajorSubsystemVersion: 6
+CHECK-NEXT: MinorSubsystemVersion: 0
+CHECK-NEXT: SizeOfImage: 12288
+CHECK-NEXT: SizeOfHeaders: 512
+CHECK-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
+CHECK-NEXT: Subsystem [ (0x8540)
+CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
+CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_NO_SEH (0x400)
+CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
+CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
+CHECK-NEXT: ]
+CHECK-NEXT: SizeOfStackReserve: 1048576
+CHECK-NEXT: SizeOfStackCommit: 4096
+CHECK-NEXT: SizeOfHeapReserve: 1048576
+CHECK-NEXT: SizeOfHeapCommit: 4096
+CHECK-NEXT: NumberOfRvaAndSize: 16
+CHECK-NEXT: DataDirectory {
+CHECK-NEXT: ExportTableRVA: 0x0
+CHECK-NEXT: ExportTableSize: 0x0
+CHECK-NEXT: ImportTableRVA: 0x0
+CHECK-NEXT: ImportTableSize: 0x0
+CHECK-NEXT: ResourceTableRVA: 0x0
+CHECK-NEXT: ResourceTableSize: 0x0
+CHECK-NEXT: ExceptionTableRVA: 0x0
+CHECK-NEXT: ExceptionTableSize: 0x0
+CHECK-NEXT: CertificateTableRVA: 0x0
+CHECK-NEXT: CertificateTableSize: 0x0
+CHECK-NEXT: BaseRelocationTableRVA: 0x0
+CHECK-NEXT: BaseRelocationTableSize: 0x0
+CHECK-NEXT: DebugRVA: 0x0
+CHECK-NEXT: DebugSize: 0x0
+CHECK-NEXT: ArchitectureRVA: 0x0
+CHECK-NEXT: ArchitectureSize: 0x0
+CHECK-NEXT: GlobalPtrRVA: 0x0
+CHECK-NEXT: GlobalPtrSize: 0x0
+CHECK-NEXT: TLSTableRVA: 0x0
+CHECK-NEXT: TLSTableSize: 0x0
+CHECK-NEXT: LoadConfigTableRVA: 0x0
+CHECK-NEXT: LoadConfigTableSize: 0x0
+CHECK-NEXT: BoundImportRVA: 0x0
+CHECK-NEXT: BoundImportSize: 0x0
+CHECK-NEXT: IATRVA: 0x0
+CHECK-NEXT: IATSize: 0x0
+CHECK-NEXT: DelayImportDescriptorRVA: 0x0
+CHECK-NEXT: DelayImportDescriptorSize: 0x0
+CHECK-NEXT: CLRRuntimeHeaderRVA: 0x0
+CHECK-NEXT: CLRRuntimeHeaderSize: 0x0
+CHECK-NEXT: ReservedRVA: 0x0
+CHECK-NEXT: ReservedSize: 0x0
+CHECK-NEXT: }
+CHECK-NEXT: }
More information about the llvm-commits
mailing list