/******************************************************************************* * Copyright (c) 2000, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ 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.Coff.FileHeader; import org.eclipse.cdt.utils.coff.Coff.OptionalHeader; import org.eclipse.cdt.utils.coff.Coff.SectionHeader; import org.eclipse.cdt.utils.coff.Coff.Symbol; import org.eclipse.cdt.utils.coff.Exe.ExeHeader; 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 signalture, 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> */ public class PE { 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; NTOptionalHeader ntHeader; 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() { StringBuffer buffer = new StringBuffer(); 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 NTOptionalHeader { 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 NTOptionalHeader(RandomAccessFile file) throws IOException { this(file, file.getFilePointer()); } public NTOptionalHeader(RandomAccessFile file, long offset) throws IOException { file.seek(offset); byte[] hdr = new byte[NTHDRSZ]; file.readFully(hdr); ReadMemoryAccess memory = new ReadMemoryAccess(hdr, true); ImageBase = memory.getInt(); SectionAlignment = memory.getInt(); FileAlignment = memory.getInt(); MajorOperatingSystemVersion = memory.getShort(); MinorOperatingSystemVersion = memory.getShort(); MajorImageVersion = memory.getShort(); MinorImageVersion = memory.getShort(); MajorSubsystemVersion = memory.getShort(); MinorSubsystemVersion = memory.getShort(); memory.getBytes(Reserved); SizeOfImage = memory.getInt(); SizeOfHeaders = memory.getInt(); CheckSum = memory.getInt(); Subsystem = memory.getShort(); DLLCharacteristics = memory.getShort(); SizeOfStackReserve = memory.getInt(); SizeOfStackCommit = memory.getInt(); SizeOfHeapReserve = memory.getInt(); SizeOfHeapCommit = memory.getInt(); LoaderFlags = memory.getInt(); NumberOfRvaAndSizes = memory.getInt(); 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() { StringBuffer buffer = new StringBuffer(); 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() { StringBuffer buffer = new StringBuffer(); 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() { StringBuffer buffer = new StringBuffer(); 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 PE (String filename) throws IOException { this(filename, 0); } public PE(String filename, long pos) throws IOException { this(filename, pos, true); } public PE (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 Coff.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 Coff.OptionalHeader(rfile, rfile.getFilePointer()); ntHeader = new NTOptionalHeader(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); Coff.FileHeader filehdr = new Coff.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 { PE pe = new PE(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 NTOptionalHeader getNTOptionalHeader() { return ntHeader; } public ImageDataDirectory[] getImageDataDirectories() throws IOException { if (dataDirectories == null) { RandomAccessFile accessFile = getRandomAccessFile(); long offset = 0; if (dosHeader != null) { offset = dosHeader.e_lfanew + 4/*NT SIG*/; } offset += FileHeader.FILHSZ + OptionalHeader.AOUTHDRSZ + NTOptionalHeader.NTHDRSZ; 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(); NTOptionalHeader ntHeader = getNTOptionalHeader(); 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 (ntHeader != null) newSym.n_value += ntHeader.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() { StringBuffer buffer = new StringBuffer(); if (exeHeader != null) { buffer.append(exeHeader); } if (dosHeader != null) { buffer.append(dosHeader); } buffer.append(fileHeader); if (optionalHeader != null) { buffer.append(optionalHeader); } if (ntHeader != null) { buffer.append(ntHeader); } 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 = Coff.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 NTOptionalHeader ntHeader = getNTOptionalHeader(); if (ntHeader==null || ntHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_DEBUG) return null; int debugDir = ntHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; if (debugDir == 0) return null; int debugFormats = ntHeader.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++) { PE.IMAGE_DEBUG_DIRECTORY dir = new PE.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 new String(); } /** * @since 5.1 */ public String getFilename() { return filename; } }