From 5f1db41a0c1f676e16b933335b65cd34651dbd18 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Wed, 6 Nov 2002 01:05:54 +0000 Subject: [PATCH] New implementation of a COFF/EXE/PE parser --- .../org/eclipse/cdt/utils/coff/Coff.java | 529 ++++++++++++++++++ .../utils/org/eclipse/cdt/utils/coff/Exe.java | 159 ++++++ .../utils/org/eclipse/cdt/utils/coff/PE.java | 407 ++++++++++++++ .../eclipse/cdt/utils/coff/PEConstants.java | 115 ++++ .../cdt/utils/coff/ReadMemoryAccess.java | 289 ++++++++++ 5 files changed, 1499 insertions(+) create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff.java create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Exe.java create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEConstants.java create mode 100644 core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/ReadMemoryAccess.java diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff.java new file mode 100644 index 00000000000..2a8567e6821 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff.java @@ -0,0 +1,529 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ +package org.eclipse.cdt.utils.coff; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class Coff { + + public static final String NL = System.getProperty("line.separator", "\n"); + FileHeader filehdr; + OptionalHeader opthdr; + RandomAccessFile rfile; + long startingOffset; + byte[] string_table; + SectionHeader[] scnhdrs; + Symbol[] symbols; + + public static class FileHeader { + public final static int FILHSZ = 20; + + public final static int F_RELFLG = 0x0001; // relocation info stripped from file + public final static int F_EXEC = 0x0002; // file is executable + // (no unresolved external references) + public final static int F_LNNO = 0x0004; // line numbers stripped from file + public final static int F_LSYMS = 0x0008; // local symbols stripped from file + public final static int F_AR16WR = 0x0080; // file is 16-bit little-endian + public final static int F_AR32WR = 0x0100; // file is 32-bit little-endian + public final static int F_AR32W = 0x0200; // file is 32-bit big-endian + public final static int F_DYNLOAD = 0x1000;// rs/6000 aix: dynamically + // loadable w/imports & exports + public final static int F_SHROBJ = 0x2000; // rs/6000 aix: file is a shared object + public final static int F_DLL = 0x2000; // PE format DLL. + + public int f_magic; /* 00-01 2 bytes: magic number */ + public int f_nscns; /* 02-03 2 bytes: number of sections: 2 bytes */ + public int f_timdat; /* 04-07 4 bytes: time & date stamp */ + public int f_symptr; /* 08-11 4 bytes: file pointer to symtab */ + public int f_nsyms; /* 12-15 4 bytes: number of symtab entries */ + public int f_opthdr; /* 16-17 2 bytes: sizeof(optional hdr) */ + public int f_flags; /* 18-19 2 bytes: flags */ + + public FileHeader (RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public FileHeader (RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[FILHSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + f_magic = memory.getUnsignedShort(); + f_nscns = memory.getUnsignedShort(); + f_timdat = memory.getInt(); + f_symptr = memory.getInt(); + f_nsyms = memory.getInt(); + f_opthdr = memory.getUnsignedShort(); + f_flags = memory.getUnsignedShort(); + } + + public boolean isStrip() { + return (f_flags & F_RELFLG) == F_RELFLG; + } + + public boolean isExec() { + return (f_flags & F_EXEC) == F_EXEC; + } + + public boolean isDebug() { + return !((f_flags & F_LNNO) == F_LNNO); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("FILE HEADER VALUES").append(NL); + + buffer.append("f_magic = ").append(f_magic).append(NL); + buffer.append("f_nscns = ").append(f_nscns).append(NL); + + buffer.append("f_timdat = "); + buffer.append(DateFormat.getDateInstance().format(new Date(f_timdat))); + buffer.append(NL); + + buffer.append("f_symptr = ").append(f_symptr).append(NL); + buffer.append("f_nsyms = ").append(f_nsyms).append(NL); + buffer.append("f_opthdr = ").append(f_opthdr).append(NL); + buffer.append("f_flags = ").append(f_flags).append(NL); + return buffer.toString(); + } + } + + public static class OptionalHeader { + public final static int AOUTHDRSZ = 28; + + public short magic; /* 2 bytes: type of file */ + public short vstamp; /* 2 bytes: version stamp */ + public int tsize; /* 4 bytes: text size in bytes, padded to FW bdry*/ + public int dsize; /* 4 bytes: initialized data " " */ + public int bsize; /* 4 bytes: uninitialized data " " */ + public int entry; /* 4 bytes: entry pt. */ + public int text_start; /* 4 bytes: base of text used for this file */ + public int data_start; /* 4 bytes: base of data used for this file */ + + public OptionalHeader(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer() + FileHeader.FILHSZ); + } + + public OptionalHeader(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[AOUTHDRSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + magic = memory.getShort(); + vstamp = memory.getShort(); + tsize = memory.getInt(); + dsize = memory.getInt(); + bsize = memory.getInt(); + entry = memory.getInt(); + text_start = memory.getInt(); + data_start = memory.getInt(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("OPTIONAL HEADER VALUES").append(NL); + buffer.append("magic = ").append(magic).append(NL); + buffer.append("vstamp = ").append(vstamp).append(NL); + buffer.append("tsize = ").append(tsize).append(NL); + buffer.append("dsize = ").append(dsize).append(NL); + buffer.append("bsize = ").append(bsize).append(NL); + buffer.append("entry = ").append(entry).append(NL); + buffer.append("text_start = ").append(text_start).append(NL); + buffer.append("data_start = ").append(data_start).append(NL); + return buffer.toString(); + } + } + + public static class SectionHeader { + + public final static int SCNHSZ = 40; + + /* names of "special" sections */ + public final static String _TEXT = ".text"; + public final static String _DATA = ".data"; + public final static String _BSS = ".bss"; + public final static String _COMMENT = ".comment"; + public final static String _LIB = ".lib"; + + /* s_flags "type". */ + public final static int STYP_REG = 0x0000; /* "regular": allocated, relocated, + loaded */ + public final static int STYP_DSECT = 0x0001; /* "dummy": relocated only */ + public final static int STYP_NOLOAD = 0x0002; /* "noload": allocated, relocated, + not loaded */ + public final static int STYP_GROUP = 0x0004; /* "grouped": formed of input + sections */ + public final static int STYP_PAD = 0x0008; /* "padding": not allocated, not + relocated, loaded */ + public final static int STYP_COPY = 0x0010; /* "copy": for decision function + used by field update; + not allocated, not relocated, + loaded; reloc & lineno entries + processed normally */ + public final static int STYP_TEXT = 0x0020; /* section contains text only. */ + public final static int S_SHRSEG = 0x0020; /* In 3b Update files (output of + ogen), sections which appear in + SHARED segments of the Pfile + will have the S_SHRSEG flag set + by ogen, to inform dufr that + updating 1 copy of the proc. will + update all process invocations. */ + public final static int STYP_DATA = 0x0040; /* section contains data only */ + public final static int STYP_BSS = 0x0080; /* section contains bss only */ + public final static int S_NEWFCN = 0x0100; /* In a minimal file or an update + file, a new function (as + compared with a replaced + function) */ + public final static int STYP_INFO = 0x0200; /* comment: not allocated not + relocated, not loaded */ + public final static int STYP_OVER = 0x0400; /* overlay: relocated not allocated + or loaded */ + public final static int STYP_LIB = 0x0800; /* for .lib: same as INFO */ + public final static int STYP_MERGE = 0x2000; /* merge section -- combines with + text, data or bss sections only */ + public final static int STYP_REVERSE_PAD = 0x4000; /* section will be padded + with no-op instructions + wherever padding is necessary + and there is a word of + contiguous bytes beginning on a + word boundary. */ + + public final static int STYP_LIT = 0x8020; /* Literal data (like STYP_TEXT) */ + + + public byte[] s_name= new byte[8]; // 8 bytes: section name + public int s_paddr; // 4 bytes: physical address, aliased s_nlib + public int s_vaddr; // 4 bytes: virtual address + public int s_size; // 4 bytes: section size + public int s_scnptr; // 4 bytes: file ptr to raw data for section + public int s_relptr; // 4 bytes: file ptr to relocation + public int s_lnnoptr; // 4 bytes: file ptr to line numbers + public int s_nreloc; // 2 bytes: number of relocation entries + public int s_nlnno; // 2 bytes: number of line number entries + public int s_flags; // 4 bytes: flags + + RandomAccessFile sfile; + + public SectionHeader(RandomAccessFile file, long offset) throws IOException { + sfile = file; + file.seek(offset); + byte[] hdr = new byte[SCNHSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + memory.getBytes(s_name); + s_paddr = memory.getInt(); + s_vaddr = memory.getInt(); + s_size = memory.getInt(); + s_scnptr = memory.getInt(); + s_relptr = memory.getInt(); + s_lnnoptr = memory.getInt(); + s_nreloc = memory.getUnsignedShort(); + s_nlnno = memory.getUnsignedShort(); + s_flags = memory.getInt(); + } + + public byte[] getRawData() throws IOException { + byte[] data = new byte[s_size]; + sfile.seek(s_scnptr); + sfile.readFully(data); + return data; + } + + public Reloc[] getRelocs() throws IOException { + Reloc[] relocs = new Reloc[s_nreloc]; + sfile.seek(s_relptr); + for (int i = 0; i < s_nreloc; i++) { + relocs[i] = new Reloc(sfile); + } + return relocs; + } + + public Lineno[] getLinenos() throws IOException { + Lineno[] lines = new Lineno[s_nlnno]; + sfile.seek(s_lnnoptr); + for (int i = 0; i < s_nlnno; i++) { + lines[i] = new Lineno(sfile); + } + return lines; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("SECTION HEADER VALUES").append(NL); + buffer.append(new String(s_name)).append(NL); + buffer.append("s_paddr = ").append(s_paddr).append(NL); + buffer.append("s_vaddr = ").append(s_vaddr).append(NL); + buffer.append("s_size = ").append(s_size).append(NL); + buffer.append("s_scnptr = ").append(s_scnptr).append(NL); + buffer.append("s_relptr = ").append(s_relptr).append(NL); + buffer.append("s_lnnoptr = ").append(s_lnnoptr).append(NL); + buffer.append("s_nreloc = ").append(s_nreloc).append(NL); + buffer.append("s_nlnno = ").append(s_nlnno).append(NL); + buffer.append("s_flags = ").append(s_flags).append(NL); +/* + try { + Reloc[] rcs = getRelocs(); + for (int i = 0; i < rcs.length; i++) { + buffer.append(rcs[i]); + } + } catch (IOException e) { + } + try { + Lineno[] nos = getLinenos(); + for (int i = 0; i < nos.length; i++) { + buffer.append(nos[i]); + } + } catch (IOException e) { + } +*/ + return buffer.toString(); + } + } + + public static class Reloc { + public static final int RELSZ = 16; + public int r_vaddr; /* 4 byte: Pointer to an area in raw data that represents a + referenced address. */ + public int r_symndx; /* 4 byte: Index into symbol table. */ + public int r_type; /* 2 byte(unsigned short): Type of address reference. */ + + public Reloc(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public Reloc(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] bytes = new byte[RELSZ]; + file.readFully(bytes); + ReadMemoryAccess memory = new ReadMemoryAccess(bytes, true); + r_vaddr = memory.getInt(); + r_symndx = memory.getInt(); + r_type = memory.getUnsignedShort(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("RELOC VALUES").append(NL); + buffer.append("r_vaddr = ").append(r_vaddr); + buffer.append(" r_symndx = ").append(r_symndx).append(NL); + return buffer.toString(); + } + } + + public static class Lineno { + public final static int LINESZ = 6; + public int l_addr; /* long. Index into symbol table if l_linn0 == 0. + Break-pointable address if l_lnno > 0. */ + public int l_lnno; /* unsigned short. Line number */ + + public Lineno(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public Lineno(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] bytes = new byte[LINESZ]; + file.readFully(bytes); + ReadMemoryAccess memory = new ReadMemoryAccess(bytes, true); + l_addr = memory.getInt(); + l_lnno = memory.getUnsignedShort(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + if (l_lnno == 0) { + buffer.append("Function address = ").append(l_addr).append(NL); + } else { + buffer.append("line# ").append(l_lnno); + buffer.append(" at address = ").append(l_addr).append(NL); + } + return buffer.toString(); + } + } + + public static class Symbol { + public final static int SYMSZ = 18; + public final static int SYMNMLEN = 8; + public byte[] _n_name = new byte[SYMNMLEN]; /* Symbol name, or pointer into + string table if symbol name + is greater than SYMNMLEN. */ + public int n_value; /* long. Symbol;s value: dependent on section number, + storage class and type. */ + public short n_scnum; /* short, Section number. */ + public int n_type; /* Unsigned short. Symbolic type. */ + public byte n_sclass; /* char, Storage class. */ + public byte n_numaux; /* char. Nuymber of auxiliary enties. */ + + public Symbol(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public Symbol(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] bytes = new byte[SYMSZ]; + file.readFully(bytes); + ReadMemoryAccess memory = new ReadMemoryAccess(bytes, true); + memory.getBytes(_n_name); + n_value = memory.getInt(); + n_scnum = memory.getShort(); + n_type = memory.getUnsignedShort(); + n_sclass = memory.getByte(); + n_numaux = memory.getByte(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("SYMBOL VALUES"); + return buffer.toString(); + } + } + + public FileHeader getFileHeader() throws IOException { + return filehdr; + } + + public OptionalHeader getOptionalHeader() throws IOException { + return opthdr; + } + + public SectionHeader[] getSectionHeaders() throws IOException { + if (scnhdrs == null) { + scnhdrs = new SectionHeader[getFileHeader().f_nscns]; + long sec = getFileHeader().FILHSZ + getFileHeader().f_opthdr; + for (int i = 0; i < scnhdrs.length; i++, sec += SectionHeader.SCNHSZ) { + scnhdrs[i] = new SectionHeader(rfile, sec); + } + } + return scnhdrs; + } + + public Symbol[] getSymbols() throws IOException { + if (symbols == null) { + long offset = getFileHeader().f_symptr; + rfile.seek(offset); + symbols = new Symbol[getFileHeader().f_nsyms]; + for (int i = 0; i < symbols.length; i++) { + symbols[i] = new Symbol(rfile); + } + } + return symbols; + } + + public byte[] getStringTable() throws IOException { + if (string_table == null) { + long symbolsize = Symbol.SYMSZ * getFileHeader().f_nsyms; + long offset = getFileHeader().f_symptr + symbolsize; + rfile.seek(offset); + byte[] bytes = new byte[4]; + rfile.readFully(bytes); + int str_len = ReadMemoryAccess.getIntLE(bytes); + if (str_len > 4) { + str_len -= 4; + string_table = new byte[str_len]; + rfile.seek(offset + 4); + rfile.readFully(string_table); + } else { + string_table = new byte[0]; + } + } + return string_table; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + try { + FileHeader header = null; + header = getFileHeader(); + if (header != null) { + buffer.append(header); + } + } catch (IOException e) { + e.printStackTrace(); + } + try { + OptionalHeader opt = null; + opt = getOptionalHeader(); + if (opt != null) { + buffer.append(opt); + } + } catch (IOException e) { + e.printStackTrace(); + } + try { + SectionHeader[] sections = getSectionHeaders(); + for (int i = 0; i < sections.length; i++) { + buffer.append(sections[i]); + } + } catch (IOException e) { + } + + try { + Symbol[] table = getSymbols(); + for (int i = 0; i < table.length; i++) { + buffer.append(table[i]); + } + } catch (IOException e) { + } + + try { + String[] strings = getStringTable(getStringTable()); + for (int i = 0; i < strings.length; i++) { + buffer.append(strings[i]); + } + } catch (IOException e) { + e.printStackTrace(); + } + return buffer.toString(); + } + + public static String[] getStringTable(byte[] bytes) { + List aList = new ArrayList(); + int offset = 0; + for (int i = 0; i < bytes.length; i++) { + if (bytes[i] == '\0') { + aList.add(new String(bytes, offset, (i + 1) - offset)); + offset = i; + } + } + return (String[])aList.toArray(new String[0]); + } + + public Coff(String filename) throws IOException { + this(new RandomAccessFile(filename, "r"), 0); + } + + public Coff(RandomAccessFile file, long offset) throws IOException { + commonSetup(file, offset); + } + + void commonSetup(RandomAccessFile file, long offset) throws IOException { + startingOffset = offset; + rfile = file; + try { + filehdr = new FileHeader(rfile, offset); + if (filehdr.f_opthdr > 0) { + opthdr = new OptionalHeader(rfile, startingOffset + 20); + } + } finally { + if (filehdr == null) { + rfile.close(); + } + } + } + + public static void main(String[] args) { + try { + Coff coff = new Coff(args[0]); + System.out.println(coff); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Exe.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Exe.java new file mode 100644 index 00000000000..b7942a77866 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Exe.java @@ -0,0 +1,159 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ +package org.eclipse.cdt.utils.coff; + +import java.io.IOException; +import java.io.RandomAccessFile; + +public class Exe { + + public static final String NL = System.getProperty("line.separator", "\n"); + protected RandomAccessFile rfile; + ExeHeader ehdr; + + static public class ExeHeader { + + public final static int EXEHDRSZ = 28; + public byte[] e_signature = new byte[2]; // 00-01 "MZ" - Link file .EXE signature + public short e_lastsize; // 02-03 Length of EXE file modulo 512 + public short e_nblocks; // 04-05 Number of 512 pages (including the last page) + public short e_nreloc; // 06-07 Number of relocation entries + public short e_hdrsize; // 08-09 Size of header in 16 byte paragraphs, + // occupied by "EXE" header and relo table. + + public short e_minalloc; // 0A-0B Minimum paragraphs of memory allocated + public short e_maxalloc; // 0C-0D Maximum number of paragraphs allocated + // in addition to the code size + public short e_ss; // 0E-0F Initial SS relative to start of executable + public short e_sp; // 10-11 Initial SP + public short e_checksum; // 12-13 Checksum (or 0) of executable + public short e_ip; // 14-15 CS:IP relative to start of executable + public short e_cs; // 16-17 CS:IP relative to start of executable + public short e_relocoffs; // 18-19 Offset of relocation table; + // 40h for new-(NE,LE,LX,W3,PE etc.) executable + public short e_noverlay; // 1A-1B Overlay number (0h = main program) + + protected ExeHeader(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + protected ExeHeader(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[EXEHDRSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + memory.getBytes(e_signature); + if (e_signature[0] != 'M' || e_signature[1] != 'Z') { + throw new IOException("Not DOS EXE format"); + } + e_lastsize = memory.getShort(); + e_nblocks = memory.getShort(); + e_nreloc = memory.getShort(); + e_hdrsize = memory.getShort(); + e_minalloc = memory.getShort(); + e_maxalloc = memory.getShort(); + e_ss = memory.getShort(); + e_sp = memory.getShort(); + e_checksum = memory.getShort(); + e_ip = memory.getShort(); + e_cs = memory.getShort(); + e_relocoffs = memory.getShort(); + e_noverlay = memory.getShort(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + + buffer.append("EXE HEADER VALUES").append(NL); + buffer.append("signature "); + buffer.append((char)e_signature[0] + " " + (char)e_signature[1]); + buffer.append(NL); + + buffer.append("lastsize: 0x"); + buffer.append(Long.toHexString(new Short(e_lastsize).longValue())); + buffer.append(NL); + + buffer.append("nblocks: 0x"); + buffer.append(Long.toHexString(new Short(e_nblocks).longValue())); + buffer.append(NL); + + buffer.append("nreloc: 0x"); + buffer.append(Long.toHexString(new Short(e_nreloc).longValue())); + buffer.append(NL); + + buffer.append("hdrsize: 0x"); + buffer.append(Long.toHexString(new Short(e_hdrsize).longValue())); + buffer.append(NL); + + buffer.append("minalloc: 0x"); + buffer.append(Long.toHexString(new Short(e_minalloc).longValue())); + buffer.append(NL); + + buffer.append("maxalloc: 0x"); + buffer.append(Long.toHexString(new Short(e_maxalloc).longValue())); + buffer.append(NL); + buffer.append("ss: 0x"); + buffer.append(Long.toHexString(new Short(e_ss).longValue())); + buffer.append(NL); + + buffer.append("sp: 0x"); + buffer.append(Long.toHexString(new Short(e_sp).longValue())); + buffer.append(NL); + + buffer.append("checksum: 0x"); + buffer.append(Long.toHexString(new Short(e_checksum).longValue())); + buffer.append(NL); + + buffer.append("ip: 0x"); + buffer.append(Long.toHexString(new Short(e_ip).longValue())); + buffer.append(NL); + + buffer.append("cs: 0x"); + buffer.append(Long.toHexString(new Short(e_cs).longValue())); + buffer.append(NL); + + buffer.append("relocoffs: 0x"); + buffer.append(Long.toHexString(new Short(e_relocoffs).longValue())); + buffer.append(NL); + + buffer.append("overlay: 0x"); + buffer.append(Long.toHexString(new Short(e_noverlay).longValue())); + buffer.append(NL); + return buffer.toString(); + } + } + + public ExeHeader getExeHeader() throws IOException { + return ehdr; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(rfile).append(NL); + buffer.append(ehdr); + return buffer.toString(); + } + + public Exe(String file) throws IOException { + rfile = new RandomAccessFile(file, "r"); + try { + ehdr = new ExeHeader(rfile); + } finally { + if (ehdr == null) { + rfile.close(); + } + } + } + + public static void main(String[] args) { + try { + Exe exe = new Exe(args[0]); + System.out.println(exe); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java new file mode 100644 index 00000000000..d9ff06d35d9 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java @@ -0,0 +1,407 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +package org.eclipse.cdt.utils.coff; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import org.eclipse.cdt.utils.coff.Coff.FileHeader; +import org.eclipse.cdt.utils.coff.Coff.OptionalHeader; +import org.eclipse.cdt.utils.coff.Coff.SectionHeader; +import org.eclipse.cdt.utils.coff.Coff.Symbol; +import org.eclipse.cdt.utils.coff.Exe.ExeHeader; + +/** + * The PE file header consists of an MS-DOS stub, the PE signalture, the COFF file Header + * and an Optional Header. + *
+ *  +-------------------+
+ *  | DOS-stub          |
+ *  +-------------------+
+ *  | file-header       |
+ *  +-------------------+
+ *  | optional header   |
+ *  |- - - - - - - - - -|
+ *  |                   |
+ *  | data directories  |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section headers   |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section 1         |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section 2         |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | ...               |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section n         |
+ *  |                   |
+ *  +-------------------+
+ * 
+ */ +public class PE { + + public static final String NL = System.getProperty("line.separator", "\n"); + RandomAccessFile rfile; + ExeHeader exeHeader; + DOSHeader dosHeader; + FileHeader fileHeader; + OptionalHeader optionalHeader; + NTOptionalHeader ntHeader; + ImageDataDirectory[] dataDirectories; + SectionHeader[] scnhdrs; + Symbol[] symbolTable; + byte[] stringTable; + + /** + */ + public static class DOSHeader { + final static int DOSHDRSZ = 100; + byte[] e_res = new byte[8]; /* Reserved words, all 0x0. */ + byte[] e_oemid = new byte[2]; /* OEM identifier (for e_oeminfo), 0x0. */ + byte[] e_oeminfo = new byte[2]; /* OEM information; e_oemid specific, 0x0. */ + byte[] e_res2 = new byte[20]; /* Reserved words, all 0x0. */ + int e_lfanew; /* 4 byte File address of new exe header, offset 60(0x3c), 0x80. */ + byte[] dos_message = new byte[64]; /* Other stuff, always follow DOS header. */ + + public DOSHeader(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public DOSHeader(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[DOSHDRSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + memory.getBytes(e_res); + memory.getBytes(e_oemid); + memory.getBytes(e_oeminfo); + memory.getBytes(e_res2); + e_lfanew = memory.getInt(); + memory.getBytes(dos_message); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("DOS STUB VALUES").append(NL); + buffer.append("e_lfanew = ").append(e_lfanew).append(NL); + buffer.append(new String(dos_message)).append(NL); + return buffer.toString(); + } + } + + public static class NTOptionalHeader { + + public final static int NTHDRSZ = 68; + public int ImageBase; // 4 bytes. + public int SectionAlignment; // 4 bytes. + public int FileAlignment; // 4 bytes. + public short MajorOperatingSystemVersion; // 2 bytes. + public short MinorOperatingSystemVersion; // 2 bytes. + public short MajorImageVersion; // 2 bytes. + public short MinorImageVersion; // 2 bytes. + public short MajorSubsystemVersion; // 2 bytes. + public short MinorSubsystemVersion; // 2 bytes. + public byte[] Reserved = new byte[4]; // 4 bytes. + public int SizeOfImage; // 4 bytes. + public int SizeOfHeaders; // 4 bytes. + public int CheckSum; // 4 bytes. + public short Subsystem; // 2 bytes. + public short DLLCharacteristics; // 2 bytes. + public int SizeOfStackReserve; // 4 bytes. + public int SizeOfStackCommit; // 4 bytes. + public int SizeOfHeapReserve; // 4 bytes. + public int SizeOfHeapCommit; // 4 bytes. + public int LoaderFlags; // 4 bytes. + public int NumberOfRvaAndSizes; // 4 bytes. + + public NTOptionalHeader(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public NTOptionalHeader(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[NTHDRSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + ImageBase = memory.getInt(); + SectionAlignment = memory.getInt(); + FileAlignment = memory.getInt(); + MajorOperatingSystemVersion = memory.getShort(); + MinorOperatingSystemVersion = memory.getShort(); + MajorImageVersion = memory.getShort(); + MinorImageVersion = memory.getShort(); + MajorSubsystemVersion = memory.getShort(); + MinorSubsystemVersion = memory.getShort(); + memory.getBytes(Reserved); + SizeOfImage = memory.getInt(); + SizeOfHeaders = memory.getInt(); + CheckSum = memory.getInt(); + Subsystem = memory.getShort(); + DLLCharacteristics = memory.getShort(); + SizeOfStackReserve = memory.getInt(); + SizeOfStackCommit = memory.getInt(); + SizeOfHeapReserve = memory.getInt(); + SizeOfHeapCommit = memory.getInt(); + LoaderFlags = memory.getInt(); + NumberOfRvaAndSizes = memory.getInt(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("NT OPTIONAL HEADER VALUES").append(NL); + buffer.append("ImageBase = ").append(ImageBase).append(NL); + buffer.append("SexctionAlignement = ").append(SectionAlignment).append(NL); + buffer.append("FileAlignment = ").append(FileAlignment).append(NL); + buffer.append("MajorOSVersion = ").append(MajorOperatingSystemVersion).append(NL); + buffer.append("MinorOSVersion = ").append(MinorOperatingSystemVersion).append(NL); + buffer.append("MajorImageVersion = ").append(MajorImageVersion).append(NL); + buffer.append("MinorImageVersion = ").append(MinorImageVersion).append(NL); + buffer.append("MajorSubVersion = ").append(MajorSubsystemVersion).append(NL); + buffer.append("MinorSubVersion = ").append(MinorSubsystemVersion).append(NL); + buffer.append("Reserved = ").append(Reserved).append(NL); + buffer.append("SizeOfImage = ").append(SizeOfImage).append(NL); + buffer.append("SizeOfHeaders = ").append(SizeOfHeaders).append(NL); + buffer.append("CheckSum = ").append(CheckSum).append(NL); + buffer.append("Subsystem = ").append(Subsystem).append(NL); + buffer.append("DLL = ").append(DLLCharacteristics).append(NL); + buffer.append("StackReserve = ").append(SizeOfStackReserve).append(NL); + buffer.append("StackCommit = ").append(SizeOfStackCommit).append(NL); + buffer.append("HeapReserve = ").append(SizeOfHeapReserve).append(NL); + buffer.append("HeapCommit = ").append(SizeOfHeapCommit).append(NL); + buffer.append("LoaderFlags = ").append(LoaderFlags).append(NL);; + buffer.append("#Rva size = ").append(NumberOfRvaAndSizes).append(NL); + return buffer.toString(); + } + } + + public class ImageDataDirectory { + public int rva; + public int size; + + public ImageDataDirectory(int r, int s) { + rva = r; + size = s; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("rva = ").append(rva).append(" "); + buffer.append("size = ").append(size).append(NL); + return buffer.toString(); + } + } + + public class ImportDirectoryEntry { + public final static int ENTRYSZ = 20; + public int rva; + public int timestamp; + public int forwarder; + public int name; + public int thunk; + + public ImportDirectoryEntry(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public ImportDirectoryEntry(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] bytes = new byte[ENTRYSZ]; + file.readFully(bytes); + ReadMemoryAccess memory = new ReadMemoryAccess(bytes, true); + rva = memory.getInt(); + timestamp = memory.getInt(); + forwarder = memory.getInt(); + name = memory.getInt(); + thunk = memory.getInt(); + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append("rva = ").append(rva); + buffer.append(" timestamp = ").append(timestamp); + buffer.append(" forwarder = ").append(forwarder); + buffer.append(" name = ").append(name); + buffer.append(" thunk = ").append(thunk).append(NL); + return buffer.toString(); + } + } + + + public PE (String filename) throws IOException { + + rfile = new RandomAccessFile(filename, "r"); + + exeHeader = new ExeHeader(rfile); + + dosHeader = new DOSHeader(rfile); + + // Jump the Coff header, and Check the sig. + rfile.seek(dosHeader.e_lfanew); + byte[] sig = new byte[4]; + rfile.readFully(sig); + if (!((sig[0] == 'P') && (sig[1] == 'E') + && (sig[2] == '\0') && (sig[3] == '\0'))) { + throw new IOException("Not a PE format"); + } + + fileHeader = new Coff.FileHeader(rfile, rfile.getFilePointer()); + + optionalHeader = new Coff.OptionalHeader(rfile, rfile.getFilePointer()); + + ntHeader = new NTOptionalHeader(rfile, rfile.getFilePointer()); + + } + + public ExeHeader getExeHeader() { + return exeHeader; + } + + public DOSHeader getDOSHeader() { + return dosHeader; + } + + public FileHeader getFileHeader() { + return fileHeader; + } + + public OptionalHeader getOptionalHeader() { + return optionalHeader; + } + + public NTOptionalHeader getNTOptionalHeader() { + return ntHeader; + } + + public ImageDataDirectory[] getImageDataDirectories() throws IOException { + if (dataDirectories == null) { + long offset = dosHeader.e_lfanew + FileHeader.FILHSZ + + OptionalHeader.AOUTHDRSZ + NTOptionalHeader.NTHDRSZ + 4/*NT SIG*/; + rfile.seek(offset); + dataDirectories = new ImageDataDirectory[PEConstants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; + byte[] data = new byte[dataDirectories.length * (4 + 4)]; + rfile.readFully(data); + ReadMemoryAccess memory = new ReadMemoryAccess(data, true); + for (int i = 0; i < dataDirectories.length; i++) { + int rva = memory.getInt(); + int size = memory.getInt(); + dataDirectories[i] = new ImageDataDirectory(rva, size); + } + } + return dataDirectories; + } + public SectionHeader[] getSectionHeaders() throws IOException { + if (scnhdrs == null) { + scnhdrs = new SectionHeader[fileHeader.f_nscns]; + long offset = dosHeader.e_lfanew + + FileHeader.FILHSZ + fileHeader.f_opthdr + 4 /* NT SIG */; + for (int i = 0; i < scnhdrs.length; i++, offset += SectionHeader.SCNHSZ) { + scnhdrs[i] = new SectionHeader(rfile, offset); + } + } + return scnhdrs; + } + + public Symbol[] getSymbols() throws IOException { + if (symbolTable == null) { + long offset = fileHeader.f_symptr; + symbolTable = new Symbol[fileHeader.f_nsyms]; + for (int i = 0; i < symbolTable.length; i++, offset += Symbol.SYMSZ) { + symbolTable[i] = new Symbol(rfile, offset); + } + } + return symbolTable; + } + + public byte[] getStringTable() throws IOException { + if (stringTable == null) { + if (fileHeader.f_nsyms > 0) { + long symbolsize = Symbol.SYMSZ * fileHeader.f_nsyms; + long offset = fileHeader.f_symptr + symbolsize; + rfile.seek(offset); + byte[] bytes = new byte[4]; + rfile.readFully(bytes); + int str_len = ReadMemoryAccess.getIntLE(bytes); + if (str_len > 4) { + str_len -= 4; + stringTable = new byte[str_len]; + rfile.seek(offset + 4); + rfile.readFully(stringTable); + } else { + stringTable = new byte[0]; + } + } else { + stringTable = new byte[0]; + } + } + return stringTable; + } + + public String toString() { + StringBuffer buffer = new StringBuffer(); + buffer.append(exeHeader); + buffer.append(dosHeader); + buffer.append(fileHeader); + buffer.append(optionalHeader); + buffer.append(ntHeader); + try { + ImageDataDirectory[] dirs = getImageDataDirectories(); + for (int i = 0; i < dirs.length; i++) { + buffer.append("Entry ").append(i); + buffer.append(" ").append(dirs[i]); + } + } catch (IOException e) { + e.printStackTrace(); + } + + try { + SectionHeader[] sections = getSectionHeaders(); + for (int i = 0; i < sections.length; i++) { + buffer.append(sections[i]); + } + } catch (IOException e) { + e.printStackTrace(); + } + + try { + Symbol[] symbols = getSymbols(); + for (int i = 0; i < symbols.length; i++) { + buffer.append(symbols[i]); + } + } catch (IOException e) { + e.printStackTrace(); + } + + try { + byte[] bytes = getStringTable(); + String[] strings = Coff.getStringTable(bytes); + for (int i = 0; i < strings.length; i++) { + buffer.append(strings[i]); + } + } catch (IOException e) { + e.printStackTrace(); + } + return buffer.toString(); + } + + public static void main(String[] args) { + try { + PE pe = new PE(args[0]); + System.out.println(pe); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEConstants.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEConstants.java new file mode 100644 index 00000000000..3f7796479f4 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PEConstants.java @@ -0,0 +1,115 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +package org.eclipse.cdt.utils.coff; + +public class PEConstants { + +/* PE characteristics, FileHeader.f_flags. */ +public final static int IMAGE_FILE_RELOCS_STRIPPED = 0x0001; +public final static int IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002; +public final static int IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004; +public final static int IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008; +public final static int IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010; +public final static int IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020; +public final static int IMAGE_FILE_16BIT_MACHINE = 0x0040; +public final static int IMAGE_FILE_BYTES_REVERSED_LO = 0x0080; +public final static int IMAGE_FILE_32BIT_MACHINE = 0x0100; +public final static int IMAGE_FILE_DEBUG_STRIPPED = 0x0200; +public final static int IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400; +public final static int IMAGE_FILE_SYSTEM = 0x1000; +public final static int IMAGE_FILE_DLL = 0x2000; +public final static int IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000; +public final static int IMAGE_FILE_BYTES_REVERSED_HI = 0x8000; + +/* FileHader.f_magic. Indicate the machine numbers. */ +public final static int IMAGE_FILE_MACHINE_UNKNOWN = 0x0; +public final static int IMAGE_FILE_MACHINE_ALPHA = 0x184; +public final static int IMAGE_FILE_MACHINE_ARM = 0x1c0; +public final static int IMAGE_FILE_MACHINE_ALPHA64 = 0x284; +public final static int IMAGE_FILE_MACHINE_I386 = 0x14c; +public final static int IMAGE_FILE_MACHINE_IA64 = 0x200; +public final static int IMAGE_FILE_MACHINE_M68K = 0x268; +public final static int IMAGE_FILE_MACHINE_MIPS16 = 0x266; +public final static int IMAGE_FILE_MACHINE_MIPSFPU = 0x366; +public final static int IMAGE_FILE_MACHINE_MIPSFPU16 = 0x466; +public final static int IMAGE_FILE_MACHINE_POWERPC = 0x1f0; +public final static int IMAGE_FILE_MACHINE_R3000 = 0x162; +public final static int IMAGE_FILE_MACHINE_R4000 = 0x166; +public final static int IMAGE_FILE_MACHINE_R10000 = 0x168; +public final static int IMAGE_FILE_MACHINE_SH3 = 0x1a2; +public final static int IMAGE_FILE_MACHINE_SH4 = 0x1a6; +public final static int IMAGE_FILE_MACHINE_THUMB = 0x1c2; + +/* OptionalHeader.magic */ +public final static int PE32 = 0x10b; +public final static int PE32PLUS = 0x20b; + +/* Windows NT Subsystem. NTOptionalHeader.Subsystem */ +public final static int IMAGE_SUBSYSTEM_UNKNOWN = 0; +public final static int IMAGE_SUBSYSTEM_NATIVE = 1; +public final static int IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; +public final static int IMAGE_SUBSYSTEM_WINDOWS_CUI = 3; +public final static int IMAGE_SUBSYSTEM_POSIX_CUI = 7; +public final static int IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9; +public final static int IMAGE_SUBSYSTEM_EFI_APPLICATION = 10; +public final static int IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11; +public final static int IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12; + +/* DLL CHarcteristics, NTOptionalHeader.DLLCharcteristics */ +public final static int IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800; // Do not bind image. +// Driver is a WDM Driver. +public final static int IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000; +// Image is Terminal Sever aware. +public final static int IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER = 0x2000; + +/* Array of Directories */ +public final static int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16; + +/* The directory of exported symbols; mostly used for DLLs. + Described below. */ +public final static int IMAGE_DIRECTORY_ENTRY_EXPORT = 0; + +/* The directory of imported symbols; see below. */ +public final static int IMAGE_DIRECTORY_ENTRY_IMPORT = 1; + +/* Directory of resources. Described below. */ +public final static int IMAGE_DIRECTORY_ENTRY_RESOURCE = 2; + +/* Exception directory - structure and purpose unknown. */ +public final static int IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3; + +/* Security directory - structure and purpose unknown. */ +public final static int IMAGE_DIRECTORY_ENTRY_SECURITY = 4; + +/* Base relocation table - see below. */ +public final static int IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; + +/* Debug directory - contents is compiler dependent. Moreover, many + compilers stuff the debug information into the code section and + don't create a separate section for it. */ +public final static int IMAGE_DIRECTORY_ENTRY_DEBUG = 6; + +/* Description string - some arbitrary copyright note or the like. */ +public final static int IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7; + +/* Machine Value (MIPS GP) - structure and purpose unknown. */ +public final static int IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8; + +/* Thread local storage directory - structure unknown; contains + variables that are declared "__declspec(thread)", i.e. + per-thread global variables. */ +public final static int IMAGE_DIRECTORY_ENTRY_TLS = 9; + +/* Load configuration directory - structure and purpose unknown. */ +public final static int IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10; + +/* Bound import directory - see description of import directory. */ +public final static int IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11; + +/* Import Address Table - see description of import directory. */ +public final static int IMAGE_DIRECTORY_ENTRY_IAT = 12; + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/ReadMemoryAccess.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/ReadMemoryAccess.java new file mode 100644 index 00000000000..75318e38a66 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/ReadMemoryAccess.java @@ -0,0 +1,289 @@ +/* + * (c) Copyright QNX Software Systems Ltd. 2002. + * All Rights Reserved. + */ + +package org.eclipse.cdt.utils.coff; + +public class ReadMemoryAccess { + + byte[] bytes; + int memOffset; + byte[] val = new byte[8]; + boolean isle; + + public ReadMemoryAccess(byte[] octets) { + this(octets, true); + } + + public ReadMemoryAccess(byte[] octets, boolean le) { + bytes = octets; + memOffset = 0; + isle = le; + } + + public void getBytes(byte[] octets) { + getBytes(octets, memOffset); + memOffset += octets.length; + } + + public void getBytes(byte[] octets, int offset) { + getBytes(octets, offset, octets.length); + } + + public void getBytes(byte[] octets, int offset, int length) { + System.arraycopy(bytes, offset, octets, 0, length); + } + + public byte getByte() { + return getByte(memOffset++); + } + + public short getUnsignedByte() { + return getUnsignedByte(memOffset++); + } + + public byte getByte(int offset) { + return bytes[offset]; + } + + public short getUnsignedByte(int offset) { + return (short)bytes[offset]; + } + + public short getShort() { + if (isle) { + return getShortLE(); + } + return getShortBE(); + } + + public int getUnsignedShort() { + if (isle) { + return getUnsignedShortLE(); + } + return getUnsignedShortBE(); + } + + public short getShortLE() { + short s = getShortLE(memOffset); + memOffset +=2; + return s; + } + + public int getUnsignedShortLE() { + int i = getUnsignedShortLE(memOffset); + memOffset +=2; + return i; + } + + public short getShortLE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + return getShortLE(val); + } + + public static short getShortLE(byte[] b) { + return (short)(((b[1]&0xff) << 8) | (b[0]&0xff)); + } + + public int getUnsignedShortLE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + return getUnsignedShortLE(val); + } + + public static int getUnsignedShortLE(byte[] b) { + return (((b[1] & 0xff) << 8) | (b[0] & 0xff)); + } + + public short getShortBE() { + short s = getShortBE(memOffset); + memOffset +=2; + return s; + } + + public int getUnsignedShortBE() { + int i = getUnsignedShortBE(memOffset); + memOffset +=2; + return i; + } + + public short getShortBE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + return getShortBE(val); + } + + public static short getShortBE(byte[] b) { + return (short)(((b[0] & 0xff) << 8) | (b[1] & 0xff)); + } + + public int getUnsignedShortBE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + return getUnsignedShortBE(val); + } + + public static int getUnsignedShortBE(byte[] b) { + return (((b[0] & 0xff) << 8) + (b[1] & 0xff)); + } + + public int getInt() { + if (isle) { + return getIntLE(); + } + return getIntBE(); + } + + public int getIntLE() { + int i = getIntLE(memOffset); + memOffset += 4; + return i; + } + + public long getUnsignedIntLE() { + long l = getUnsignedIntLE(memOffset); + memOffset += 4; + return l; + } + + public long getUnsignedIntLE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + val[2] = getByte(offset + 2); + val[3] = getByte(offset + 3); + return getUnsignedIntLE(val); + } + + public static long getUnsignedIntLE(byte[] b) { + return (long)(((b[3] & 0xff) << 24) | + ((b[2] & 0xff) << 16) | + ((b[1] & 0xff) << 8) | + (b[0] & 0xff)); + } + + public int getIntLE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + val[2] = getByte(offset + 2); + val[3] = getByte(offset + 3); + return getIntLE(val); + } + + public static int getIntLE(byte[] b) { + return (int)(((b[3] & 0xff) << 24) | + ((b[2] & 0xff) << 16) | + ((b[1] & 0xff) << 8) | + (b[0] & 0xff)); + } + + public int getIntBE() { + int i = getIntBE(memOffset); + memOffset += 4; + return i; + } + + public long getUnsignedIntBE() { + long l = getUnsignedIntBE(memOffset); + memOffset += 4; + return l; + } + + public int getIntBE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + val[2] = getByte(offset + 2); + val[3] = getByte(offset + 3); + return getIntBE(val); + } + + public static int getIntBE(byte[] b) { + return (int)(((b[0] & 0xff) << 24) | + ((b[1] & 0xff) << 16) | + ((b[2] & 0xff) << 8) | + (b[3] & 0xff)); + } + + public long getUnsignedIntBE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + val[2] = getByte(offset + 2); + val[3] = getByte(offset + 3); + return getUnsignedIntBE(val); + } + + public static long getUnsignedIntBE(byte[] b) { + return (long)(((b[0] & 0xff) << 24) | + ((b[1] & 0xff) << 16) | + ((b[2] & 0xff) << 8) | + (b[3] & 0xff)); + } + + public long getLong() { + if (isle) { + return getLongLE(); + } + return getLongBE(); + } + + public long getLongLE() { + long l = getLongLE(memOffset); + memOffset += 8; + return l; + } + + public long getLongLE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + val[2] = getByte(offset + 2); + val[3] = getByte(offset + 3); + val[4] = getByte(offset + 4); + val[5] = getByte(offset + 5); + val[6] = getByte(offset + 6); + val[7] = getByte(offset + 7); + return getLongLE(val); + } + + public long getLongLE(byte[] b) { + return ((long)(b[7] & 0xff) << 56) | + ((long)(b[6] & 0xff) << 48) | + ((long)(b[5] & 0xff) << 40) | + ((long)(b[4] & 0xff) << 32) | + ((long)(b[3] & 0xff) << 24) | + ((long)(b[2] & 0xff) << 16) | + ((long)(b[1] & 0xff) << 8) | + ((long)(b[0] & 0xff)); + } + + + public long getLongBE() { + long l = getLongBE(memOffset); + memOffset += 8; + return l; + } + + public long getLongBE(int offset) { + val[0] = getByte(offset); + val[1] = getByte(offset + 1); + val[2] = getByte(offset + 2); + val[3] = getByte(offset + 3); + val[4] = getByte(offset + 4); + val[5] = getByte(offset + 5); + val[6] = getByte(offset + 6); + val[7] = getByte(offset + 7); + return getLongBE(val); + } + + public long getLongBE(byte[] b) { + return ((long)(b[0] & 0xff) << 56) | + ((long)(b[1] & 0xff) << 48) | + ((long)(b[2] & 0xff) << 40) | + ((long)(b[3] & 0xff) << 32) | + ((long)(b[4] & 0xff) << 24) | + ((long)(b[5] & 0xff) << 16) | + ((long)(b[6] & 0xff) << 8) | + ((long)(b[7] & 0xff)); + } + +}