diff options
author | Adrien Thierry | 2019-08-14 16:33:36 +0000 |
---|---|---|
committer | Jonah Graham | 2019-09-03 14:44:02 +0000 |
commit | 975ff2f0cceb61467dad967589768610a081563a (patch) | |
tree | a0baacc2d35fbd9f8304a1b7900e42658503a098 | |
parent | fc46dc3304a117f3d1f5e0a6c2f7f0a963d09ee0 (diff) | |
download | org.eclipse.cdt-975ff2f0cceb61467dad967589768610a081563a.tar.gz org.eclipse.cdt-975ff2f0cceb61467dad967589768610a081563a.tar.xz org.eclipse.cdt-975ff2f0cceb61467dad967589768610a081563a.zip |
Bug 550076 - Added new parser for PE executables
This new parser is compatible with both 32 bit and 64 bit executables.
Change-Id: Ief9db7c6fcc10ea9e92d5ca58186eb50100d39f6
Signed-off-by: Adrien Thierry <adrien.thierry@spacecodesign.com>
30 files changed, 3081 insertions, 4 deletions
diff --git a/core/org.eclipse.cdt.core/plugin.properties b/core/org.eclipse.cdt.core/plugin.properties index 4ba81d30227..39cddf9c21b 100755 --- a/core/org.eclipse.cdt.core/plugin.properties +++ b/core/org.eclipse.cdt.core/plugin.properties @@ -43,8 +43,10 @@ IndexerMarker=Indexer Marker ElfParser.name=Elf Parser GNUElfParser.name=GNU Elf Parser -PEWindowsParser.name=PE Windows Parser -CygwinPEParser.name=Cygwin PE Parser +PEWindowsParser.name=PE Windows Parser (Deprecated) +PE64WindowsParser.name=PE64 Windows Parser +CygwinPEParser.name=Cygwin PE Parser (Deprecated) +CygwinPE64Parser.name=Cygwin PE64 Parser XCOFF32Parser.name=AIX XCOFF32 Parser MachOParser.name=Mach-O Parser (Deprecated) MachOParser64.name=Mach-O 64 Parser diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index a2c915f60c8..63f59d96ec8 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -72,6 +72,8 @@ </run> </cextension> </extension> + <!-- Deprecated as of CDT 6.9. Use 64 bit version PEParser64 instead. + This class is planned for removal in next major release. --> <extension id="PE" name="%PEWindowsParser.name" @@ -83,6 +85,18 @@ </cextension> </extension> <extension + id="PE64" + name="%PE64WindowsParser.name" + point="org.eclipse.cdt.core.BinaryParser"> + <cextension> + <run + class="org.eclipse.cdt.utils.coff.parser.PEParser64"> + </run> + </cextension> + </extension> + <!-- Deprecated as of CDT 6.9. Use 64 bit version CygwinPEParser64 instead. + This class is planned for removal in next major release. --> + <extension id="Cygwin_PE" name="%CygwinPEParser.name" point="org.eclipse.cdt.core.BinaryParser"> @@ -93,6 +107,16 @@ </cextension> </extension> <extension + id="Cygwin_PE64" + name="%CygwinPE64Parser.name" + point="org.eclipse.cdt.core.BinaryParser"> + <cextension> + <run + class="org.eclipse.cdt.utils.coff.parser.CygwinPEParser64"> + </run> + </cextension> + </extension> + <extension id="XCOFF32" name="%XCOFF32Parser.name" point="org.eclipse.cdt.core.BinaryParser"> 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 index b418fb34fd4..28169a3e5db 100644 --- 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 @@ -26,6 +26,11 @@ import org.eclipse.cdt.core.CCorePlugin; import com.ibm.icu.text.DateFormat; +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link Coff64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class Coff { public static final String NL = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff64.java new file mode 100644 index 00000000000..1530253c767 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/Coff64.java @@ -0,0 +1,819 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - Initial Coff class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff; + +import java.io.EOFException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel.MapMode; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.eclipse.cdt.core.CCorePlugin; + +import com.ibm.icu.text.DateFormat; + +/** + * @since 6.9 + */ +public class Coff64 { + + public static final String NL = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + 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); + commonSetup(hdr, true); + } + + public FileHeader(byte[] hdr, boolean little) throws EOFException { + commonSetup(hdr, little); + } + + public void commonSetup(byte[] hdr, boolean little) throws EOFException { + if (hdr == null || hdr.length < FILHSZ) { + throw new EOFException(CCorePlugin.getResourceString("Util.exception.arrayToSmall")); //$NON-NLS-1$ + } + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, little); + 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); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("FILE HEADER VALUES").append(NL); //$NON-NLS-1$ + + buffer.append("f_magic = ").append(f_magic).append(NL); //$NON-NLS-1$ + buffer.append("f_nscns = ").append(f_nscns).append(NL); //$NON-NLS-1$ + + buffer.append("f_timdat = "); //$NON-NLS-1$ + buffer.append(DateFormat.getDateInstance().format(new Date(f_timdat))); + buffer.append(NL); + + buffer.append("f_symptr = ").append(f_symptr).append(NL); //$NON-NLS-1$ + buffer.append("f_nsyms = ").append(f_nsyms).append(NL); //$NON-NLS-1$ + buffer.append("f_opthdr = ").append(f_opthdr).append(NL); //$NON-NLS-1$ + buffer.append("f_flags = ").append(f_flags).append(NL); //$NON-NLS-1$ + return buffer.toString(); + } + } + + public static class OptionalHeader { + public short magic; /* 2 bytes: type of file */ + public OptionalHeader64 optionalHeader64; + public OptionalHeader32 optionalHeader32; + + private final static int MAGICSZ = 2; + private boolean is64Bits; + + public static class OptionalHeader64 { + public final static int AOUTHDRSZ = 22; + + 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 OptionalHeader64(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[AOUTHDRSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + vstamp = memory.getShort(); + tsize = memory.getInt(); + dsize = memory.getInt(); + bsize = memory.getInt(); + entry = memory.getInt(); + text_start = memory.getInt(); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("vstamp = ").append(vstamp).append(NL); //$NON-NLS-1$ + buffer.append("tsize = ").append(tsize).append(NL); //$NON-NLS-1$ + buffer.append("dsize = ").append(dsize).append(NL); //$NON-NLS-1$ + buffer.append("bsize = ").append(bsize).append(NL); //$NON-NLS-1$ + buffer.append("entry = ").append(entry).append(NL); //$NON-NLS-1$ + buffer.append("text_start = ").append(text_start).append(NL); //$NON-NLS-1$ + return buffer.toString(); + } + } + + public static class OptionalHeader32 { + public final static int AOUTHDRSZ = 26; + + 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 OptionalHeader32(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] hdr = new byte[AOUTHDRSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + vstamp = memory.getShort(); + tsize = memory.getInt(); + dsize = memory.getInt(); + bsize = memory.getInt(); + entry = memory.getInt(); + text_start = memory.getInt(); + data_start = memory.getInt(); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("vstamp = ").append(vstamp).append(NL); //$NON-NLS-1$ + buffer.append("tsize = ").append(tsize).append(NL); //$NON-NLS-1$ + buffer.append("dsize = ").append(dsize).append(NL); //$NON-NLS-1$ + buffer.append("bsize = ").append(bsize).append(NL); //$NON-NLS-1$ + buffer.append("entry = ").append(entry).append(NL); //$NON-NLS-1$ + buffer.append("text_start = ").append(text_start).append(NL); //$NON-NLS-1$ + buffer.append("data_start = ").append(data_start).append(NL); //$NON-NLS-1$ + return buffer.toString(); + } + } + + 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[MAGICSZ]; + file.readFully(hdr); + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); + magic = memory.getShort(); + + if (magic == 523) { // 64 bit executable + optionalHeader64 = new OptionalHeader64(file, file.getFilePointer()); + is64Bits = true; + } else if (magic == 267) { // 32 bit executable + optionalHeader32 = new OptionalHeader32(file, file.getFilePointer()); + is64Bits = false; + } + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("OPTIONAL HEADER VALUES").append(NL); //$NON-NLS-1$ + buffer.append("magic = ").append(magic).append(NL); //$NON-NLS-1$ + + if (is64Bits()) + buffer.append(optionalHeader64.toString()); + else + buffer.append(optionalHeader32.toString()); + + return buffer.toString(); + } + + public boolean is64Bits() { + return is64Bits; + } + + public int getSize() { + if (is64Bits()) + return OptionalHeader64.AOUTHDRSZ; + else + return OptionalHeader32.AOUTHDRSZ; + } + } + + public static class SectionHeader { + + public final static int SCNHSZ = 40; + + /* names of "special" sections */ + public final static String _TEXT = ".text"; //$NON-NLS-1$ + public final static String _DATA = ".data"; //$NON-NLS-1$ + public final static String _BSS = ".bss"; //$NON-NLS-1$ + public final static String _COMMENT = ".comment"; //$NON-NLS-1$ + public final static String _LIB = ".lib"; //$NON-NLS-1$ + + /* 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; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("SECTION HEADER VALUES").append(NL); //$NON-NLS-1$ + buffer.append(new String(s_name)).append(NL); + buffer.append("s_paddr = ").append(s_paddr).append(NL); //$NON-NLS-1$ + buffer.append("s_vaddr = ").append(s_vaddr).append(NL); //$NON-NLS-1$ + buffer.append("s_size = ").append(s_size).append(NL); //$NON-NLS-1$ + buffer.append("s_scnptr = ").append(s_scnptr).append(NL); //$NON-NLS-1$ + buffer.append("s_relptr = ").append(s_relptr).append(NL); //$NON-NLS-1$ + buffer.append("s_lnnoptr = ").append(s_lnnoptr).append(NL); //$NON-NLS-1$ + buffer.append("s_nreloc = ").append(s_nreloc).append(NL); //$NON-NLS-1$ + buffer.append("s_nlnno = ").append(s_nlnno).append(NL); //$NON-NLS-1$ + buffer.append("s_flags = ").append(s_flags).append(NL); //$NON-NLS-1$ + ///* + 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(); + } + + /** + * @since 5.1 + */ + public ByteBuffer mapSectionData() throws IOException { + return sfile.getChannel().map(MapMode.READ_ONLY, s_scnptr, s_paddr).load().asReadOnlyBuffer(); + } + } + + 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(); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("RELOC VALUES").append(NL); //$NON-NLS-1$ + buffer.append("r_vaddr = ").append(r_vaddr); //$NON-NLS-1$ + buffer.append(" r_symndx = ").append(r_symndx).append(NL); //$NON-NLS-1$ + 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(); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + if (l_lnno == 0) { + buffer.append("Function address = ").append(l_addr).append(NL); //$NON-NLS-1$ + } else { + buffer.append("line# ").append(l_lnno); //$NON-NLS-1$ + buffer.append(" at address = ").append(l_addr).append(NL); //$NON-NLS-1$ + } + return buffer.toString(); + } + } + + public static class Symbol { + public final static int SYMSZ = 18; + public final static int SYMNMLEN = 8; + + /* Derived types, in n_type. */ + public final static int DT_NON = 0; /* no derived type */ + public final static int DT_PTR = 1; /* pointer */ + public final static int DT_FCN = 2; /* function */ + public final static int DT_ARY = 3; /* array */ + + public final static int N_TMASK = 0x30; + public final static int N_BTSHFT = 4; + public final static int N_TSHIFT = 2; + + /** @since 5.3 */ + public final static int T_NULL = 0x00; /* No symbol */ + /** @since 5.3 */ + public final static int T_VOID = 0x01; /* -- 0001 void function argument (not used) */ + /** @since 5.3 */ + public final static int T_CHAR = 0x02; /* -- 0010 character */ + /** @since 5.3 */ + public final static int T_SHORT = 0x03; /* -- 0011 short integer */ + /** @since 5.3 */ + public final static int T_INT = 0x04; /* -- 0100 integer */ + /** @since 5.3 */ + public final static int T_LONG = 0x05; /* -- 0101 long integer */ + /** @since 5.3 */ + public final static int T_FLOAT = 0x06; /* -- 0110 floating point */ + /** @since 5.3 */ + public final static int T_DOUBLE = 0x07; /* -- 0111 double precision float */ + /** @since 5.3 */ + public final static int T_STRUCT = 0x08; /* -- 1000 structure */ + /** @since 5.3 */ + public final static int T_UNION = 0x09; /* -- 1001 union */ + /** @since 5.3 */ + public final static int T_ENUM = 0x10; /* -- 1010 enumeration */ + /** @since 5.3 */ + public final static int T_MOE = 0x11; /* -- 1011 member of enumeration */ + /** @since 5.3 */ + public final static int T_UCHAR = 0x12; /* -- 1100 unsigned character */ + /** @since 5.3 */ + public final static int T_USHORT = 0x13; /* -- 1101 unsigned short */ + /** @since 5.3 */ + public final static int T_UINT = 0x14; /* -- 1110 unsigned integer */ + /** @since 5.3 */ + public final static int T_ULONG = 0x15; /* -- 1111 unsigned long */ + /** @since 5.3 */ + public final static int T_LNGDBL = 0x16; /* -1 0000 long double (special case bit pattern) */ + + 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. Number of auxiliary enties. */ + /** @since 5.4 */ + public short n_aux_lnno; /* short, line number in auxiliary entry */ + /** @since 5.4 */ + public short n_aux_size; /* short, size in bytes in auxiliary entry */ + /** @since 5.4 */ + public int n_aux_fcn_size; /* long, size of function in bytes found in auxiliary entry */ + + private boolean is64Bit; + + public Symbol(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer(), false); + } + + public Symbol(RandomAccessFile file, long offset) throws IOException { + this(file, offset, false); + } + + /** + * @since 5.4 + */ + public Symbol(RandomAccessFile file, boolean is64Bit) throws IOException { + this(file, file.getFilePointer(), is64Bit); + } + + /** + * @since 5.4 + */ + public Symbol(RandomAccessFile file, long offset, boolean is64Bit) throws IOException { + this.is64Bit = is64Bit; + 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(); + if (n_numaux > 0) { + // read auxiliary section + byte[] bytes2 = new byte[SYMSZ * n_numaux]; + file.readFully(bytes2); + memory = new ReadMemoryAccess(bytes2, true); + memory.getInt(); // ignore first 4 bytes - tag index + n_aux_lnno = memory.getShort(); + n_aux_size = memory.getShort(); + // function size is unioned with lnno and size so we must rewind and + // reread + memory = new ReadMemoryAccess(bytes2, true); + memory.getInt(); // ignore first 4 bytes - tag index + n_aux_fcn_size = memory.getInt(); + } + } + + public boolean isLongName() { + return (_n_name[0] == 0); + } + + public String getName() { + // For a long name, _n_name[0] == 0 and this would just return empty string. + for (int i = 0; i < _n_name.length; i++) { + if (_n_name[i] == 0) { + return new String(_n_name, 0, i); + } + } + // all eight bytes are filled + return new String(_n_name); + } + + public String getName(byte[] table) { + if (table.length > 0 && isLongName()) { + ReadMemoryAccess memory = new ReadMemoryAccess(_n_name, true); + memory.getInt(); // pass over the first 4 bytes. + // The first for bytes of the string table represent the + // number of bytes in the string table. + int offset = memory.getInt() - 4; + if (offset > 0) { + for (int i = offset; i < table.length; i++) { + if (table[i] == 0) { + return new String(table, offset, i - offset); + } + } + } + } + return getName(); + } + + /** @since 5.3 */ + public boolean isNoSymbol() { + return (n_type == T_NULL); + } + + public boolean isPointer() { + return (n_type & N_TMASK) == (DT_PTR << N_BTSHFT); + } + + public boolean isFunction() { + return (n_type & N_TMASK) == (DT_FCN << N_BTSHFT); + } + + public boolean isArray() { + return (n_type & N_TMASK) == (DT_ARY << N_BTSHFT); + } + + /** + * @since 5.4 + */ + public int getSize() { + if (n_type <= T_LNGDBL) { + switch (n_type) { + case T_CHAR: + case T_UCHAR: + return 1; + case T_SHORT: + case T_USHORT: + return 2; + case T_LONG: + case T_ULONG: + return 4; + case T_INT: + case T_UINT: + return 4; + case T_FLOAT: + return 4; + case T_DOUBLE: + return 8; + case T_MOE: + return 4; + case T_LNGDBL: + return 16; + case T_ENUM: + case T_STRUCT: + case T_UNION: + return n_aux_size; + } + } else if (isFunction()) { + return n_aux_fcn_size; + } else if (isArray()) { + return n_aux_size; + } else if (isPointer()) { + return is64Bit ? 8 : 4; + } + return 1; + } + + @Override + public String toString() { + return getName(); + } + + } + + 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 = FileHeader.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, (getFileHeader().f_flags & FileHeader.F_AR32WR) == 0); + } + } + 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 < rfile.length()) { + 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; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + 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].getName(getStringTable())).append(NL); + } + } catch (IOException e) { + } + + return buffer.toString(); + } + + public static String[] getStringTable(byte[] bytes) { + List<String> 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 - offset)); + offset = i + 1; + } + } + return aList.toArray(new String[0]); + } + + public Coff64(String filename) throws IOException { + this(new RandomAccessFile(filename, "r"), 0); //$NON-NLS-1$ + } + + public Coff64(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 { + Coff64 coff = new Coff64(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/PE.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE.java index a19c36fc8d2..e8b55c744db 100644 --- 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 @@ -67,6 +67,12 @@ import org.eclipse.cdt.utils.debug.stabs.StabsReader; * +-------------------+ * </pre> */ + +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link PE64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class PE { public static final String NL = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE64.java new file mode 100644 index 00000000000..6585605a7cf --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/PE64.java @@ -0,0 +1,1029 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - Initial PE class + *******************************************************************************/ + +package org.eclipse.cdt.utils.coff; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IAddressFactory; +import org.eclipse.cdt.core.ISymbolReader; +import org.eclipse.cdt.utils.Addr32Factory; +import org.eclipse.cdt.utils.coff.Coff64.FileHeader; +import org.eclipse.cdt.utils.coff.Coff64.OptionalHeader; +import org.eclipse.cdt.utils.coff.Coff64.SectionHeader; +import org.eclipse.cdt.utils.coff.Coff64.Symbol; +import org.eclipse.cdt.utils.coff.Exe.ExeHeader; +import org.eclipse.cdt.utils.debug.dwarf.DwarfReader; +import org.eclipse.cdt.utils.debug.stabs.StabsReader; + +/** + * The PE file header consists of an MS-DOS stub, the PE signature, the COFF file Header + * and an Optional Header. + * <pre> + * +-------------------+ + * | DOS-stub | + * +-------------------+ + * | file-header | + * +-------------------+ + * | optional header | + * |- - - - - - - - - -| + * | | + * | data directories | + * | | + * +-------------------+ + * | | + * | section headers | + * | | + * +-------------------+ + * | | + * | section 1 | + * | | + * +-------------------+ + * | | + * | section 2 | + * | | + * +-------------------+ + * | | + * | ... | + * | | + * +-------------------+ + * | | + * | section n | + * | | + * +-------------------+ + * </pre> + * @since 6.9 + */ +public class PE64 { + + public static final String NL = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + RandomAccessFile rfile; + String filename; + ExeHeader exeHeader; + DOSHeader dosHeader; + FileHeader fileHeader; + OptionalHeader optionalHeader; + NTOptionalHeader64 ntHeader64; + NTOptionalHeader32 ntHeader32; + ImageDataDirectory[] dataDirectories; + SectionHeader[] scnhdrs; + Symbol[] symbolTable; + byte[] stringTable; + + public static class Attribute { + public static final int PE_TYPE_EXE = 1; + public static final int PE_TYPE_SHLIB = 2; + public static final int PE_TYPE_OBJ = 3; + public static final int PE_TYPE_CORE = 4; + + String cpu; + int type; + int word; + boolean bDebug; + boolean isle; + IAddressFactory addrFactory; + + public String getCPU() { + return cpu; + } + + public int getType() { + return type; + } + + public boolean hasDebug() { + return bDebug; + } + + public boolean isLittleEndian() { + return isle; + } + + public int getWord() { + return word; + } + } + + /** + */ + 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); + commonSetup(memory); + } + + public DOSHeader(byte[] hdr, boolean little) throws IOException { + ReadMemoryAccess memory = new ReadMemoryAccess(hdr, little); + commonSetup(memory); + } + + public DOSHeader(ReadMemoryAccess memory) throws IOException { + commonSetup(memory); + } + + public void commonSetup(ReadMemoryAccess memory) throws IOException { + if (memory.getSize() < DOSHDRSZ) { + throw new IOException("Not a Dos Header"); //$NON-NLS-1$ + } + memory.getBytes(e_res); + memory.getBytes(e_oemid); + memory.getBytes(e_oeminfo); + memory.getBytes(e_res2); + e_lfanew = memory.getInt(); + memory.getBytes(dos_message); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("DOS STUB VALUES").append(NL); //$NON-NLS-1$ + buffer.append("e_lfanew = ").append(e_lfanew).append(NL); //$NON-NLS-1$ + buffer.append(new String(dos_message)).append(NL); + return buffer.toString(); + } + } + + public static class IMAGE_DEBUG_DIRECTORY { + final int DEBUGDIRSZ = 28; + public int Characteristics; + public int TimeDateStamp; + public short MajorVersion; + public short MinorVersion; + public int Type; + public int SizeOfData; + public int AddressOfRawData; + public int PointerToRawData; + + public IMAGE_DEBUG_DIRECTORY(RandomAccessFile file, long offset) throws IOException { + file.seek(offset); + byte[] dir = new byte[DEBUGDIRSZ]; + file.readFully(dir); + ReadMemoryAccess memory = new ReadMemoryAccess(dir, true); + Characteristics = memory.getInt(); + TimeDateStamp = memory.getInt(); + MajorVersion = memory.getShort(); + MinorVersion = memory.getShort(); + Type = memory.getInt(); + SizeOfData = memory.getInt(); + AddressOfRawData = memory.getInt(); + PointerToRawData = memory.getInt(); + } + } + + public static class IMAGE_DATA_DIRECTORY { + + public int VirtualAddress; + public int Size; + } + + public static class NTOptionalHeader64 { + + public final static int NTHDRSZ = 216; + public long ImageBase; // 8 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 long SizeOfStackReserve; // 8 bytes. + public long SizeOfStackCommit; // 8 bytes. + public long SizeOfHeapReserve; // 8 bytes. + public long SizeOfHeapCommit; // 8 bytes. + public int LoaderFlags; // 4 bytes. + public int NumberOfRvaAndSizes; // 4 bytes. + public IMAGE_DATA_DIRECTORY DataDirectory[]; + + public NTOptionalHeader64(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public NTOptionalHeader64(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.getLong(); + 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.getLong(); + SizeOfStackCommit = memory.getLong(); + SizeOfHeapReserve = memory.getLong(); + SizeOfHeapCommit = memory.getLong(); + LoaderFlags = memory.getInt(); + NumberOfRvaAndSizes = memory.getInt(); + + DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes]; // 8*16=128 bytes + for (int i = 0; i < NumberOfRvaAndSizes; i++) { + DataDirectory[i] = new IMAGE_DATA_DIRECTORY(); + DataDirectory[i].VirtualAddress = memory.getInt(); + DataDirectory[i].Size = memory.getInt(); + } + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("NT OPTIONAL HEADER VALUES").append(NL); //$NON-NLS-1$ + buffer.append("ImageBase = ").append(ImageBase).append(NL); //$NON-NLS-1$ + buffer.append("SexctionAlignement = ").append(SectionAlignment).append(NL); //$NON-NLS-1$ + buffer.append("FileAlignment = ").append(FileAlignment).append(NL); //$NON-NLS-1$ + buffer.append("MajorOSVersion = ").append(MajorOperatingSystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("MinorOSVersion = ").append(MinorOperatingSystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("MajorImageVersion = ").append(MajorImageVersion).append(NL); //$NON-NLS-1$ + buffer.append("MinorImageVersion = ").append(MinorImageVersion).append(NL); //$NON-NLS-1$ + buffer.append("MajorSubVersion = ").append(MajorSubsystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("MinorSubVersion = ").append(MinorSubsystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("Reserved = ").append(Reserved).append(NL); //$NON-NLS-1$ + buffer.append("SizeOfImage = ").append(SizeOfImage).append(NL); //$NON-NLS-1$ + buffer.append("SizeOfHeaders = ").append(SizeOfHeaders).append(NL); //$NON-NLS-1$ + buffer.append("CheckSum = ").append(CheckSum).append(NL); //$NON-NLS-1$ + buffer.append("Subsystem = ").append(Subsystem).append(NL); //$NON-NLS-1$ + buffer.append("DLL = ").append(DLLCharacteristics).append(NL); //$NON-NLS-1$ + buffer.append("StackReserve = ").append(SizeOfStackReserve).append(NL); //$NON-NLS-1$ + buffer.append("StackCommit = ").append(SizeOfStackCommit).append(NL); //$NON-NLS-1$ + buffer.append("HeapReserve = ").append(SizeOfHeapReserve).append(NL); //$NON-NLS-1$ + buffer.append("HeapCommit = ").append(SizeOfHeapCommit).append(NL); //$NON-NLS-1$ + buffer.append("LoaderFlags = ").append(LoaderFlags).append(NL); //$NON-NLS-1$ + buffer.append("#Rva size = ").append(NumberOfRvaAndSizes).append(NL); //$NON-NLS-1$ + return buffer.toString(); + } + } + + public static class NTOptionalHeader32 { + + public final static int NTHDRSZ = 196; + 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 IMAGE_DATA_DIRECTORY DataDirectory[]; + + public NTOptionalHeader32(RandomAccessFile file) throws IOException { + this(file, file.getFilePointer()); + } + + public NTOptionalHeader32(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(); + + DataDirectory = new IMAGE_DATA_DIRECTORY[NumberOfRvaAndSizes]; // 8*16=128 bytes + for (int i = 0; i < NumberOfRvaAndSizes; i++) { + DataDirectory[i] = new IMAGE_DATA_DIRECTORY(); + DataDirectory[i].VirtualAddress = memory.getInt(); + DataDirectory[i].Size = memory.getInt(); + } + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("NT OPTIONAL HEADER VALUES").append(NL); //$NON-NLS-1$ + buffer.append("ImageBase = ").append(ImageBase).append(NL); //$NON-NLS-1$ + buffer.append("SexctionAlignement = ").append(SectionAlignment).append(NL); //$NON-NLS-1$ + buffer.append("FileAlignment = ").append(FileAlignment).append(NL); //$NON-NLS-1$ + buffer.append("MajorOSVersion = ").append(MajorOperatingSystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("MinorOSVersion = ").append(MinorOperatingSystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("MajorImageVersion = ").append(MajorImageVersion).append(NL); //$NON-NLS-1$ + buffer.append("MinorImageVersion = ").append(MinorImageVersion).append(NL); //$NON-NLS-1$ + buffer.append("MajorSubVersion = ").append(MajorSubsystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("MinorSubVersion = ").append(MinorSubsystemVersion).append(NL); //$NON-NLS-1$ + buffer.append("Reserved = ").append(Reserved).append(NL); //$NON-NLS-1$ + buffer.append("SizeOfImage = ").append(SizeOfImage).append(NL); //$NON-NLS-1$ + buffer.append("SizeOfHeaders = ").append(SizeOfHeaders).append(NL); //$NON-NLS-1$ + buffer.append("CheckSum = ").append(CheckSum).append(NL); //$NON-NLS-1$ + buffer.append("Subsystem = ").append(Subsystem).append(NL); //$NON-NLS-1$ + buffer.append("DLL = ").append(DLLCharacteristics).append(NL); //$NON-NLS-1$ + buffer.append("StackReserve = ").append(SizeOfStackReserve).append(NL); //$NON-NLS-1$ + buffer.append("StackCommit = ").append(SizeOfStackCommit).append(NL); //$NON-NLS-1$ + buffer.append("HeapReserve = ").append(SizeOfHeapReserve).append(NL); //$NON-NLS-1$ + buffer.append("HeapCommit = ").append(SizeOfHeapCommit).append(NL); //$NON-NLS-1$ + buffer.append("LoaderFlags = ").append(LoaderFlags).append(NL); //$NON-NLS-1$ + buffer.append("#Rva size = ").append(NumberOfRvaAndSizes).append(NL); //$NON-NLS-1$ + return buffer.toString(); + } + } + + public class ImageDataDirectory { + public int rva; + public int size; + + public ImageDataDirectory(int r, int s) { + rva = r; + size = s; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("rva = ").append(rva).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ + buffer.append("size = ").append(size).append(NL); //$NON-NLS-1$ + 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(); + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("rva = ").append(rva); //$NON-NLS-1$ + buffer.append(" timestamp = ").append(timestamp); //$NON-NLS-1$ + buffer.append(" forwarder = ").append(forwarder); //$NON-NLS-1$ + buffer.append(" name = ").append(name); //$NON-NLS-1$ + buffer.append(" thunk = ").append(thunk).append(NL); //$NON-NLS-1$ + return buffer.toString(); + } + } + + public PE64(String filename) throws IOException { + this(filename, 0); + } + + public PE64(String filename, long pos) throws IOException { + this(filename, pos, true); + } + + public PE64(String filename, long pos, boolean filter) throws IOException { + try { + rfile = new RandomAccessFile(filename, "r"); //$NON-NLS-1$ + this.filename = filename; + rfile.seek(pos); + + // Object files do not have exe/dos header. + try { + 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(CCorePlugin.getResourceString("Util.exception.notPE")); //$NON-NLS-1$ + } + } catch (IOException e) { + rfile.seek(pos); + } + + fileHeader = new Coff64.FileHeader(rfile, rfile.getFilePointer()); + + // Check if this a valid machine. + if (!isValidMachine(fileHeader.f_magic)) { + throw new IOException(CCorePlugin.getResourceString("Util.exception.unknownFormat")); //$NON-NLS-1$ + } + + if (fileHeader.f_opthdr > 0) { + optionalHeader = new Coff64.OptionalHeader(rfile, rfile.getFilePointer()); + + if (optionalHeader.is64Bits()) + ntHeader64 = new NTOptionalHeader64(rfile, rfile.getFilePointer()); + else + ntHeader32 = new NTOptionalHeader32(rfile, rfile.getFilePointer()); + } + } finally { + if (rfile != null) { + rfile.close(); + rfile = null; + } + } + } + + public static boolean isValidMachine(int magic) { + // Check if this a valid machine. + switch (magic) { + case PEConstants.IMAGE_FILE_MACHINE_ALPHA: + case PEConstants.IMAGE_FILE_MACHINE_ARM: + case PEConstants.IMAGE_FILE_MACHINE_ARM2: + case PEConstants.IMAGE_FILE_MACHINE_ALPHA64: + case PEConstants.IMAGE_FILE_MACHINE_AMD64: + case PEConstants.IMAGE_FILE_MACHINE_I386: + case PEConstants.IMAGE_FILE_MACHINE_IA64: + case PEConstants.IMAGE_FILE_MACHINE_M68K: + case PEConstants.IMAGE_FILE_MACHINE_MIPS16: + case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU: + case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU16: + case PEConstants.IMAGE_FILE_MACHINE_POWERPC: + case PEConstants.IMAGE_FILE_MACHINE_R3000: + case PEConstants.IMAGE_FILE_MACHINE_R4000: + case PEConstants.IMAGE_FILE_MACHINE_R10000: + case PEConstants.IMAGE_FILE_MACHINE_SH3: + case PEConstants.IMAGE_FILE_MACHINE_SH4: + case PEConstants.IMAGE_FILE_MACHINE_THUMB: + // Ok; + return true; + //throw new IOException("Unknow machine/format"); + } + return false; + } + + public static Attribute getAttributes(FileHeader filhdr) { + Attribute attrib = new Attribute(); + // Machine type. + switch (filhdr.f_magic) { + case PEConstants.IMAGE_FILE_MACHINE_UNKNOWN: + attrib.cpu = "none"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_ALPHA: + attrib.cpu = "alpha"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_ARM: + case PEConstants.IMAGE_FILE_MACHINE_ARM2: + attrib.cpu = "arm"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_ALPHA64: + attrib.cpu = "arm64"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_AMD64: + attrib.cpu = "amd64"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_I386: + attrib.cpu = "x86"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_IA64: + attrib.cpu = "ia64"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_M68K: + attrib.cpu = "m68k"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_MIPS16: + attrib.cpu = "mips16"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU: + attrib.cpu = "mipsfpu"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU16: + attrib.cpu = "mipsfpu16"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_POWERPC: + attrib.cpu = "powerpc"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_R3000: + attrib.cpu = "r3000"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_R4000: + attrib.cpu = "r4000"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_R10000: + attrib.cpu = "r10000"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_SH3: + attrib.cpu = "sh3"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_SH4: + attrib.cpu = "sh4"; //$NON-NLS-1$ + break; + case PEConstants.IMAGE_FILE_MACHINE_THUMB: + attrib.cpu = "thumb"; //$NON-NLS-1$ + break; + } + + /* PE characteristics, FileHeader.f_flags. */ + if ((filhdr.f_flags & PEConstants.IMAGE_FILE_DLL) != 0) { + attrib.type = Attribute.PE_TYPE_SHLIB; + } else if ((filhdr.f_flags & PEConstants.IMAGE_FILE_EXECUTABLE_IMAGE) != 0) { + attrib.type = Attribute.PE_TYPE_EXE; + } else { + attrib.type = Attribute.PE_TYPE_OBJ; + } + + // For PE always assume little endian unless otherwise. + attrib.isle = true; + // Little Endian. + if ((filhdr.f_flags & PEConstants.IMAGE_FILE_BYTES_REVERSED_LO) != 0) { + attrib.isle = true; + } + // Big Endian. + if ((filhdr.f_flags & PEConstants.IMAGE_FILE_BYTES_REVERSED_HI) != 0) { + attrib.isle = false; + } + + // No debug information. + if ((filhdr.f_flags & PEConstants.IMAGE_FILE_DEBUG_STRIPPED) != 0) { + attrib.bDebug = false; + } else { + attrib.bDebug = true; + } + + // sizeof word. + if ((filhdr.f_flags & PEConstants.IMAGE_FILE_16BIT_MACHINE) != 0) { + attrib.word = 16; + } + if ((filhdr.f_flags & PEConstants.IMAGE_FILE_32BIT_MACHINE) != 0) { + attrib.word = 32; + } + + attrib.addrFactory = new Addr32Factory(); + return attrib; + } + + public static boolean isExeHeader(byte[] e_signature) { + if (e_signature == null || e_signature.length < 2 || e_signature[0] != 'M' || e_signature[1] != 'Z') + return false; + return true; + } + + public Attribute getAttribute() throws IOException { + return getAttributes(getFileHeader()); + } + + public static Attribute getAttribute(byte[] data) throws IOException { + ReadMemoryAccess memory = new ReadMemoryAccess(data, true); + int idx = 0; + try { + //Exe.ExeHeader exeHdr = new Exe.ExeHeader(memory); + new Exe.ExeHeader(memory); + DOSHeader dosHdr = new DOSHeader(memory); + // Jump the Coff header, and Check the sig. + idx = dosHdr.e_lfanew; + if (idx + 4 < data.length) { + if (!((data[idx + 0] == 'P') && (data[idx + 1] == 'E') && (data[idx + 2] == '\0') + && (data[idx + 3] == '\0'))) { + throw new IOException(CCorePlugin.getResourceString("Util.exception.notPE")); //$NON-NLS-1$ + } + idx += 4; + } + } catch (IOException e) { + } + if (idx < data.length) { + byte[] bytes = new byte[data.length - idx]; + System.arraycopy(data, idx, bytes, 0, data.length - idx); + Coff64.FileHeader filehdr = new Coff64.FileHeader(bytes, true); + if (isValidMachine(filehdr.f_magic)) { + return getAttributes(filehdr); + } + } + throw new IOException(CCorePlugin.getResourceString("Util.exception.notPE")); //$NON-NLS-1$ + } + + public static Attribute getAttribute(String file) throws IOException { + PE64 pe = new PE64(file); + Attribute attrib = pe.getAttribute(); + pe.dispose(); + return attrib; + } + + public void dispose() throws IOException { + if (rfile != null) { + rfile.close(); + rfile = null; + } + } + + @Override + protected void finalize() throws Throwable { + try { + dispose(); + } finally { + super.finalize(); + } + } + + public ExeHeader getExeHeader() { + return exeHeader; + } + + public DOSHeader getDOSHeader() { + return dosHeader; + } + + public FileHeader getFileHeader() { + return fileHeader; + } + + public OptionalHeader getOptionalHeader() { + return optionalHeader; + } + + public NTOptionalHeader64 getNTOptionalHeader64() { + return ntHeader64; + } + + public NTOptionalHeader32 getNTOptionalHeader32() { + return ntHeader32; + } + + public ImageDataDirectory[] getImageDataDirectories() throws IOException { + if (dataDirectories == null) { + RandomAccessFile accessFile = getRandomAccessFile(); + long offset = 0; + if (dosHeader != null) { + offset = dosHeader.e_lfanew + 4/*NT SIG*/; + } + + int ntHeaderSize = 0; + if (ntHeader64 != null) + ntHeaderSize = NTOptionalHeader64.NTHDRSZ; + else if (ntHeader32 != null) + ntHeaderSize = NTOptionalHeader32.NTHDRSZ; + + offset += FileHeader.FILHSZ + getOptionalHeader().getSize() + ntHeaderSize; + accessFile.seek(offset); + dataDirectories = new ImageDataDirectory[PEConstants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; + byte[] data = new byte[dataDirectories.length * (4 + 4)]; + accessFile.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) { + RandomAccessFile accessFile = getRandomAccessFile(); + scnhdrs = new SectionHeader[fileHeader.f_nscns]; + long offset = 0; + if (dosHeader != null) { + offset = dosHeader.e_lfanew + 4 /* NT SIG */; + } + offset += FileHeader.FILHSZ + fileHeader.f_opthdr; + for (int i = 0; i < scnhdrs.length; i++, offset += SectionHeader.SCNHSZ) { + scnhdrs[i] = new SectionHeader(accessFile, offset); + } + } + return scnhdrs; + } + + public Symbol[] getSymbols() throws IOException { + if (symbolTable == null) { + SectionHeader[] secHeaders = getSectionHeaders(); + NTOptionalHeader64 ntHeader64 = getNTOptionalHeader64(); + NTOptionalHeader32 ntHeader32 = getNTOptionalHeader32(); + + RandomAccessFile accessFile = getRandomAccessFile(); + long offset = fileHeader.f_symptr; + symbolTable = new Symbol[fileHeader.f_nsyms]; + for (int i = 0; i < symbolTable.length; i++, offset += Symbol.SYMSZ) { + Symbol newSym = new Symbol(accessFile, offset, (fileHeader.f_flags & FileHeader.F_AR32WR) == 0); + + // Now convert section offset of the symbol to image offset. + if (newSym.n_scnum >= 1 && newSym.n_scnum <= secHeaders.length) // valid section # + newSym.n_value += secHeaders[newSym.n_scnum - 1].s_vaddr; + + // convert to absolute address. + if (ntHeader64 != null) + newSym.n_value += ntHeader64.ImageBase; + else if (ntHeader32 != null) + newSym.n_value += ntHeader32.ImageBase; + + symbolTable[i] = newSym; + } + } + return symbolTable; + } + + public byte[] getStringTable() throws IOException { + if (stringTable == null) { + if (fileHeader.f_nsyms > 0) { + RandomAccessFile accessFile = getRandomAccessFile(); + long symbolsize = Symbol.SYMSZ * fileHeader.f_nsyms; + long offset = fileHeader.f_symptr + symbolsize; + accessFile.seek(offset); + byte[] bytes = new byte[4]; + accessFile.readFully(bytes); + int str_len = ReadMemoryAccess.getIntLE(bytes); + if (str_len > 4 && str_len < accessFile.length()) { + str_len -= 4; + stringTable = new byte[str_len]; + accessFile.seek(offset + 4); + accessFile.readFully(stringTable); + } else { + stringTable = new byte[0]; + } + } else { + stringTable = new byte[0]; + } + } + return stringTable; + } + + @Override + public String toString() { + StringBuilder buffer = new StringBuilder(); + if (exeHeader != null) { + buffer.append(exeHeader); + } + if (dosHeader != null) { + buffer.append(dosHeader); + } + buffer.append(fileHeader); + if (optionalHeader != null) { + buffer.append(optionalHeader); + } + if (ntHeader64 != null) { + buffer.append(ntHeader64); + } else if (ntHeader32 != null) { + buffer.append(ntHeader32); + } + try { + ImageDataDirectory[] dirs = getImageDataDirectories(); + for (int i = 0; i < dirs.length; i++) { + buffer.append("Entry ").append(i); //$NON-NLS-1$ + buffer.append(" ").append(dirs[i]); //$NON-NLS-1$ + } + } 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 = Coff64.getStringTable(bytes); + for (int i = 0; i < strings.length; i++) { + buffer.append(strings[i]); + } + } catch (IOException e) { + e.printStackTrace(); + } + return buffer.toString(); + } + + RandomAccessFile getRandomAccessFile() throws IOException { + if (rfile == null) { + rfile = new RandomAccessFile(filename, "r"); //$NON-NLS-1$ + } + return rfile; + } + + private ISymbolReader createCodeViewReader() { + ISymbolReader symReader = null; + final int IMAGE_DIRECTORY_ENTRY_DEBUG = 6; + + try { + // the debug directory is the 6th entry + NTOptionalHeader64 ntHeader64 = getNTOptionalHeader64(); + NTOptionalHeader32 ntHeader32 = getNTOptionalHeader32(); + if (ntHeader32 == null && ntHeader64 == null) + return null; + + int debugDir = 0, debugFormats = 0; + + if (ntHeader64 != null) { + if (ntHeader64.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_DEBUG) + return null; + + debugDir = ntHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + if (debugDir == 0) + return null; + + debugFormats = ntHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / 28; + if (debugFormats == 0) + return null; + } else if (ntHeader32 != null) { + if (ntHeader32.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_DEBUG) + return null; + + debugDir = ntHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + if (debugDir == 0) + return null; + + debugFormats = ntHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / 28; + if (debugFormats == 0) + return null; + } + + SectionHeader[] sections = getSectionHeaders(); + + // loop through the section headers to find the .rdata section + for (int i = 0; i < sections.length; i++) { + String name = new String(sections[i].s_name).trim(); + if (name.equals(".rdata")) { //$NON-NLS-1$ + // figure out the file offset of the debug ddirectory entries + int offsetInto_rdata = debugDir - sections[i].s_vaddr; + int fileOffset = sections[i].s_scnptr + offsetInto_rdata; + RandomAccessFile accessFile = getRandomAccessFile(); + + // loop through the debug directories looking for CodeView (type 2) + for (int j = 0; j < debugFormats; j++) { + PE64.IMAGE_DEBUG_DIRECTORY dir = new PE64.IMAGE_DEBUG_DIRECTORY(accessFile, fileOffset); + + if ((2 == dir.Type) && (dir.SizeOfData > 0)) { + // CodeView found, seek to actual data + int debugBase = dir.PointerToRawData; + accessFile.seek(debugBase); + + // sanity check. the first four bytes of the CodeView + // data should be "NB11" + String s2 = accessFile.readLine(); + if (s2.startsWith("NB11")) { //$NON-NLS-1$ + Attribute att = getAttribute(); + symReader = new CodeViewReader(accessFile, debugBase, att.isLittleEndian()); + return symReader; + } + } + fileOffset += dir.DEBUGDIRSZ; + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + + return symReader; + } + + private ISymbolReader createStabsReader() { + ISymbolReader symReader = null; + try { + SectionHeader[] sections = getSectionHeaders(); + byte[] stab = null; + byte[] stabstr = null; + + // loop through the section headers looking for stabs info + for (int i = 0; i < sections.length; i++) { + String name = new String(sections[i].s_name).trim(); + if (name.equals(".stab")) { //$NON-NLS-1$ + stab = sections[i].getRawData(); + } + if (name.equals(".stabstr")) { //$NON-NLS-1$ + stabstr = sections[i].getRawData(); + } + } + + // if we found both sections then proceed + if (stab != null && stabstr != null) { + Attribute att = getAttribute(); + symReader = new StabsReader(stab, stabstr, att.isLittleEndian()); + } + + } catch (IOException e) { + } + return symReader; + } + + public ISymbolReader getSymbolReader() { + ISymbolReader reader = null; + reader = createStabsReader(); + if (reader == null) { + reader = createCodeViewReader(); + } + if (reader == null) { + reader = createDwarfReader(); + } + return reader; + } + + private ISymbolReader createDwarfReader() { + DwarfReader reader = null; + // Check if Dwarf data exists + try { + reader = new DwarfReader(this); + } catch (IOException e) { + // No Dwarf data in the Elf. + } + return reader; + } + + /** + * @since 5.1 + */ + public String getStringTableEntry(int offset) throws IOException { + byte[] bytes = getStringTable(); + offset = offset - 4; + for (int i = offset; i < bytes.length; i++) { + if (bytes[i] == 0) { + return new String(bytes, offset, i - offset); + } + } + + return ""; //$NON-NLS-1$ + } + + /** + * @since 5.1 + */ + public String getFilename() { + return filename; + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive.java index f2c3fe73c98..b5bb34ffefe 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive.java @@ -20,6 +20,11 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; import org.eclipse.cdt.utils.AR.ARHeader; import org.eclipse.core.runtime.IPath; +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link CygwinPEBinaryArchive64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class CygwinPEBinaryArchive extends PEBinaryArchive { /** diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive64.java new file mode 100644 index 00000000000..1737b3401cd --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryArchive64.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2004, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial CygwinPEBinaryArchive class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; +import org.eclipse.cdt.utils.AR.ARHeader; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class CygwinPEBinaryArchive64 extends PEBinaryArchive64 { + + /** + * @param parser + * @param path + * @throws IOException + */ + public CygwinPEBinaryArchive64(PEParser64 parser, IPath path) throws IOException { + super(parser, path); + } + + @Override + protected void addArchiveMembers(ARHeader[] headers, ArrayList<IBinaryObject> children2) { + for (int i = 0; i < headers.length; i++) { + IBinaryObject bin = new CygwinPEBinaryObject64(getBinaryParser(), getPath(), headers[i]); + children.add(bin); + } + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable.java index 5051e409291..3290f748a74 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable.java @@ -18,6 +18,11 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.core.runtime.IPath; +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link CygwinPEBinaryExecutable64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class CygwinPEBinaryExecutable extends CygwinPEBinaryObject implements IBinaryExecutable { /** diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable64.java new file mode 100644 index 00000000000..f95f032c6e4 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryExecutable64.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2004, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial CygwinPEBinaryExecutable class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class CygwinPEBinaryExecutable64 extends CygwinPEBinaryObject64 implements IBinaryExecutable { + + /** + * @param parser + * @param path + * @param executable + */ + public CygwinPEBinaryExecutable64(IBinaryParser parser, IPath path, int executable) { + super(parser, path, IBinaryFile.EXECUTABLE); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java index d74bed3ffcb..695bffeb5fe 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject.java @@ -41,6 +41,11 @@ import org.eclipse.core.runtime.Path; /* * CygwinPEBinaryObject */ +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link CygwinPEBinaryObject64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class CygwinPEBinaryObject extends PEBinaryObject { private Addr2line autoDisposeAddr2line; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject64.java new file mode 100644 index 00000000000..1d93731a844 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryObject64.java @@ -0,0 +1,320 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial CygwinPEBinaryObject class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.cdt.core.CConventions; +import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.IBinaryParser.ISymbol; +import org.eclipse.cdt.utils.AR.ARHeader; +import org.eclipse.cdt.utils.Addr2line; +import org.eclipse.cdt.utils.Addr32; +import org.eclipse.cdt.utils.CPPFilt; +import org.eclipse.cdt.utils.CygPath; +import org.eclipse.cdt.utils.ICygwinToolsFactroy; +import org.eclipse.cdt.utils.NM; +import org.eclipse.cdt.utils.Objdump; +import org.eclipse.cdt.utils.Symbol; +import org.eclipse.cdt.utils.coff.Coff64; +import org.eclipse.cdt.utils.coff.PE64; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; + +/** + * @since 6.9 + */ +public class CygwinPEBinaryObject64 extends PEBinaryObject64 { + + private Addr2line autoDisposeAddr2line; + private Addr2line symbolLoadingAddr2line; + private CygPath symbolLoadingCygPath; + private CPPFilt symbolLoadingCPPFilt; + long starttime; + + /** + * @param parser + * @param path + * @param header + */ + public CygwinPEBinaryObject64(IBinaryParser parser, IPath path, ARHeader header) { + super(parser, path, header); + } + + public CygwinPEBinaryObject64(IBinaryParser parser, IPath path, int type) { + super(parser, path, type); + } + + public Addr2line getAddr2line(boolean autodisposing) { + if (!autodisposing) { + return getAddr2line(); + } + if (autoDisposeAddr2line == null) { + autoDisposeAddr2line = getAddr2line(); + if (autoDisposeAddr2line != null) { + starttime = System.currentTimeMillis(); + Runnable worker = () -> { + + long diff = System.currentTimeMillis() - starttime; + while (diff < 10000) { + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + break; + } + diff = System.currentTimeMillis() - starttime; + } + stopAddr2Line(); + }; + new Thread(worker, "Addr2line Reaper").start(); //$NON-NLS-1$ + } + } else { + starttime = System.currentTimeMillis(); // reset autodispose timeout + } + return autoDisposeAddr2line; + } + + synchronized void stopAddr2Line() { + if (autoDisposeAddr2line != null) { + autoDisposeAddr2line.dispose(); + } + autoDisposeAddr2line = null; + } + + private Addr2line getAddr2line() { + ICygwinToolsFactroy factory = getBinaryParser().getAdapter(ICygwinToolsFactroy.class); + if (factory != null) { + return factory.getAddr2line(getPath()); + } + return null; + } + + protected CPPFilt getCPPFilt() { + ICygwinToolsFactroy factory = getBinaryParser().getAdapter(ICygwinToolsFactroy.class); + if (factory != null) { + return factory.getCPPFilt(); + } + return null; + } + + protected Objdump getObjdump() { + ICygwinToolsFactroy factory = getBinaryParser().getAdapter(ICygwinToolsFactroy.class); + if (factory != null) { + return factory.getObjdump(getPath()); + } + return null; + } + + protected CygPath getCygPath() { + ICygwinToolsFactroy factory = getBinaryParser().getAdapter(ICygwinToolsFactroy.class); + if (factory != null) { + return factory.getCygPath(); + } + return null; + } + + /** + */ + protected NM getNM() { + ICygwinToolsFactroy factory = getBinaryParser().getAdapter(ICygwinToolsFactroy.class); + if (factory != null) { + return factory.getNM(getPath()); + } + return null; + } + + /** + * @throws IOException + * @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getContents() + */ + @Override + public InputStream getContents() throws IOException { + InputStream stream = null; + Objdump objdump = getObjdump(); + if (objdump != null) { + try { + byte[] contents = objdump.getOutput(); + stream = new ByteArrayInputStream(contents); + } catch (IOException e) { + // Nothing + } + } + if (stream == null) { + stream = super.getContents(); + } + return stream; + } + + @Override + protected void loadSymbols(PE64 pe) throws IOException { + symbolLoadingAddr2line = getAddr2line(false); + symbolLoadingCPPFilt = getCPPFilt(); + symbolLoadingCygPath = getCygPath(); + + ArrayList<Symbol> list = new ArrayList<>(); + super.loadSymbols(pe, list); + + // Add any global symbols + NM nm = getNM(); + if (nm != null) { + NM.AddressNamePair[] pairs = nm.getBSSSymbols(); + for (int i = 0; i < pairs.length; ++i) { + addSymbol(pairs[i], list, ISymbol.VARIABLE); + } + pairs = nm.getDataSymbols(); + for (int i = 0; i < pairs.length; ++i) { + addSymbol(pairs[i], list, ISymbol.VARIABLE); + } + } + // pairs = nm.getTextSymbols(); + // for (int i = 0; i < pairs.length; ++i) { + // addSymbol(pairs[i], list, ISymbol.FUNCTION); + // } + symbols = list.toArray(NO_SYMBOLS); + Arrays.sort(symbols); + list.clear(); + + if (symbolLoadingAddr2line != null) { + symbolLoadingAddr2line.dispose(); + symbolLoadingAddr2line = null; + } + if (symbolLoadingCPPFilt != null) { + symbolLoadingCPPFilt.dispose(); + symbolLoadingCPPFilt = null; + } + if (symbolLoadingCygPath != null) { + symbolLoadingCygPath.dispose(); + symbolLoadingCygPath = null; + } + } + + private void addSymbol(NM.AddressNamePair p, List<Symbol> list, int type) { + String name = p.name; + if (name != null && name.length() > 0 && CConventions.isValidIdentifier(name)) { + IAddress addr = new Addr32(p.address); + int size = 4; + if (symbolLoadingCPPFilt != null) { + try { + name = symbolLoadingCPPFilt.getFunction(name); + } catch (IOException e1) { + symbolLoadingCPPFilt.dispose(); + symbolLoadingCPPFilt = null; + } + } + if (symbolLoadingAddr2line != null) { + try { + String filename = symbolLoadingAddr2line.getFileName(addr); + // Addr2line returns the funny "??" when it can not find + // the file. + if (filename != null && filename.equals("??")) { //$NON-NLS-1$ + filename = null; + } + if (filename != null) { + try { + if (symbolLoadingCygPath != null) { + filename = symbolLoadingCygPath.getFileName(filename); + } + } catch (IOException e) { + symbolLoadingCygPath.dispose(); + symbolLoadingCygPath = null; + } + } + IPath file = filename != null ? new Path(filename) : Path.EMPTY; + int startLine = symbolLoadingAddr2line.getLineNumber(addr); + int endLine = symbolLoadingAddr2line.getLineNumber(addr.add(size - 1)); + list.add(new CygwinSymbol64(this, name, type, addr, size, file, startLine, endLine)); + } catch (IOException e) { + symbolLoadingAddr2line.dispose(); + symbolLoadingAddr2line = null; + } + } + } + } + + @Override + protected void addSymbols(Coff64.Symbol[] peSyms, byte[] table, List<Symbol> list) { + for (Coff64.Symbol peSym : peSyms) { + if (peSym.isFunction() || peSym.isPointer() || peSym.isArray()) { + String name = peSym.getName(table); + if (name == null || name.trim().length() == 0 || !Character.isJavaIdentifierStart(name.charAt(0))) { + continue; + } + int type = peSym.isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE; + IAddress addr = new Addr32(peSym.n_value); + int size = 4; + if (symbolLoadingCPPFilt != null) { + try { + name = symbolLoadingCPPFilt.getFunction(name); + } catch (IOException e1) { + symbolLoadingCPPFilt.dispose(); + symbolLoadingCPPFilt = null; + } + } + if (symbolLoadingAddr2line != null) { + try { + String filename = symbolLoadingAddr2line.getFileName(addr); + // Addr2line returns the funny "??" when it can not find + // the file. + if (filename != null && filename.equals("??")) { //$NON-NLS-1$ + filename = null; + } + + if (filename != null) { + try { + if (symbolLoadingCygPath != null) { + filename = symbolLoadingCygPath.getFileName(filename); + } + } catch (IOException e) { + symbolLoadingCygPath.dispose(); + symbolLoadingCygPath = null; + } + } + IPath file = filename != null ? new Path(filename) : Path.EMPTY; + int startLine = symbolLoadingAddr2line.getLineNumber(addr); + int endLine = symbolLoadingAddr2line.getLineNumber(addr.add(size - 1)); + list.add(new CygwinSymbol64(this, name, type, addr, size, file, startLine, endLine)); + } catch (IOException e) { + symbolLoadingAddr2line.dispose(); + symbolLoadingAddr2line = null; + // the symbol still needs to be added + list.add(new CygwinSymbol64(this, name, type, addr, size)); + } + } else { + list.add(new CygwinSymbol64(this, name, type, addr, size)); + } + + } + } + } + + @Override + @SuppressWarnings("unchecked") + public <T> T getAdapter(Class<T> adapter) { + if (adapter == Addr2line.class) { + return (T) getAddr2line(false); + } else if (adapter == CPPFilt.class) { + return (T) getCPPFilt(); + } else if (adapter == CygPath.class) { + return (T) getCygPath(); + } + return super.getAdapter(adapter); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared.java index 323a576b1c8..32d1748f311 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared.java @@ -18,6 +18,11 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryShared; import org.eclipse.core.runtime.IPath; +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link CygwinPEBinaryShared64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class CygwinPEBinaryShared extends CygwinPEBinaryObject implements IBinaryShared { protected CygwinPEBinaryShared(IBinaryParser parser, IPath path) { diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared64.java new file mode 100644 index 00000000000..2bbbeaac8df --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEBinaryShared64.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2004, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial CygwinPEBinaryShared class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.cdt.core.IBinaryParser.IBinaryShared; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class CygwinPEBinaryShared64 extends CygwinPEBinaryObject64 implements IBinaryShared { + + protected CygwinPEBinaryShared64(IBinaryParser parser, IPath path) { + super(parser, path, IBinaryFile.SHARED); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser.java index c0dd7d6defa..04085df9239 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser.java @@ -21,7 +21,10 @@ import org.eclipse.cdt.utils.ICygwinToolsFactroy; import org.eclipse.core.runtime.IPath; /** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link CygwinPEParser64}. + * This class is planned for removal in next major release. */ +@Deprecated public class CygwinPEParser extends PEParser { private DefaultCygwinToolFactory toolFactory; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser64.java new file mode 100644 index 00000000000..3cd81bd001b --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinPEParser64.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - Initial CygwinPEParser class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import java.io.IOException; + +import org.eclipse.cdt.utils.DefaultCygwinToolFactory; +import org.eclipse.cdt.utils.ICygwinToolsFactroy; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class CygwinPEParser64 extends PEParser64 { + + private DefaultCygwinToolFactory toolFactory; + + /** + * @see org.eclipse.cdt.core.IBinaryParser#getFormat() + */ + @Override + public String getFormat() { + return "Cygwin PE"; //$NON-NLS-1$ + } + + @Override + protected IBinaryArchive createBinaryArchive(IPath path) throws IOException { + return new CygwinPEBinaryArchive64(this, path); + } + + @Override + protected IBinaryExecutable createBinaryExecutable(IPath path) { + return new CygwinPEBinaryExecutable64(this, path, IBinaryFile.EXECUTABLE); + } + + @Override + protected IBinaryObject createBinaryCore(IPath path) { + return new CygwinPEBinaryObject64(this, path, IBinaryFile.CORE); + } + + @Override + protected IBinaryObject createBinaryObject(IPath path) { + return new CygwinPEBinaryObject64(this, path, IBinaryFile.OBJECT); + } + + @Override + protected IBinaryShared createBinaryShared(IPath path) { + return new CygwinPEBinaryShared64(this, path); + } + + protected DefaultCygwinToolFactory createToolFactory() { + return new DefaultCygwinToolFactory(this); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.PlatformObject#getAdapter(java.lang.Class) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(ICygwinToolsFactroy.class)) { + if (toolFactory == null) { + toolFactory = createToolFactory(); + } + return toolFactory; + } + return super.getAdapter(adapter); + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol.java index e88c2bade19..cbe080d2a9f 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol.java @@ -32,6 +32,11 @@ import org.eclipse.core.runtime.IPath; * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link CygwinSymbol64}. + * This class is planned for removal in next major release. + */ +@Deprecated class CygwinSymbol extends Symbol { /** diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol64.java new file mode 100644 index 00000000000..a279918ab2c --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/CygwinSymbol64.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2005, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial CygwinSymbol class + *******************************************************************************/ +/* + * Created on Jul 6, 2004 + * + * To change the template for this generated file go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +package org.eclipse.cdt.utils.coff.parser; + +import java.io.IOException; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.utils.Addr2line; +import org.eclipse.cdt.utils.Symbol; +import org.eclipse.core.runtime.IPath; + +/** + * @author DInglis + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +class CygwinSymbol64 extends Symbol { + + /** + * @param binary + * @param name + * @param type + * @param addr + * @param size + * @param sourceFile + * @param startLine + * @param endLine + */ + public CygwinSymbol64(CygwinPEBinaryObject64 binary, String name, int type, IAddress addr, long size, + IPath sourceFile, int startLine, int endLine) { + super(binary, name, type, addr, size, sourceFile, startLine, endLine); + } + + /** + * @param binary + * @param name + * @param type + * @param addr + * @param size + */ + public CygwinSymbol64(CygwinPEBinaryObject64 binary, String name, int type, IAddress addr, long size) { + super(binary, name, type, addr, size); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.Symbol#getLineNumber(long) + */ + @Override + public int getLineNumber(long offset) { + int line = -1; + Addr2line addr2line = ((CygwinPEBinaryObject64) binary).getAddr2line(true); + if (addr2line != null) { + try { + return addr2line.getLineNumber(getAddress().add(offset)); + } catch (IOException e) { + // ignore + } + } + return line; + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive.java index d5034aa9dfa..9040b0523ba 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive.java @@ -25,7 +25,10 @@ import org.eclipse.cdt.utils.BinaryFile; import org.eclipse.core.runtime.IPath; /** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link PEBinaryArchive64}. + * This class is planned for removal in next major release. */ +@Deprecated public class PEBinaryArchive extends BinaryFile implements IBinaryArchive { ArrayList<IBinaryObject> children; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive64.java new file mode 100644 index 00000000000..d4aa241357e --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryArchive64.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - Initial PEBinaryArchive class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.cdt.core.IBinaryParser.IBinaryArchive; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.cdt.core.IBinaryParser.IBinaryObject; +import org.eclipse.cdt.utils.AR; +import org.eclipse.cdt.utils.AR.ARHeader; +import org.eclipse.cdt.utils.BinaryFile; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class PEBinaryArchive64 extends BinaryFile implements IBinaryArchive { + + ArrayList<IBinaryObject> children; + + public PEBinaryArchive64(PEParser64 parser, IPath path) throws IOException { + super(parser, path, IBinaryFile.ARCHIVE); + new AR(path.toOSString()).dispose(); // check file type + children = new ArrayList<>(5); + } + + /** + * @see org.eclipse.cdt.core.IBinaryParser.IBinaryArchive#getObjects() + */ + @Override + public IBinaryObject[] getObjects() { + if (hasChanged()) { + children.clear(); + AR ar = null; + try { + ar = new AR(getPath().toOSString()); + AR.ARHeader[] headers = ar.getHeaders(); + addArchiveMembers(headers, children); + } catch (IOException e) { + //e.printStackTrace(); + } + if (ar != null) { + ar.dispose(); + } + children.trimToSize(); + } + return children.toArray(new IBinaryObject[0]); + } + + /** + * @param headers + * @param children2 + */ + protected void addArchiveMembers(ARHeader[] headers, ArrayList<IBinaryObject> children2) { + for (int i = 0; i < headers.length; i++) { + IBinaryObject bin = new PEBinaryObject64(getBinaryParser(), getPath(), headers[i]); + children.add(bin); + } + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable.java index 984d0f43f3c..6bded3149a2 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable.java @@ -18,6 +18,11 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable; import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.core.runtime.IPath; +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link PEBinaryExecutable64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class PEBinaryExecutable extends PEBinaryObject implements IBinaryExecutable { public PEBinaryExecutable(IBinaryParser parser, IPath path) { diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable64.java new file mode 100644 index 00000000000..a50090109b6 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryExecutable64.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2004, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial PEBinaryExecutable class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.IBinaryParser.IBinaryExecutable; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class PEBinaryExecutable64 extends PEBinaryObject64 implements IBinaryExecutable { + + public PEBinaryExecutable64(IBinaryParser parser, IPath path) { + super(parser, path, IBinaryFile.EXECUTABLE); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java index 3add07a14af..24446c71122 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject.java @@ -35,7 +35,10 @@ import org.eclipse.cdt.utils.coff.PE; import org.eclipse.core.runtime.IPath; /** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link PEBinaryObject64}. + * This class is planned for removal in next major release. */ +@Deprecated public class PEBinaryObject extends BinaryObjectAdapter { BinaryObjectInfo info; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject64.java new file mode 100644 index 00000000000..699a49e9f89 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryObject64.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - Initial PEBinaryObject class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.cdt.core.IAddressFactory; +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.cdt.core.IBinaryParser.ISymbol; +import org.eclipse.cdt.core.ISymbolReader; +import org.eclipse.cdt.utils.AR; +import org.eclipse.cdt.utils.Addr32; +import org.eclipse.cdt.utils.Addr32Factory; +import org.eclipse.cdt.utils.BinaryObjectAdapter; +import org.eclipse.cdt.utils.Symbol; +import org.eclipse.cdt.utils.coff.Coff64; +import org.eclipse.cdt.utils.coff.PE64; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class PEBinaryObject64 extends BinaryObjectAdapter { + + BinaryObjectInfo info; + IAddressFactory addressFactory; + ISymbol[] symbols; + AR.ARHeader header; + + public PEBinaryObject64(IBinaryParser parser, IPath path, AR.ARHeader header) { + super(parser, path, IBinaryFile.OBJECT); + } + + public PEBinaryObject64(IBinaryParser parser, IPath p, int type) { + super(parser, p, type); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getName() + */ + @Override + public String getName() { + if (header != null) { + return header.getObjectName(); + } + return super.getName(); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser.IBinaryFile#getContents() + */ + @Override + public InputStream getContents() throws IOException { + if (getPath() != null && header != null) { + return new ByteArrayInputStream(header.getObjectData()); + } + return super.getContents(); + } + + /** + * @see org.eclipse.cdt.core.IBinaryParser.IBinaryObject#getSymbols() + */ + @Override + public ISymbol[] getSymbols() { + if (hasChanged() || symbols == null) { + try { + loadAll(); + } catch (IOException e) { + symbols = NO_SYMBOLS; + } + } + return symbols; + } + + @Override + protected BinaryObjectInfo getBinaryObjectInfo() { + if (hasChanged() || info == null) { + try { + loadInfo(); + } catch (IOException e) { + info = new BinaryObjectInfo(); + } + } + return info; + } + + @Override + @SuppressWarnings("unchecked") + public <T> T getAdapter(Class<T> adapter) { + if (adapter.equals(PE64.class)) { + try { + if (header != null) { + return (T) new PE64(getPath().toOSString(), header.getObjectDataOffset()); + } + return (T) new PE64(getPath().toOSString()); + } catch (IOException e) { + } + } + if (adapter.equals(ISymbolReader.class)) { + PE64 pe = getAdapter(PE64.class); + if (pe != null) { + return (T) pe.getSymbolReader(); + } + } + return super.getAdapter(adapter); + } + + protected PE64 getPE() throws IOException { + if (header != null) { + return new PE64(getPath().toOSString(), header.getObjectDataOffset()); + } + return new PE64(getPath().toOSString()); + } + + protected void loadAll() throws IOException { + PE64 pe = null; + try { + pe = getPE(); + loadInfo(pe); + loadSymbols(pe); + } finally { + if (pe != null) { + pe.dispose(); + } + } + } + + protected void loadInfo() throws IOException { + PE64 pe = null; + try { + pe = getPE(); + loadInfo(pe); + } finally { + if (pe != null) { + pe.dispose(); + } + } + } + + protected void loadInfo(PE64 pe) throws IOException { + info = new BinaryObjectInfo(); + PE64.Attribute attribute = getPE().getAttribute(); + info.isLittleEndian = attribute.isLittleEndian(); + info.hasDebug = attribute.hasDebug(); + info.cpu = attribute.getCPU(); + } + + protected void loadSymbols(PE64 pe) throws IOException { + ArrayList<Symbol> list = new ArrayList<>(); + loadSymbols(pe, list); + symbols = list.toArray(NO_SYMBOLS); + Arrays.sort(symbols); + list.clear(); + } + + protected void loadSymbols(PE64 pe, List<Symbol> list) throws IOException { + Coff64.Symbol[] peSyms = pe.getSymbols(); + byte[] table = pe.getStringTable(); + addSymbols(peSyms, table, list); + } + + protected void addSymbols(Coff64.Symbol[] peSyms, byte[] table, List<Symbol> list) { + for (org.eclipse.cdt.utils.coff.Coff64.Symbol peSym : peSyms) { + if (peSym.isFunction() || peSym.isPointer() || peSym.isArray()) { + String name = peSym.getName(table); + if (name == null || name.trim().length() == 0 || !Character.isJavaIdentifierStart(name.charAt(0))) { + continue; + } + int type = peSym.isFunction() ? ISymbol.FUNCTION : ISymbol.VARIABLE; + list.add(new Symbol(this, name, type, new Addr32(peSym.n_value), peSym.getSize())); + } + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.BinaryObjectAdapter#getAddressFactory() + */ + @Override + public IAddressFactory getAddressFactory() { + if (addressFactory == null) { + addressFactory = new Addr32Factory(); + } + return addressFactory; + } +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared.java index c083e9c5186..ff0eb2d014d 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared.java @@ -18,6 +18,11 @@ import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; import org.eclipse.cdt.core.IBinaryParser.IBinaryShared; import org.eclipse.core.runtime.IPath; +/** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link PEBinaryShared64}. + * This class is planned for removal in next major release. + */ +@Deprecated public class PEBinaryShared extends PEBinaryObject implements IBinaryShared { public PEBinaryShared(IBinaryParser parser, IPath p) { diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared64.java new file mode 100644 index 00000000000..041b2b39426 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEBinaryShared64.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2004, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - initial PEBinaryShared class + *******************************************************************************/ +package org.eclipse.cdt.utils.coff.parser; + +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.core.IBinaryParser.IBinaryFile; +import org.eclipse.cdt.core.IBinaryParser.IBinaryShared; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class PEBinaryShared64 extends PEBinaryObject64 implements IBinaryShared { + + public PEBinaryShared64(IBinaryParser parser, IPath p) { + super(parser, p, IBinaryFile.SHARED); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java index ea691ae0c4d..697a3126e24 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser.java @@ -27,7 +27,10 @@ import org.eclipse.cdt.utils.coff.PEConstants; import org.eclipse.core.runtime.IPath; /** + * @deprecated. Deprecated as of CDT 6.9. Use 64 bit version {@link PEParser64}. + * This class is planned for removal in next major release. */ +@Deprecated public class PEParser extends AbstractCExtension implements IBinaryParser { /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser64.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser64.java new file mode 100644 index 00000000000..0071af23500 --- /dev/null +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/coff/parser/PEParser64.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2000, 2019 Space Codesign Systems and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Space Codesign Systems - Initial API and implementation + * QNX Software Systems - Initial PEParser class + *******************************************************************************/ + +package org.eclipse.cdt.utils.coff.parser; + +import java.io.EOFException; +import java.io.IOException; + +import org.eclipse.cdt.core.AbstractCExtension; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.IBinaryParser; +import org.eclipse.cdt.utils.AR; +import org.eclipse.cdt.utils.coff.PE64; +import org.eclipse.cdt.utils.coff.PE64.Attribute; +import org.eclipse.cdt.utils.coff.PEConstants; +import org.eclipse.core.runtime.IPath; + +/** + * @since 6.9 + */ +public class PEParser64 extends AbstractCExtension implements IBinaryParser { + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#getBinary(org.eclipse.core.runtime.IPath) + */ + @Override + public IBinaryFile getBinary(IPath path) throws IOException { + return getBinary(null, path); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#getBinary(byte[], org.eclipse.core.runtime.IPath) + */ + @Override + public IBinaryFile getBinary(byte[] hints, IPath path) throws IOException { + if (path == null) { + throw new IOException(CCorePlugin.getResourceString("Util.exception.nullPath")); //$NON-NLS-1$ + } + + IBinaryFile binary = null; + try { + PE64.Attribute attribute = null; + if (hints != null && hints.length > 0) { + try { + attribute = PE64.getAttribute(hints); + } catch (EOFException e) { + // continue to try + } + } + // the hints may have to small, keep on trying. + if (attribute == null) { + attribute = PE64.getAttribute(path.toOSString()); + } + + if (attribute != null) { + switch (attribute.getType()) { + case Attribute.PE_TYPE_EXE: + binary = createBinaryExecutable(path); + break; + + case Attribute.PE_TYPE_SHLIB: + binary = createBinaryShared(path); + break; + + case Attribute.PE_TYPE_OBJ: + binary = createBinaryObject(path); + break; + + case Attribute.PE_TYPE_CORE: + binary = createBinaryCore(path); + break; + } + } + } catch (IOException e) { + // Is it an Archive? + binary = createBinaryArchive(path); + } + + return binary; + } + + /** + * @see org.eclipse.cdt.core.IBinaryParser#getFormat() + */ + @Override + public String getFormat() { + return "PE"; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#isBinary(byte[], org.eclipse.core.runtime.IPath) + */ + @Override + public boolean isBinary(byte[] array, IPath path) { + boolean isBin = PE64.isExeHeader(array) || AR.isARHeader(array); + // It maybe an object file try the known machine types. + if (!isBin && array.length > 1) { + int f_magic = (((array[1] & 0xff) << 8) | (array[0] & 0xff)); + switch (f_magic) { + case PEConstants.IMAGE_FILE_MACHINE_ALPHA: + case PEConstants.IMAGE_FILE_MACHINE_ARM: + case PEConstants.IMAGE_FILE_MACHINE_ALPHA64: + case PEConstants.IMAGE_FILE_MACHINE_I386: + case PEConstants.IMAGE_FILE_MACHINE_IA64: + case PEConstants.IMAGE_FILE_MACHINE_M68K: + case PEConstants.IMAGE_FILE_MACHINE_MIPS16: + case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU: + case PEConstants.IMAGE_FILE_MACHINE_MIPSFPU16: + case PEConstants.IMAGE_FILE_MACHINE_POWERPC: + case PEConstants.IMAGE_FILE_MACHINE_R3000: + case PEConstants.IMAGE_FILE_MACHINE_R4000: + case PEConstants.IMAGE_FILE_MACHINE_R10000: + case PEConstants.IMAGE_FILE_MACHINE_SH3: + case PEConstants.IMAGE_FILE_MACHINE_SH4: + case PEConstants.IMAGE_FILE_MACHINE_THUMB: + case PEConstants.IMAGE_FILE_MACHINE_ARM2: + // Ok; + isBin = true; + break; + } + } + return isBin; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.IBinaryParser#getHintBufferSize() + */ + @Override + public int getHintBufferSize() { + return 512; + } + + protected IBinaryExecutable createBinaryExecutable(IPath path) { + return new PEBinaryExecutable64(this, path); + } + + protected IBinaryObject createBinaryCore(IPath path) { + return new PEBinaryObject64(this, path, IBinaryFile.CORE); + } + + protected IBinaryObject createBinaryObject(IPath path) { + return new PEBinaryObject64(this, path, IBinaryFile.OBJECT); + } + + protected IBinaryShared createBinaryShared(IPath path) { + return new PEBinaryShared64(this, path); + } + + protected IBinaryArchive createBinaryArchive(IPath path) throws IOException { + return new PEBinaryArchive64(this, path); + } + +} diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java index 4ec78e0367c..01a2f54ffe1 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 QNX Software Systems and others. + * Copyright (c) 2000, 2019 QNX Software Systems and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -27,7 +27,9 @@ import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.utils.coff.Coff.SectionHeader; +import org.eclipse.cdt.utils.coff.Coff64; import org.eclipse.cdt.utils.coff.PE; +import org.eclipse.cdt.utils.coff.PE64; import org.eclipse.cdt.utils.debug.DebugUnknownType; import org.eclipse.cdt.utils.debug.IDebugEntryRequestor; import org.eclipse.cdt.utils.debug.tools.DebugSym; @@ -200,6 +202,13 @@ public class Dwarf { init(exe); } + /** + * @since 6.9 + */ + public Dwarf(PE64 exe) throws IOException { + init(exe); + } + public void init(Elf exe) throws IOException { Elf.ELFhdr header = exe.getELFhdr(); isLE = header.e_ident[Elf.ELFhdr.EI_DATA] == Elf.ELFhdr.ELFDATA2LSB; @@ -320,6 +329,35 @@ public class Dwarf { } + /** + * @since 6.9 + */ + public void init(PE64 exe) throws IOException { + + isLE = true; + Coff64.SectionHeader[] sections = exe.getSectionHeaders(); + + for (int i = 0; i < sections.length; i++) { + String name = new String(sections[i].s_name).trim(); + if (name.startsWith("/")) //$NON-NLS-1$ + { + int stringTableOffset = Integer.parseInt(name.substring(1)); + name = exe.getStringTableEntry(stringTableOffset); + } + for (String element : Dwarf.DWARF_SCNNAMES) { + if (name.equals(element)) { + try { + dwarfSections.put(element, sections[i].mapSectionData()); + } catch (Exception e) { + e.printStackTrace(); + CCorePlugin.log(e); + } + } + } + } + + } + int read_4_bytes(ByteBuffer in) throws IOException { try { byte[] bytes = new byte[4]; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java index 624b27e59aa..16a390b96eb 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2016 Nokia and others. + * Copyright (c) 2007, 2019 Nokia and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -35,6 +35,7 @@ import org.eclipse.cdt.core.ICompileOptionsFinder; import org.eclipse.cdt.core.ISymbolReader; import org.eclipse.cdt.utils.coff.Coff.SectionHeader; import org.eclipse.cdt.utils.coff.PE; +import org.eclipse.cdt.utils.coff.PE64; import org.eclipse.cdt.utils.debug.IDebugEntryRequestor; import org.eclipse.cdt.utils.elf.Elf; import org.eclipse.cdt.utils.elf.Elf.Section; @@ -79,6 +80,13 @@ public class DwarfReader extends Dwarf implements ISymbolReader, ICompileOptions super(exe); } + /** + * @since 6.9 + */ + public DwarfReader(PE64 exe) throws IOException { + super(exe); + } + // Override parent. // @Override |