/*
 * Copyright (c) 2001, 2004, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** 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.
/** Identifies the object file type. */
private short file_type; // Elf32_Half
The required architecture.
/** The required architecture. */
private short arch; // Elf32_Half
Version
/** 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.
/** 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.
/** 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.
/** 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.
/** Processor specific flags. */
private int flags; // Elf32_Word
ELF header size in bytes.
/** 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.
/** 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.
/** Number of entries in the program header table, 0 if no * entries. */
private short num_ph; // Elf32_Half
Section header entry size in bytes.
/** 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.
/** 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.
/** 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.
/** MemoizedObject array of section headers associated with this * ELF file. */
private MemoizedObject[] sectionHeaders;
MemoizedObject array of program headers associated with this ELF file.
/** MemoizedObject array of program headers associated with this * ELF file. */
private MemoizedObject[] programHeaders;
Used to cache symbol table lookup.
/** Used to cache symbol table lookup. */
private ELFSectionHeader symbolTableSection;
Used to cache dynamic symbol table lookup.
/** Used to cache dynamic symbol table lookup. */
private ELFSectionHeader dynamicSymbolTableSection;
Used to cache hash table lookup.
/** Used to cache hash table lookup. */
private ELFHashTable hashTable;
Reads the ELF header and sets up the section and program headers in memoized arrays.
/** * 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.
/** * 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.
/** * 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.
/** * Implementation of the ELFSectionHeader interface. */
class ELFSectionHeaderImpl implements ELFSectionHeader {
Index into the section header string table which gives the name of the section.
/** Index into the section header string table which gives the * name of the section. */
private int name_ndx; // Elf32_Word
Section content and semantics.
/** Section content and semantics. */
private int type; // Elf32_Word
Flags.
/** 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.
/** 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.
/** 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.
/** Size in bytes of the section. TYPE_NOBITS is a special case. */
private int size; // Elf32_Word
Section header table index link.
/** Section header table index link. */
private int link; // Elf32_Word
Extra information determined by the section type.
/** Extra information determined by the section type. */
private int info; // Elf32_Word
Address alignment constraints for the section.
/** Address alignment constraints for the section. */
private int address_alignment; // Elf32_Word
Size of a fixed-size entry, 0 if none.
/** Size of a fixed-size entry, 0 if none. */
private int entry_size; // Elf32_Word
Memoized symbol table.
/** Memoized symbol table. */
private MemoizedObject[] symbols;
Memoized string table.
/** Memoized string table. */
private MemoizedObject stringTable;
Memoized hash table.
/** Memoized hash table. */
private MemoizedObject hashTable;
Reads the section header information located at offset.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** 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.
/** 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.
/** 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.
/** Specifies the symbol type and beinding attributes. */
private byte info; // unsigned char
Currently holds the value of 0 and has no meaning.
/** 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.
/** 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.
/** 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.
/** * Implementation of the ELFStringTable interface. */
class ELFStringTableImpl implements ELFStringTable {
The string table data.
/** The string table data. */
private byte data[]; private int numStrings;
Reads all the strings from [offset, length].
/** * 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.
/** 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.
/** * 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).
/** 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.
/** Returns the unsigned value of the byte. */
short unsignedByte(byte arg) { return (short)(arg & 0x00FF); }
Returns a big-endian unsigned representation of the short.
/** 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.
/** 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).
/** 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(); } }