Mercurial > hg > truffle
diff agent/src/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFFileParser.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | c18cbe5936b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/posix/elf/ELFFileParser.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,1097 @@ +/* + * Copyright 2001-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.debugger.posix.elf; + +import java.io.*; +import java.util.*; +import sun.jvm.hotspot.utilities.memo.*; +import sun.jvm.hotspot.debugger.DataSource; +import sun.jvm.hotspot.debugger.RandomAccessFileDataSource; + +public class ELFFileParser { + private static ELFFileParser elfParser; + private static final String US_ASCII = "US-ASCII"; + + public static ELFFileParser getParser() { + if (elfParser == null) { + elfParser = new ELFFileParser(); + } + return elfParser; + } + + /** + * Parses the data in filename and returns the ELFFile representation. + */ + public ELFFile parse(String filename) throws ELFException { + try { + RandomAccessFile file = new RandomAccessFile(filename, "r"); + return parse(new RandomAccessFileDataSource(file)); + } catch (FileNotFoundException e) { + throw new ELFException(e); + } + } + + /** + * Parses the data source and returns the ELFFile representation. + */ + public ELFFile parse(DataSource source) throws ELFException { + return new ELFFileImpl(source); + } + + /** + * Implementation of the ELFFile interface. + */ + class ELFFileImpl implements ELFFile { + private DataSource file; + private ELFHeader header; + private byte ident[] = new byte[16]; + + ELFFileImpl(DataSource file) throws ELFException { + this.file = file; + int bytesRead = readBytes(ident); + if (bytesRead != ident.length) { + throw new ELFException("Error reading elf header (read " + + bytesRead + "bytes, expected to " + + "read " + ident.length + "bytes)."); + } + + // Check the magic number before we continue reading the file. + if (!Arrays.equals(getMagicNumber(), ELF_MAGIC_NUMBER)) { + throw new ELFException("Bad magic number for file."); + } + + header = new ELFHeaderImpl(); + } + + public ELFHeader getHeader() { return header; } + + public byte[] getMagicNumber() { + byte magicNumber[] = new byte[4]; + magicNumber[0] = ident[NDX_MAGIC_0]; + magicNumber[1] = ident[NDX_MAGIC_1]; + magicNumber[2] = ident[NDX_MAGIC_2]; + magicNumber[3] = ident[NDX_MAGIC_3]; + return magicNumber; + } + + public byte getObjectSize() { return ident[NDX_OBJECT_SIZE]; } + public byte getEncoding() { return ident[NDX_ENCODING]; } + public byte getVersion() { return ident[NDX_VERSION]; } + + + /** + * Implementation of the ELFHeader interface. + */ + class ELFHeaderImpl implements ELFHeader { + /** Marks the file as an object file and provide machine-independent + * data so the contents may be decoded and interpreted. */ + private byte ident[] = new byte[16]; // unsigned char + /** Identifies the object file type. */ + private short file_type; // Elf32_Half + /** The required architecture. */ + private short arch; // Elf32_Half + /** Version */ + private int version; // Elf32_Word + /** Virtual address to which the system first transfers control. + * If there is no entry point for the file the value is 0. */ + private int entry_point; // Elf32_Addr + /** Program header table offset in bytes. If there is no program + * header table the value is 0. */ + private int ph_offset; // Elf32_Off + /** Section header table offset in bytes. If there is no section + * header table the value is 0. */ + private int sh_offset; // Elf32_Off + /** Processor specific flags. */ + private int flags; // Elf32_Word + /** ELF header size in bytes. */ + private short eh_size; // Elf32_Half + /** Size of one entry in the file's program header table in bytes. + * All entries are the same size. */ + private short ph_entry_size; // Elf32_Half + /** Number of entries in the program header table, 0 if no + * entries. */ + private short num_ph; // Elf32_Half + /** Section header entry size in bytes. */ + private short sh_entry_size; // Elf32_Half + /** Number of entries in the section header table, 0 if no + * entries. */ + private short num_sh; // Elf32_Half + /** Index into the section header table associated with the section + * name string table. SH_UNDEF if there is no section name string + * table. */ + private short sh_string_ndx; // Elf32_Half + + /** MemoizedObject array of section headers associated with this + * ELF file. */ + private MemoizedObject[] sectionHeaders; + /** MemoizedObject array of program headers associated with this + * ELF file. */ + private MemoizedObject[] programHeaders; + + /** Used to cache symbol table lookup. */ + private ELFSectionHeader symbolTableSection; + /** Used to cache dynamic symbol table lookup. */ + private ELFSectionHeader dynamicSymbolTableSection; + /** Used to cache hash table lookup. */ + private ELFHashTable hashTable; + + /** + * Reads the ELF header and sets up the section and program headers + * in memoized arrays. + */ + ELFHeaderImpl() throws ELFException { + file_type = readShort(); + arch = readShort(); + version = readInt(); + entry_point = readInt(); + ph_offset = readInt(); + sh_offset = readInt(); + flags = readInt(); + eh_size = readShort(); + ph_entry_size = readShort(); + num_ph = readShort(); + sh_entry_size = readShort(); + num_sh = readShort(); + sh_string_ndx = readShort(); + + // Set up the section headers + sectionHeaders = new MemoizedObject[num_sh]; + for (int i = 0; i < num_sh; i++) { + final long sectionHeaderOffset = + (long)(sh_offset + (i * sh_entry_size)); + sectionHeaders[i] = new MemoizedObject() { + public Object computeValue() { + return new ELFSectionHeaderImpl(sectionHeaderOffset); + } + }; + } + +// // Set up the program headers +// programHeaders = new MemoizedObject[num_sh]; +// for (int i = 0; i < num_sh; i++) { +// final long programHeaderOffset = +// (long)(ph_offset + (i * ph_entry_size)); +// programHeaders[i] = new MemoizedObject() { +// public Object computeValue() { +// return new ProgramHeaderImpl(programHeaderOffset); +// } +// }; +// } + } + + public short getFileType() { return file_type; } + public short getArch() { return arch; } + public short getSectionHeaderSize() { return sh_entry_size; } + public short getNumberOfSectionHeaders() { return num_sh; } + +// public short getProgramHeaderSize() { return ph_entry_size; } +// public short getNumberOfProgramHeaders() { return num_ph; } + + + /** + * Returns the section header at the specified index. The section + * header at index 0 is defined as being a undefined section. */ + public ELFSectionHeader getSectionHeader(int index) { + return (ELFSectionHeader)sectionHeaders[index].getValue(); + } + + public ELFStringTable getSectionHeaderStringTable() { + return getSectionHeader(sh_string_ndx).getStringTable(); + } + + public ELFStringTable getStringTable() { + return findStringTableWithName(ELFSectionHeader.STRING_TABLE_NAME); + } + + public ELFStringTable getDynamicStringTable() { + return findStringTableWithName( + ELFSectionHeader.DYNAMIC_STRING_TABLE_NAME); + } + + private ELFStringTable findStringTableWithName(String tableName) { + // Loop through the section header and look for a section + // header with the name "tableName". We can ignore entry 0 + // since it is defined as being undefined. + ELFSectionHeader sh = null; + for (int i = 1; i < getNumberOfSectionHeaders(); i++) { + sh = getSectionHeader(i); + if (tableName.equals(sh.getName())) { + return sh.getStringTable(); + } + } + return null; + } + + /** + * The ELFHashTable does not currently work. This method will + * always return null. */ + public ELFHashTable getHashTable() { +// if (hashTable != null) { +// return hashTable; +// } +// +// ELFHashTable ht = null; +// for (int i = 1; i < getNumberOfSectionHeaders(); i++) { +// if ((ht = getSectionHeader(i).getHashTable()) != null) { +// hashTable = ht; +// return hashTable; +// } +// } + return null; + } + + public ELFSectionHeader getSymbolTableSection() { + if (symbolTableSection != null) { + return symbolTableSection; + } + + symbolTableSection = + getSymbolTableSection(ELFSectionHeader.TYPE_SYMTBL); + return symbolTableSection; + } + + public ELFSectionHeader getDynamicSymbolTableSection() { + if (dynamicSymbolTableSection != null) { + return dynamicSymbolTableSection; + } + + dynamicSymbolTableSection = + getSymbolTableSection(ELFSectionHeader.TYPE_DYNSYM); + return dynamicSymbolTableSection; + } + + private ELFSectionHeader getSymbolTableSection(int type) { + ELFSectionHeader sh = null; + for (int i = 1; i < getNumberOfSectionHeaders(); i++) { + sh = getSectionHeader(i); + if (sh.getType() == type) { + dynamicSymbolTableSection = sh; + return sh; + } + } + return null; + } + + public ELFSymbol getELFSymbol(String symbolName) { + if (symbolName == null) { + return null; + } + + // Check dynamic symbol table for symbol name. + ELFSymbol symbol = null; + int numSymbols = 0; + ELFSectionHeader sh = getDynamicSymbolTableSection(); + if (sh != null) { + numSymbols = sh.getNumberOfSymbols(); + for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { + if (symbolName.equals( + (symbol = sh.getELFSymbol(i)).getName())) { + return symbol; + } else if (symbolName.equals( + (symbol = sh.getELFSymbol( + numSymbols - 1 - i)).getName())) { + return symbol; + } + } + } + + // Check symbol table for symbol name. + sh = getSymbolTableSection(); + if (sh != null) { + numSymbols = sh.getNumberOfSymbols(); + for (int i = 0; i < Math.ceil(numSymbols / 2); i++) { + if (symbolName.equals( + (symbol = sh.getELFSymbol(i)).getName())) { + return symbol; + } else if (symbolName.equals( + (symbol = sh.getELFSymbol( + numSymbols - 1 - i)).getName())) { + return symbol; + } + } + } + return null; + } + + public ELFSymbol getELFSymbol(long address) { + // Check dynamic symbol table for address. + ELFSymbol symbol = null; + int numSymbols = 0; + long value = 0L; + + ELFSectionHeader sh = getDynamicSymbolTableSection(); + if (sh != null) { + numSymbols = sh.getNumberOfSymbols(); + for (int i = 0; i < numSymbols; i++) { + symbol = sh.getELFSymbol(i); + value = symbol.getValue(); + if (address >= value && address < value + symbol.getSize()) { + return symbol; + } + } + } + + // Check symbol table for symbol name. + sh = getSymbolTableSection(); + if (sh != null) { + numSymbols = sh.getNumberOfSymbols(); + for (int i = 0; i < numSymbols; i++) { + symbol = sh.getELFSymbol(i); + value = symbol.getValue(); + if (address >= value && address < value + symbol.getSize()) { + return symbol; + } + } + } + return null; + } + +// public ProgramHeader getProgramHeader(int index) { +// return (ProgramHeader)programHeaders[index].getValue(); +// } + } + + + /** + * Implementation of the ELFSectionHeader interface. + */ + class ELFSectionHeaderImpl implements ELFSectionHeader { + /** Index into the section header string table which gives the + * name of the section. */ + private int name_ndx; // Elf32_Word + /** Section content and semantics. */ + private int type; // Elf32_Word + /** Flags. */ + private int flags; // Elf32_Word + /** If the section will be in the memory image of a process this + * will be the address at which the first byte of section will be + * loaded. Otherwise, this value is 0. */ + private int address; // Elf32_Addr + /** Offset from beginning of file to first byte of the section. */ + private int section_offset; // Elf32_Off + /** Size in bytes of the section. TYPE_NOBITS is a special case. */ + private int size; // Elf32_Word + /** Section header table index link. */ + private int link; // Elf32_Word + /** Extra information determined by the section type. */ + private int info; // Elf32_Word + /** Address alignment constraints for the section. */ + private int address_alignment; // Elf32_Word + /** Size of a fixed-size entry, 0 if none. */ + private int entry_size; // Elf32_Word + + /** Memoized symbol table. */ + private MemoizedObject[] symbols; + /** Memoized string table. */ + private MemoizedObject stringTable; + /** Memoized hash table. */ + private MemoizedObject hashTable; + + /** + * Reads the section header information located at offset. + */ + ELFSectionHeaderImpl(long offset) throws ELFException { + seek(offset); + name_ndx = readInt(); + type = readInt(); + flags = readInt(); + address = readInt(); + section_offset = readInt(); + size = readInt(); + link = readInt(); + info = readInt(); + address_alignment = readInt(); + entry_size = readInt(); + + switch (type) { + case ELFSectionHeader.TYPE_NULL: + break; + case ELFSectionHeader.TYPE_PROGBITS: + break; + case ELFSectionHeader.TYPE_SYMTBL: + case ELFSectionHeader.TYPE_DYNSYM: + // Setup the symbol table. + int num_entries = size / entry_size; + symbols = new MemoizedObject[num_entries]; + for (int i = 0; i < num_entries; i++) { + final int symbolOffset = section_offset + + (i * entry_size); + symbols[i] = new MemoizedObject() { + public Object computeValue() { + return new ELFSymbolImpl(symbolOffset,type); + } + }; + } + break; + case ELFSectionHeader.TYPE_STRTBL: + // Setup the string table. + final int strTableOffset = section_offset; + final int strTableSize = size; + stringTable = new MemoizedObject() { + public Object computeValue() { + return new ELFStringTableImpl(strTableOffset, + strTableSize); + } + }; + break; + case ELFSectionHeader.TYPE_RELO_EXPLICIT: + break; + case ELFSectionHeader.TYPE_HASH: + final int hashTableOffset = section_offset; + final int hashTableSize = size; + hashTable = new MemoizedObject() { + public Object computeValue() { + return new ELFHashTableImpl(hashTableOffset, + hashTableSize); + } + }; + break; + case ELFSectionHeader.TYPE_DYNAMIC: + break; + case ELFSectionHeader.TYPE_NOTE: + break; + case ELFSectionHeader.TYPE_NOBITS: + break; + case ELFSectionHeader.TYPE_RELO: + break; + case ELFSectionHeader.TYPE_SHLIB: + break; + default: + break; + } + } + + public int getType() { + return type; + } + + public int getNumberOfSymbols() { + if (symbols != null) { + return symbols.length; + } + return 0; + } + + /** + * Returns the ELFSymbol at the specified index. Index 0 is + * reserved for the undefined ELF symbol. */ + public ELFSymbol getELFSymbol(int index) { + return (ELFSymbol)symbols[index].getValue(); + } + + public ELFStringTable getStringTable() { + if (stringTable != null) { + return (ELFStringTable)stringTable.getValue(); + } + return null; + } + + /** + * The ELFHashTable does not currently work. This method will + * always return null. */ + public ELFHashTable getHashTable() { + if (hashTable != null) { + return (ELFHashTable)hashTable.getValue(); + } + return null; + } + + public String getName() { + if (name_ndx == 0) { + return null; + } + + ELFStringTable tbl = getHeader().getSectionHeaderStringTable(); + return tbl.get(name_ndx); + } + + public int getLink() { + return link; + } + + public int getOffset() { + return section_offset; + } + } + + +// class ProgramHeaderImpl implements ProgramHeader { +// /** Defines the kind of segment this element describes. */ +// private int type; // Elf32_Word +// /** Offset from the beginning of the file. */ +// private int offset; // Elf32_Off +// /** Virtual address at which the first byte of the segment +// * resides in memory. */ +// private int virtual_address; // Elf32_Addr +// /** Reserved for the physical address of the segment on systems +// * where physical addressinf is relevant. */ +// private int physical_address; // Elf32_addr +// /** File image size of segment in bytes, may be 0. */ +// private int file_size; // Elf32_Word +// /** Memory image size of segment in bytes, may be 0. */ +// private int mem_size; // Elf32_Word +// /** Flags relevant to this segment. Values for flags are defined +// * in ELFSectionHeader. */ +// private int flags; // Elf32_Word +// private int alignment; // Elf32_Word +// +// private MemoizedObject[] symbols; +// +// ProgramHeaderImpl(long offset) throws ELFException { +// seek(offset); +// type = readInt(); +// this.offset = readInt(); +// virtual_address = readInt(); +// physical_address = readInt(); +// file_size = readInt(); +// mem_size = readInt(); +// flags = readInt(); +// alignment = readInt(); +// +// switch (type) { +// case ELFSectionHeader.TYPE_NULL: +// break; +// case ELFSectionHeader.TYPE_PROGBITS: +// break; +// case ELFSectionHeader.TYPE_SYMTBL: +// case ELFSectionHeader.TYPE_DYNSYM: +// break; +// case ELFSectionHeader.TYPE_STRTBL: +// // Setup the string table. +// final int strTableOffset = section_offset; +// final int strTableSize = size; +// stringTable = new MemoizedObject() { +// public Object computeValue() { +// return new ELFStringTableImpl(strTableOffset, +// strTableSize); +// } +// }; +// new ELFStringTableImpl(offset, file_size); +// break; +// case ELFSectionHeader.TYPE_RELO_EXPLICIT: +// break; +// case ELFSectionHeader.TYPE_HASH: +// break; +// case ELFSectionHeader.TYPE_DYNAMIC: +// break; +// case ELFSectionHeader.TYPE_NOTE: +// break; +// case ELFSectionHeader.TYPE_NOBITS: +// break; +// case ELFSectionHeader.TYPE_RELO: +// break; +// case ELFSectionHeader.TYPE_SHLIB: +// break; +// default: +// break; +// } +// } +// +// public int getType() { +// return type; +// } +// } + + + /** + * Implementation of the ELFSymbol interface. + */ + class ELFSymbolImpl implements ELFSymbol { + /** Index into the symbol string table that holds the character + * representation of the symbols. 0 means the symbol has no + * character name. */ + private int name_ndx; // Elf32_Word + /** Value of the associated symbol. This may be an address or + * an absolute value. */ + private int value; // Elf32_Addr + /** Size of the symbol. 0 if the symbol has no size or the size + * is unknown. */ + private int size; // Elf32_Word + /** Specifies the symbol type and beinding attributes. */ + private byte info; // unsigned char + /** Currently holds the value of 0 and has no meaning. */ + private byte other; // unsigned char + /** Index to the associated section header. This value will need + * to be read as an unsigned short if we compare it to + * ELFSectionHeader.NDX_LORESERVE and ELFSectionHeader.NDX_HIRESERVE. */ + private short section_header_ndx; // Elf32_Half + + private int section_type; + + /** Offset from the beginning of the file to this symbol. */ + private long offset; + + ELFSymbolImpl(long offset, int section_type) throws ELFException { + seek(offset); + this.offset = offset; + name_ndx = readInt(); + value = readInt(); + size = readInt(); + info = readByte(); + other = readByte(); + section_header_ndx = readShort(); + + this.section_type = section_type; + + switch (getType()) { + case TYPE_NOOBJECT: + break; + case TYPE_OBJECT: + break; + case TYPE_FUNCTION: + break; + case TYPE_SECTION: + break; + case TYPE_FILE: + break; + case TYPE_LOPROC: + break; + case TYPE_HIPROC: + break; + default: + break; + } + } + + public int getBinding() { return info >> 4; } + public int getType() { return info & 0x0F; } + public long getOffset() { return offset; } + + public String getName() { + // Check to make sure this symbol has a name. + if (name_ndx == 0) { + return null; + } + + // Retrieve the name of the symbol from the correct string + // table. + String symbol_name = null; + if (section_type == ELFSectionHeader.TYPE_SYMTBL) { + symbol_name = getHeader().getStringTable().get(name_ndx); + } else if (section_type == ELFSectionHeader.TYPE_DYNSYM) { + symbol_name = + getHeader().getDynamicStringTable().get(name_ndx); + } + return symbol_name; + } + + public long getValue() { + return value; + } + + public int getSize() { + return size; + } + } + + /** + * Implementation of the ELFStringTable interface. + */ + class ELFStringTableImpl implements ELFStringTable { + /** The string table data. */ + private byte data[]; + private int numStrings; + + /** + * Reads all the strings from [offset, length]. + */ + ELFStringTableImpl(long offset, int length) throws ELFException { + seek(offset); + data = new byte[length]; + int bytesRead = readBytes(data); + if (bytesRead != length) { + throw new ELFException("Error reading string table (read " + + bytesRead + "bytes, expected to " + + "read " + data.length + "bytes)."); + } + + // Count the strings. + numStrings = 0; + for (int ptr = 0; ptr < data.length; ptr++) { + if (data[ptr] == '\0') { + numStrings++; + } + } + } + + public String get(int index) { + int startPtr = index; + int endPtr = index; + while (data[endPtr] != '\0') { + endPtr++; + } + return new String(data, startPtr, endPtr - startPtr); + } + + public int getNumStrings() { + return numStrings; + } + } + + + /** Implementation of the ELFHashTable. */ + class ELFHashTableImpl implements ELFHashTable { + private int num_buckets; + private int num_chains; + + // These could probably be memoized. + private int buckets[]; + private int chains[]; + + ELFHashTableImpl(long offset, int length) throws ELFException { + seek(offset); + num_buckets = readInt(); + num_chains = readInt(); + + buckets = new int[num_buckets]; + chains = new int[num_chains]; + // Read the bucket data. + for (int i = 0; i < num_buckets; i++) { + buckets[i] = readInt(); + } + + // Read the chain data. + for (int i = 0; i < num_chains; i++) { + chains[i] = readInt(); + } + + // Make sure that the amount of bytes we were supposed to read + // was what we actually read. + int actual = num_buckets * 4 + num_chains * 4 + 8; + if (length != actual) { + throw new ELFException("Error reading string table (read " + + actual + "bytes, expected to " + + "read " + length + "bytes)."); + } + } + + /** + * This method doesn't work every time and is unreliable. Use + * ELFSection.getELFSymbol(String) to retrieve symbols by name. + * NOTE: since this method is currently broken it will always + * return null. */ + public ELFSymbol getSymbol(String symbolName) { +// if (symbolName == null) { +// return null; +// } +// +// long hash = 0; +// long g = 0; +// +// for (int i = 0; i < symbolName.length(); i++) { +// hash = (hash << 4) + symbolName.charAt(i); +// if ((g = hash & 0xf0000000) != 0) { +// hash ^= g >>> 24; +// } +// hash &= ~g; +// } +// +// ELFSymbol symbol = null; +// ELFSectionHeader dyn_sh = +// getHeader().getDynamicSymbolTableSection(); +// int index = (int)hash % num_buckets; +// while(index != 0) { +// symbol = dyn_sh.getELFSymbol(index); +// if (symbolName.equals(symbol.getName())) { +// break; +// } +// symbol = null; +// index = chains[index]; +// } +// return symbol; + return null; + } + } + + + public void close() throws ELFException { + try { + file.close(); + } catch (IOException e) { + throw new ELFException(e); + } + } + + void seek(long offset) throws ELFException { + try { + file.seek(offset); + } catch (IOException e) { + throw new ELFException(e); + } + } + + long getFilePointer() throws ELFException { + try { + return file.getFilePointer(); + } catch (IOException e) { + throw new ELFException(e); + } + } + + byte readByte() throws ELFException { + try { + return file.readByte(); + } catch (IOException e) { + throw new ELFException(e); + } + } + + int readBytes(byte[] b) throws ELFException { + try { + return file.read(b); + } catch (IOException e) { + throw new ELFException(e); + } + } + + short readShort() throws ELFException { + try { + short val; + switch (ident[NDX_ENCODING]) { + case DATA_LSB: + val = byteSwap(file.readShort()); + break; + case DATA_MSB: + val = file.readShort(); + break; + default: + throw new ELFException("Invalid encoding."); + } + return val; + } catch (IOException e) { + throw new ELFException(e); + } + } + + int readInt() throws ELFException { + try { + int val; + switch (ident[NDX_ENCODING]) { + case DATA_LSB: + val = byteSwap(file.readInt()); + break; + case DATA_MSB: + val = file.readInt(); + break; + default: + throw new ELFException("Invalid encoding."); + } + return val; + } catch (IOException e) { + throw new ELFException(e); + } + } + + long readLong() throws ELFException { + try { + long val; + switch (ident[NDX_ENCODING]) { + case DATA_LSB: + val = byteSwap(file.readLong()); + break; + case DATA_MSB: + val = file.readLong(); + break; + default: + throw new ELFException("Invalid encoding."); + } + return val; + } catch (IOException e) { + throw new ELFException(e); + } + } + + /** Signed byte utility functions used for converting from big-endian + * (MSB) to little-endian (LSB). */ + short byteSwap(short arg) { + return (short) ((arg << 8) | ((arg >>> 8) & 0xFF)); + } + + int byteSwap(int arg) { + return (((int) byteSwap((short) arg)) << 16) | + (((int) (byteSwap((short) (arg >>> 16)))) & 0xFFFF); + } + + long byteSwap(long arg) { + return ((((long) byteSwap((int) arg)) << 32) | + (((long) byteSwap((int) (arg >>> 32))) & 0xFFFFFFFF)); + } + + + /* Unsigned byte utility functions. Since java does not have unsigned + * data types we must convert values manually and we must return + * unsigned values in a larger data type. Therefore we can only have + * unsigned values for byte, short, and int. */ + short readUnsignedByte() throws ELFException { + try { + return unsignedByte(file.readByte()); + } catch (IOException e) { + throw new ELFException(e); + } + } + + int readUnsignedShort() throws ELFException { + try { + int val; + switch (ident[NDX_ENCODING]) { + case DATA_LSB: + val = unsignedByteSwap(file.readShort()); + break; + case DATA_MSB: + val = unsignedByte(file.readShort()); + break; + default: + throw new ELFException("Invalid encoding."); + } + return val; + } catch (IOException e) { + throw new ELFException(e); + } + } + + long readUnsignedInt() throws ELFException { + try { + long val; + switch (ident[NDX_ENCODING]) { + case DATA_LSB: + val = unsignedByteSwap(file.readInt()); + break; + case DATA_MSB: + val = unsignedByte(file.readInt()); + break; + default: + throw new ELFException("Invalid encoding."); + } + return val; + } catch (IOException e) { + throw new ELFException(e); + } + } + + /** Returns the unsigned value of the byte. */ + short unsignedByte(byte arg) { + return (short)(arg & 0x00FF); + } + + /** Returns a big-endian unsigned representation of the short. */ + int unsignedByte(short arg) { + int val; + if (arg >= 0) { + val = arg; + } else { + val = (int)(((int)unsignedByte((byte)(arg >>> 8)) << 8) | + ((byte)arg)); + } + return val; + } + + /** Returns a big-endian unsigned representation of the int. */ + long unsignedByte(int arg) { + long val; + if (arg >= 0) { + val = arg; + } else { + val = (long)(((long)unsignedByte((short)(arg >>> 16)) << 16) | + ((short)arg)); + } + return val; + } + + /** Unsigned byte utility functions used for converting from big-endian + * (MSB) to little-endian (LSB). */ + int unsignedByteSwap(short arg) { + return (int)(((int)unsignedByte((byte)arg)) << 8) | + ((int)unsignedByte((byte)(arg >>> 8))); + } + + long unsignedByteSwap(int arg) { + return (long)(((long)unsignedByteSwap((short)arg)) << 16) | + ((long)unsignedByteSwap((short)(arg >>> 16))); + } + } + + public static void main(String args[]) { + if (args.length != 1) { + System.out.println("Usage: java ELFFileParser <elf file>"); + System.exit(0); + } + + // Parse the file. + ELFFile elfFile = ELFFileParser.getParser().parse(args[0]); + + ELFHeader elfHeader = elfFile.getHeader(); + System.out.println("ELF File: " + args[0]); + + System.out.println("ELF object size: " + + ((elfFile.getObjectSize() == 0) ? "Invalid Object Size" : + (elfFile.getObjectSize() == 1) ? "32-bit" : "64-bit")); + System.out.println("ELF data encoding: " + + ((elfFile.getEncoding() == 0) ? "Invalid Data Encoding" : + (elfFile.getEncoding() == 1) ? "LSB" : "MSB")); + + int h = elfHeader.getNumberOfSectionHeaders(); + System.out.println("--> Start: reading " + h + " section headers."); + for (int i = 0; i < elfHeader.getNumberOfSectionHeaders(); i++) { + ELFSectionHeader sh = elfHeader.getSectionHeader(i); + String str = sh.getName(); + System.out.println("----> Start: Section (" + i + ") " + str); + + int num = 0; + if ((num = sh.getNumberOfSymbols()) != 0) { + System.out.println("------> Start: reading " + num + " symbols."); + for (int j = 0; j < num ; j++) { + ELFSymbol sym = sh.getELFSymbol(j); + //String name = sym.getName(); + //if (name != null) { + // System.out.println(name); + //} + } + System.out.println("<------ End: reading " + num + " symbols."); + } + ELFStringTable st; + if (sh.getType() == ELFSectionHeader.TYPE_STRTBL) { + System.out.println("------> Start: reading string table."); + st = sh.getStringTable(); + System.out.println("<------ End: reading string table."); + } + if (sh.getType() == ELFSectionHeader.TYPE_HASH) { + System.out.println("------> Start: reading hash table."); + sh.getHashTable(); + System.out.println("<------ End: reading hash table."); + } + System.out.println("<---- End: Section (" + i + ") " + str); + } + System.out.println("<-- End: reading " + h + " section headers."); +/* + h = elfHeader.getNumberOfProgramHeaders(); + System.out.println("--> Start: reading " + h + " program headers."); + for (int i = 0; i < elfHeader.getNumberOfProgramHeaders(); i++) { + elfHeader.getProgramHeader(i); + } + System.out.println("<-- End: reading " + h + " program headers."); +*/ + elfFile.close(); + } +}