/* * 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. */ 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 "); 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(); } }