From 883ac8c873b496916ea5fe0787d097dd5e1dbab3 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 27 Mar 2013 21:17:16 +0100 Subject: [PATCH] x64 exe support --- .../WinLauncher/WinLauncher.vcxproj | 4 +- .../src/com/pme/exe/Bin.java | 42 ++++++++++++++++--- .../src/com/pme/exe/ExeFormat.java | 8 ++++ .../src/com/pme/exe/ExeReader.java | 27 ++++++++++-- .../src/com/pme/exe/ImageFileHeader.java | 9 +++- .../src/com/pme/exe/ImageOptionalHeader.java | 27 ++++++++---- .../src/com/pme/exe/PeHeaderReader.java | 26 ++++++------ .../com/pme/launcher/LauncherGenerator.java | 6 ++- .../src/com/pme/util/BitsUtil.java | 8 ++++ 9 files changed, 125 insertions(+), 32 deletions(-) create mode 100644 tools/launcher-generator/src/com/pme/exe/ExeFormat.java diff --git a/native/WinLauncher/WinLauncher/WinLauncher.vcxproj b/native/WinLauncher/WinLauncher/WinLauncher.vcxproj index acbee35bbb63..598b5bf49298 100644 --- a/native/WinLauncher/WinLauncher/WinLauncher.vcxproj +++ b/native/WinLauncher/WinLauncher/WinLauncher.vcxproj @@ -68,7 +68,7 @@ true - C:\Java\jdk1.6.0_37\include;C:\Java\jdk1.6.0_37\include\win32;$(IncludePath) + C:\Java\jdk1.6.0_43\include;C:\Java\jdk1.6.0_43\include\win32;$(IncludePath) false @@ -76,7 +76,7 @@ false - C:\Java\jdk1.6.0_37\include;C:\Java\jdk1.6.0_37\include\win32;$(IncludePath) + C:\Java\jdk1.6.0_43\include;C:\Java\jdk1.6.0_43\include\win32;$(IncludePath) diff --git a/tools/launcher-generator/src/com/pme/exe/Bin.java b/tools/launcher-generator/src/com/pme/exe/Bin.java index 8d4e7862606a..1b3edb7a67c0 100644 --- a/tools/launcher-generator/src/com/pme/exe/Bin.java +++ b/tools/launcher-generator/src/com/pme/exe/Bin.java @@ -251,11 +251,6 @@ public abstract class Bin { myValue = value; return this; } - - public Value setValue(short value) { - myValue = BitsUtil.revertBytesOfShort(value); - return this; - } } public static class Byte extends Value { @@ -362,6 +357,43 @@ public abstract class Bin { } } + public static class LongLong extends Value { + public LongLong(String name) { + super(name); + } + + @Override + public long getValue() { + return BitsUtil.revertBytesOfLong(getRawValue()); + } + + @Override + public Value setValue(long value) { + setRawValue(BitsUtil.revertBytesOfLong(value)); + return this; + } + + @Override + public long sizeInBytes() { + return 8; + } + + @Override + public void read(DataInput stream) throws IOException { + setRawValue(stream.readLong()); + } + + @Override + public void write(DataOutput stream) throws IOException { + stream.writeLong(getRawValue()); + } + + @Override + public void report(OutputStreamWriter writer) throws IOException { + _report(writer, getDescription() + " : " + Long.toHexString(getValue())); + } + } + public static class Padding extends Bin { private int myBytes; diff --git a/tools/launcher-generator/src/com/pme/exe/ExeFormat.java b/tools/launcher-generator/src/com/pme/exe/ExeFormat.java new file mode 100644 index 000000000000..90a4c427eca6 --- /dev/null +++ b/tools/launcher-generator/src/com/pme/exe/ExeFormat.java @@ -0,0 +1,8 @@ +package com.pme.exe; + +/** + * @author yole + */ +public enum ExeFormat { + UNKNOWN, X86, X64 +} diff --git a/tools/launcher-generator/src/com/pme/exe/ExeReader.java b/tools/launcher-generator/src/com/pme/exe/ExeReader.java index 20d7a101c19b..02b71c8631da 100644 --- a/tools/launcher-generator/src/com/pme/exe/ExeReader.java +++ b/tools/launcher-generator/src/com/pme/exe/ExeReader.java @@ -19,7 +19,10 @@ package com.pme.exe; import com.pme.exe.res.ValuesAdd; -import java.io.*; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.io.OutputStreamWriter; /** * Date: Mar 30, 2006 @@ -33,7 +36,8 @@ public class ExeReader extends Bin.Structure{ private Bin.Bytes myBytes; private Bin.Bytes myMsDosStub; private MsDosHeader myMsDosHeader; - public ExeReader(String name) { + + public ExeReader(String name, ExeFormat exeFormat) { super(name); myMsDosHeader = new MsDosHeader(); addMember( myMsDosHeader ); @@ -41,8 +45,11 @@ public class ExeReader extends Bin.Structure{ ValuesAdd size = new ValuesAdd( member, new DWord("").setValue( myMsDosHeader.sizeInBytes() ) ); myMsDosStub = new Bytes( "MsDos stub program", size ); addMember( myMsDosStub ); - myPeHeader = new PeHeaderReader( member ); + myPeHeader = new PeHeaderReader(member, exeFormat); addMember( myPeHeader ); + if (exeFormat == ExeFormat.UNKNOWN) { + return; + } myImageOptionalHeader = (ImageOptionalHeader) myPeHeader.getMember("Image Optional Header"); mySectionHeaders = (ArrayOfBins)myPeHeader.getMember( "ImageSectionHeaders" ); addSizeHolder( myImageOptionalHeader.getValueMember( "SizeOfImage" ) ); //b164 @@ -89,6 +96,9 @@ public class ExeReader extends Bin.Structure{ public void read(DataInput stream) throws IOException { super.read(stream); + if (mySectionHeaders == null) { + return; + } long filePointer = getOffset() + sizeOfHeaders(); @@ -144,4 +154,15 @@ public class ExeReader extends Bin.Structure{ section.report(writer); } } + + public ExeFormat getExeFormat() { + long machine = myPeHeader.getImageFileHeader().getMachine(); + if (machine == 0x14c) { + return ExeFormat.X86; + } + if (machine == 0x8664) { + return ExeFormat.X64; + } + throw new UnsupportedOperationException("Unsupported machine code " + machine); + } } diff --git a/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java b/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java index 50eb512b7f65..998db0fdd49d 100644 --- a/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java +++ b/tools/launcher-generator/src/com/pme/exe/ImageFileHeader.java @@ -25,9 +25,12 @@ import java.io.OutputStreamWriter; * Time: 5:17:01 PM */ public class ImageFileHeader extends Bin.Structure { + private final ImageFileHeader.Machine myMachine; + public ImageFileHeader() { super("Image File Header"); - addMember( new Machine( ) ); + myMachine = new Machine(); + addMember(myMachine); addMember( new Word( "NumberOfSections" ) ); addMember( new DWord( "TimeDateStamp" ) ); addMember( new DWord( "PointerToSymbolTable" ) ); @@ -36,6 +39,10 @@ public class ImageFileHeader extends Bin.Structure { addMember( new Word( "Characteristics" ) ); } + public long getMachine() { + return myMachine.getValue(); + } + class Machine extends Bin.Word{ public Machine() { diff --git a/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java b/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java index b8c152c52439..373b79a84922 100644 --- a/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java +++ b/tools/launcher-generator/src/com/pme/exe/ImageOptionalHeader.java @@ -22,7 +22,7 @@ package com.pme.exe; * Time: 6:01:16 PM */ public class ImageOptionalHeader extends Bin.Structure { - public ImageOptionalHeader() { + public ImageOptionalHeader(ExeFormat format) { super("Image Optional Header"); addMember( new Word( "Magic" ) ); addMember( new Byte( "MajorLinkerVersion")); @@ -32,8 +32,13 @@ public class ImageOptionalHeader extends Bin.Structure { addMember( new DWord( "SizeOfUninitializedData" ) ); addMember( new DWord( "AddressOfEntryPoint" ) ); addMember( new DWord( "BaseOfCode" ) ); - addMember( new DWord( "BaseOfData" ) ); - addMember( new DWord( "ImageBase" ) ); + if (format == ExeFormat.X86) { + addMember( new DWord( "BaseOfData" ) ); + addMember( new DWord( "ImageBase" ) ); + } + else { + addMember(new LongLong("ImageBase")); + } addMember( new DWord( "SectionAlignment" ) ); addMember( new DWord( "FileAlignment" ) ); addMember( new Word( "MajorOperatingSystemVersion" ) ); @@ -48,10 +53,18 @@ public class ImageOptionalHeader extends Bin.Structure { addMember( new DWord( "CheckSum" ) ); addMember( new Word( "Subsystem" ) ); addMember( new Word( "DllCharacteristics" ) ); - addMember( new DWord( "SizeOfStackReserve" ) ); - addMember( new DWord( "SizeOfStackCommit" ) ); - addMember( new DWord( "SizeOfHeapReserve" ) ); - addMember( new DWord( "SizeOfHeapCommit" ) ); + if (format == ExeFormat.X86) { + addMember( new DWord( "SizeOfStackReserve" ) ); + addMember( new DWord( "SizeOfStackCommit" ) ); + addMember( new DWord( "SizeOfHeapReserve" ) ); + addMember( new DWord( "SizeOfHeapCommit" ) ); + } + else { + addMember( new LongLong( "SizeOfStackReserve" ) ); + addMember( new LongLong( "SizeOfStackCommit" ) ); + addMember( new LongLong( "SizeOfHeapReserve" ) ); + addMember( new LongLong( "SizeOfHeapCommit" ) ); + } addMember( new DWord( "LoaderFlags" ) ); DWord numberOfRvaAndSizes = (DWord)addMember( new DWord( "NumberOfRvaAndSizes") ); ArrayOfBins imageDataDirectories = new ArrayOfBins("ImageDataDirectories", ImageDataDirectory.class, numberOfRvaAndSizes); diff --git a/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java b/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java index 6a5217c52899..8895c4e43f45 100644 --- a/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java +++ b/tools/launcher-generator/src/com/pme/exe/PeHeaderReader.java @@ -17,30 +17,30 @@ package com.pme.exe; -import java.io.IOException; -import java.io.DataInput; - /** * Date: Mar 31, 2006 * Time: 5:00:49 PM */ public class PeHeaderReader extends Bin.Structure{ - private Bin.Value myStartOffset; + private final ImageFileHeader myImageFileHeader; - public PeHeaderReader( Bin.Value startOffset ){ + public PeHeaderReader(Bin.Value startOffset, ExeFormat exeFormat) { super( "PE Header" ); - myStartOffset = startOffset; - addOffsetHolder( myStartOffset ); + addOffsetHolder(startOffset); addMember( new DWord( "Signature" ) ); - ImageFileHeader imageFileHeader = new ImageFileHeader(); - addMember( imageFileHeader ); - addMember( new ImageOptionalHeader() ); - Bin.Value numberOfSections = imageFileHeader.getValueMember( "NumberOfSections" ); + myImageFileHeader = new ImageFileHeader(); + addMember(myImageFileHeader); + if (exeFormat == ExeFormat.UNKNOWN) { + return; + } + addMember(new ImageOptionalHeader(exeFormat)); + Bin.Value numberOfSections = myImageFileHeader.getValueMember("NumberOfSections"); ArrayOfBins imageSectionHeaders = new ArrayOfBins( "ImageSectionHeaders", ImageSectionHeader.class, numberOfSections ); imageSectionHeaders.setCountHolder( numberOfSections ); addMember( imageSectionHeaders ); } - public void read(DataInput stream) throws IOException { - super.read( stream ); + + public ImageFileHeader getImageFileHeader() { + return myImageFileHeader; } } diff --git a/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java b/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java index b4f5d7600dd7..f822736e1213 100644 --- a/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java +++ b/tools/launcher-generator/src/com/pme/launcher/LauncherGenerator.java @@ -19,6 +19,7 @@ package com.pme.launcher; import com.google.common.io.Files; import com.google.common.io.InputSupplier; +import com.pme.exe.ExeFormat; import com.pme.exe.ExeReader; import com.pme.exe.SectionReader; import com.pme.exe.res.DirectoryEntry; @@ -50,8 +51,11 @@ public class LauncherGenerator { } public void load() throws IOException { - myReader = new ExeReader(myTemplate.getName()); RandomAccessFile stream = new RandomAccessFile(myTemplate, "r"); + ExeReader formatReader = new ExeReader(myTemplate.getName(), ExeFormat.UNKNOWN); + formatReader.read(stream); + stream.seek(0L); + myReader = new ExeReader(myTemplate.getName(), formatReader.getExeFormat()); myReader.read(stream); stream.close(); SectionReader sectionReader = myReader.getSectionReader(".rsrc"); diff --git a/tools/launcher-generator/src/com/pme/util/BitsUtil.java b/tools/launcher-generator/src/com/pme/util/BitsUtil.java index 1303b3e65b24..a934e9fd7178 100644 --- a/tools/launcher-generator/src/com/pme/util/BitsUtil.java +++ b/tools/launcher-generator/src/com/pme/util/BitsUtil.java @@ -28,12 +28,20 @@ public class BitsUtil { public static int revertBytesOfShort( short shortValue ){ return ((shortValue << 8) & 0xff00) + ((shortValue >> 8) & 0xff); } + public static long revertBytesOfInt( int intValue ){ long result = (intValue & 0x000000ff); result <<= 24; result += ((intValue & 0x0000ff00) << 8) + ((intValue & 0x00ff0000) >> 8) + ((intValue >> 24) & 0xff); return result; } + + public static long revertBytesOfLong(long longValue) { + long ms = revertBytesOfInt((int) (longValue >> 32)); + long ls = revertBytesOfInt((int) longValue); + return ms | ls << 32; + } + public static int unsignedByte( byte byteValue ){ int result = byteValue; return (result & 0xff);