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 @@ + + + + + + + + + + + + + + 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; * +-------------------+ * */ + +/** + * @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. + *
+ *  +-------------------+
+ *  | DOS-stub          |
+ *  +-------------------+
+ *  | file-header       |
+ *  +-------------------+
+ *  | optional header   |
+ *  |- - - - - - - - - -|
+ *  |                   |
+ *  | data directories  |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section headers   |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section 1         |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section 2         |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | ...               |
+ *  |                   |
+ *  +-------------------+
+ *  |                   |
+ *  | section n         |
+ *  |                   |
+ *  +-------------------+
+ * 
+ * @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 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 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 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 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 getAdapter(Class 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 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 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 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 getAdapter(Class 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 list = new ArrayList<>(); + loadSymbols(pe, list); + symbols = list.toArray(NO_SYMBOLS); + Arrays.sort(symbols); + list.clear(); + } + + protected void loadSymbols(PE64 pe, List 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 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