void WriteOptionalHeaders()
{
Section text = GetSection(".text");
WriteUInt16((ushort)(!pe64 ? 0x10b : 0x20b)); // Magic
WriteByte(8); // LMajor
WriteByte(0); // LMinor
WriteUInt32(text.SizeOfRawData); // CodeSize
uint dataSize = 0;
foreach (Section sect in sections)
{
sect.PointerToRawData += Align(GetHeaderSize(), file_alignment);
if (sect.Name != ".text")
{
dataSize += sect.SizeOfRawData;
}
}
WriteUInt32(dataSize); // InitializedDataSize
WriteUInt32(0); // UninitializedDataSize
var entry_point_rva = text_map.GetRVA(TextSegment.StartupStub);
if (module.Architecture == TargetArchitecture.IA64)
{
entry_point_rva += 0x20;
}
WriteUInt32(entry_point_rva); // EntryPointRVA
WriteUInt32(text_rva); // BaseOfCode
if (!pe64)
{
WriteUInt32(0); // BaseOfData
WriteUInt32((uint)image_base); // ImageBase
}
else
{
WriteUInt64(image_base); // ImageBase
}
WriteUInt32(section_alignment); // SectionAlignment
WriteUInt32(file_alignment); // FileAlignment
WriteUInt16(4); // OSMajor
WriteUInt16(0); // OSMinor
WriteUInt16(0); // UserMajor
WriteUInt16(0); // UserMinor
WriteUInt16(4); // SubSysMajor
WriteUInt16(0); // SubSysMinor
WriteUInt32(0); // Reserved
Section reloc = GetSection(".reloc");
Section last = sections[sections.Count - 1];
foreach (Section sect in sections)
{
if (sect.VirtualAddress > last.VirtualAddress)
{
last = sect;
}
}
WriteUInt32(last.VirtualAddress + Align(last.VirtualSize, section_alignment)); // ImageSize
WriteUInt32(text.PointerToRawData); // HeaderSize
WriteUInt32(0); // Checksum
WriteUInt16(GetSubSystem()); // SubSystem
WriteUInt16(0x8540); // DLLFlags
const ulong stack_reserve = 0x100000;
const ulong stack_commit = 0x1000;
const ulong heap_reserve = 0x100000;
const ulong heap_commit = 0x1000;
if (!pe64)
{
WriteUInt32((uint)stack_reserve);
WriteUInt32((uint)stack_commit);
WriteUInt32((uint)heap_reserve);
WriteUInt32((uint)heap_commit);
}
else
{
WriteUInt64(stack_reserve);
WriteUInt64(stack_commit);
WriteUInt64(heap_reserve);
WriteUInt64(heap_commit);
}
WriteUInt32(0); // LoaderFlags
WriteUInt32(16); // NumberOfDataDir
WriteZeroDataDirectory(); // ExportTable
WriteDataDirectory(text_map.GetDataDirectory(TextSegment.ImportDirectory)); // ImportTable
Section rsrc = GetSection(".rsrc");
if (rsrc != null) // ResourceTable
{
WriteUInt32(rsrc.VirtualAddress);
WriteUInt32(rsrc.VirtualSize);
}
else
{
WriteZeroDataDirectory();
}
WriteZeroDataDirectory(); // ExceptionTable
WriteZeroDataDirectory(); // CertificateTable
WriteUInt32(reloc.VirtualAddress); // BaseRelocationTable
WriteUInt32(reloc.VirtualSize);
if (text_map.GetLength(TextSegment.DebugDirectory) > 0)
{
WriteUInt32(text_map.GetRVA(TextSegment.DebugDirectory));
WriteUInt32(28u);
}
else
{
WriteZeroDataDirectory();
}
WriteZeroDataDirectory(); // Copyright
WriteZeroDataDirectory(); // GlobalPtr
WriteZeroDataDirectory(); // TLSTable
WriteZeroDataDirectory(); // LoadConfigTable
WriteZeroDataDirectory(); // BoundImport
WriteDataDirectory(text_map.GetDataDirectory(TextSegment.ImportAddressTable)); // IAT
WriteZeroDataDirectory(); // DelayImportDesc
WriteDataDirectory(text_map.GetDataDirectory(TextSegment.CLIHeader)); // CLIHeader
WriteZeroDataDirectory(); // Reserved
}