x64 exe support

This commit is contained in:
Dmitry Jemerov
2013-03-27 21:18:31 +01:00
parent ba69f2361b
commit 883ac8c873
9 changed files with 125 additions and 32 deletions
@@ -68,7 +68,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>C:\Java\jdk1.6.0_37\include;C:\Java\jdk1.6.0_37\include\win32;$(IncludePath)</IncludePath>
<IncludePath>C:\Java\jdk1.6.0_43\include;C:\Java\jdk1.6.0_43\include\win32;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -76,7 +76,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>C:\Java\jdk1.6.0_37\include;C:\Java\jdk1.6.0_37\include\win32;$(IncludePath)</IncludePath>
<IncludePath>C:\Java\jdk1.6.0_43\include;C:\Java\jdk1.6.0_43\include\win32;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -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;
@@ -0,0 +1,8 @@
package com.pme.exe;
/**
* @author yole
*/
public enum ExeFormat {
UNKNOWN, X86, X64
}
@@ -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);
}
}
@@ -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() {
@@ -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<ImageDataDirectory> imageDataDirectories = new ArrayOfBins<ImageDataDirectory>("ImageDataDirectories", ImageDataDirectory.class, numberOfRvaAndSizes);
@@ -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;
}
}
@@ -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");
@@ -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);