blob: 45fbaabd1e8a82499427d04544c1ff97128c4409 [file] [log] [blame]
package org.eclipse.cdt.utils.elf;
/*
* (c) Copyright QNX Software Systems Ltd. 2002.
* All Rights Reserved.
*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.cdt.utils.Addr2line;
import org.eclipse.cdt.utils.CPPFilt;
// test checkin
public class Elf {
protected ERandomAccessFile efile;
protected ELFhdr ehdr;
protected Section[] sections;
protected Addr2line addr2line;
protected boolean cppFiltEnabled = true;
protected CPPFilt cppFilt;
protected String file;
protected byte[] section_strtab;
private int syms = 0;
private Symbol[] symbols;
private Symbol[] symtab_symbols;
private Section symtab_sym;
private Symbol[] dynsym_symbols;
private Section dynsym_sym;
protected String EMPTY_STRING = "";
public class ELFhdr {
/* e_ident offsets */
public final static int EI_MAG0 = 0;
public final static int EI_MAG1 = 1;
public final static int EI_MAG2 = 2;
public final static int EI_MAG3 = 3;
public final static int EI_CLASS = 4;
public final static int EI_DATA = 5;
public final static int EI_VERSION = 6;
public final static int EI_PAD = 7;
public final static int EI_NDENT = 16;
/* e_ident[EI_CLASS] */
public final static int ELFCLASSNONE = 0;
public final static int ELCLASS32 = 1;
public final static int ELFCLASS64 = 2;
/* e_ident[EI_DATA] */
public final static int ELFDATANONE = 0;
public final static int ELFDATA2LSB = 1;
public final static int ELFDATA2MSB = 2;
/* values of e_type */
public final static int ET_NONE = 0;
public final static int ET_REL = 1;
public final static int ET_EXEC = 2;
public final static int ET_DYN = 3;
public final static int ET_CORE = 4;
public final static int ET_LOPROC = 0xff00;
public final static int ET_HIPROC = 0xffff;
/* values of e_machine */
public final static int EM_NONE = 0;
public final static int EM_M32 = 1;
public final static int EM_SPARC = 2;
public final static int EM_386 = 3;
public final static int EM_68K = 4;
public final static int EM_88K = 5;
public final static int EM_486 = 6;
public final static int EM_860 = 7;
public final static int EM_MIPS = 8;
public final static int EM_MIPS_RS3_LE = 10;
public final static int EM_RS6000 = 11;
public final static int EM_PA_RSIC = 15;
public final static int EM_nCUBE = 16;
public final static int EM_VPP500 = 17;
public final static int EM_SPARC32PLUS = 18;
public final static int EM_PPC = 20;
public final static int EM_ARM = 40;
public final static int EM_SH = 42;
public byte e_ident[] = new byte[EI_NDENT];
public short e_type; /* file type (Elf32_Half) */
public short e_machine; /* machine type (Elf32_Half) */
public long e_version; /* version number (Elf32_Word) */
public long e_entry; /* entry point (Elf32_Addr)*/
public long e_phoff; /* Program hdr offset (Elf32_Off)*/
public long e_shoff; /* Section hdr offset (Elf32_Off)*/
public long e_flags; /* Processor flags (Elf32_Word)*/
public short e_ehsize; /* sizeof ehdr (Elf32_Half)*/
public short e_phentsize; /* Program header entry size (Elf32_Half)*/
public short e_phnum; /* Number of program headers (Elf32_Half)*/
public short e_shentsize; /* Section header entry size (Elf32_Half)*/
public short e_shnum; /* Number of section headers (Elf32_Half)*/
public short e_shstrndx; /* String table index (Elf32_Half)*/
protected ELFhdr() throws IOException {
efile.seek(0);
efile.readFully(e_ident);
if ( e_ident[ELFhdr.EI_MAG0] != 0x7f || e_ident[ELFhdr.EI_MAG1] != 'E' ||
e_ident[ELFhdr.EI_MAG2] != 'L' || e_ident[ELFhdr.EI_MAG3] != 'F' )
throw new IOException("Not ELF format");
efile.setEndian(e_ident[ELFhdr.EI_DATA] == ELFhdr.ELFDATA2LSB);
e_type = efile.readShortE();
e_machine = efile.readShortE();
e_version = efile.readIntE();
e_entry = efile.readIntE();
e_phoff = efile.readIntE();
e_shoff = efile.readIntE();
e_flags = efile.readIntE();
e_ehsize = efile.readShortE();
e_phentsize = efile.readShortE();
e_phnum = efile.readShortE();
e_shentsize = efile.readShortE();
e_shnum = efile.readShortE();
e_shstrndx = efile.readShortE();
}
}
public class Section {
/* sh_type */
public final static int SHT_NULL = 0;
public final static int SHT_PROGBITS = 1;
public final static int SHT_SYMTAB = 2;
public final static int SHT_STRTAB = 3;
public final static int SHT_RELA = 4;
public final static int SHT_HASH = 5;
public final static int SHT_DYNAMIC = 6;
public final static int SHT_NOTE = 7;
public final static int SHT_NOBITS = 8;
public final static int SHT_REL = 9;
public final static int SHT_SHLIB = 10;
public final static int SHT_DYNSYM = 11;
public final static int SHT_LOPROC = 0x70000000;
/* sh_flags */
public final static int SHF_WRITE = 1;
public final static int SHF_ALLOC = 2;
public final static int SHF_EXECINTR = 4;
public long sh_name;
public long sh_type;
public long sh_flags;
public long sh_addr;
public long sh_offset;
public long sh_size;
public long sh_link;
public long sh_info;
public long sh_addralign;
public long sh_entsize;
public byte[] loadSectionData() throws IOException {
byte[] data = new byte[(int)sh_size];
efile.seek( sh_offset );
efile.read( data );
return data;
}
public String toString() {
try {
if ( section_strtab == null ) {
if ( ehdr.e_shstrndx > sections.length || ehdr.e_shstrndx < 0)
return EMPTY_STRING;
int size = (int)sections[ehdr.e_shstrndx].sh_size;
if ( size <= 0 || size > efile.length() )
return EMPTY_STRING;
section_strtab = new byte[size];
efile.seek(sections[ehdr.e_shstrndx].sh_offset);
efile.read(section_strtab);
}
int str_size = 0;
if ( sh_name > section_strtab.length) {
return EMPTY_STRING;
}
while( section_strtab[(int)sh_name + str_size] != 0)
str_size++;
return new String(section_strtab, (int)sh_name, str_size);
} catch (IOException e) {
return EMPTY_STRING;
}
}
}
protected String string_from_elf_section(Elf.Section section, int index) throws IOException {
StringBuffer str = new StringBuffer();
byte tmp;
if ( index > section.sh_size ) {
return EMPTY_STRING;
}
efile.seek(section.sh_offset + index);
while( true ) {
tmp = efile.readByte();
if ( tmp == 0 )
break;
str.append((char)tmp);
}
return str.toString();
}
public class Symbol implements Comparable {
/* Symbol bindings */
public final static int STB_LOCAL = 0;
public final static int STB_GLOBAL = 1;
public final static int STB_WEAK = 2;
/* Symbol type */
public final static int STT_NOTYPE = 0;
public final static int STT_OBJECT = 1;
public final static int STT_FUNC = 2;
public final static int STT_SECTION = 3;
public final static int STT_FILE = 4;
/* Special Indexes */
public final static int SHN_UNDEF = 0;
public final static int SHN_LORESERVE = 0xffffff00;
public final static int SHN_LOPROC = 0xffffff00;
public final static int SHN_HIPROC = 0xffffff1f;
public final static int SHN_LOOS = 0xffffff20;
public final static int SHN_HIOS = 0xffffff3f;
public final static int SHN_ABS = 0xfffffff1;
public final static int SHN_COMMON = 0xfffffff2;
public final static int SHN_XINDEX = 0xffffffff;
public final static int SHN_HIRESERVE = 0xffffffff;
public long st_name;
public long st_value;
public long st_size;
public short st_info;
public short st_other;
public short st_shndx;
private String name = null;
private String line = null;
private String func = null;
private Section sym_section;
private String cppFilt(String in) {
if (cppFiltEnabled) {
try {
if (in.indexOf("__") != -1 || in.indexOf("_._") != -1) {
if (cppFilt == null) {
cppFilt = new CPPFilt();
}
return cppFilt.getFunction(in);
}
} catch (IOException e) {
return in;
}
}
return in;
}
public Symbol( Section section ) {
sym_section = section;
}
public int st_type() {
return st_info & 0xf;
}
public int st_bind() {
return (st_info >> 4) & 0xf;
}
public int compareTo(Object obj) {
long thisVal = 0;
long anotherVal = 0;
if ( obj instanceof Symbol ) {
Symbol sym = (Symbol)obj;
thisVal = this.st_value;
anotherVal = sym.st_value;
} else if ( obj instanceof Long ) {
Long val = (Long)obj;
anotherVal = val.longValue();
thisVal = (long)this.st_value;
}
return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
public String toString() {
if ( name == null ) {
try {
Section sections[] = getSections();
Section symstr = sections[(int)sym_section.sh_link];
name = cppFilt(string_from_elf_section(symstr, (int)st_name ));
} catch (IOException e ) {
return EMPTY_STRING;
}
}
return name;
}
/**
* Returns line information in the form of filename:line
* and if the information is not available may return null
* _or_ may return ??:??
*/
public String lineInfo() throws IOException {
if ( line == null ) {
if ( addr2line == null )
addr2line = new Addr2line(file);
long value = st_value;
// We try to get the nearest match
// since the symbol may not exactly align with debug info.
// In C line number 0 is invalid, line starts at 1 for file, we use
// this for validation.
for (int i = 0; i <= 20; i += 4, value += i) {
line = addr2line.getLine(value);
if (line != null) {
int colon = line.lastIndexOf(':');
String number = line.substring(colon + 1);
if (!number.startsWith("0")) {
break; // bail out
}
}
}
func = addr2line.getFunction(value);
}
return line;
}
public String lineInfo(long vma) throws IOException {
if ( addr2line == null )
addr2line = new Addr2line(file);
return addr2line.getLine(vma);
}
/**
* If the function is available from the symbol information,
* this will return the function name. May return null if
* the function can't be determined.
*/
public String getFunction() throws IOException {
if ( func == null ) {
lineInfo();
}
return func;
}
/**
* If the filename is available from the symbol information,
* this will return the base filename information. May
* return null if the filename can't be determined.
*/
public String getFilename() throws IOException {
if ( line == null ) {
lineInfo();
}
int index1, index2;
if(line == null || (index1 = line.lastIndexOf(':')) == -1) {
return null;
}
// we do this because addr2line on win produces
// <cygdrive/pathtoexc/C:/pathtofile:##>
index2 = line.indexOf(':');
if ( index1 == index2 ) {
index2 = 0;
} else {
index2--;
}
return line.substring(index2, index1);
}
/**
* Returns the line number of the function which is closest
* associated with the address if it is available.
* from the symbol information. If it is not available,
* then -1 is returned.
*/
public int getFuncLineNumber() throws IOException {
if ( line == null ) {
lineInfo();
}
int index;
if(line == null || (index = line.lastIndexOf(':')) == -1) {
return -1;
}
try {
int lineno = Integer.parseInt(line.substring(index + 1));
return (lineno == 0) ? -1 : lineno;
} catch(Exception e) {
return -1;
}
}
/**
* Returns the line number of the file if it is available
* from the symbol information. If it is not available,
* then -1 is returned.
*/
public int getLineNumber(long vma) throws IOException {
int index;
String ligne = lineInfo(vma);
if(ligne == null || (index = ligne.lastIndexOf(':')) == -1) {
return -1;
}
try {
int lineno = Integer.parseInt(ligne.substring(index + 1));
return (lineno == 0) ? -1 : lineno;
} catch(Exception e) {
return -1;
}
}
}
/**
* We have to implement a separate compararator since when we do the
* binary search down below we are using a Long and a Symbol object
* and the Long doesn't know how to compare against a Symbol so if
* we compare Symbol vs Long it is ok, but not if we do Long vs Symbol.
*/
class SymbolComparator implements Comparator {
long val1, val2;
public int compare(Object o1, Object o2) {
if(o1 instanceof Long) {
val1 = ((Long)o1).longValue();
} else if(o1 instanceof Symbol) {
val1 = ((Symbol)o1).st_value;
} else {
return -1;
}
if(o2 instanceof Long) {
val2 = ((Long)o2).longValue();
} else if(o2 instanceof Symbol) {
val2 = ((Symbol)o2).st_value;
} else {
return -1;
}
return (val1 == val2) ? 0
: ((val1 < val2) ? -1 : 1);
}
}
public class PHdr {
public final static int PT_NULL = 0;
public final static int PT_LOAD = 1;
public final static int PT_DYNAMIC = 2;
public final static int PT_INTERP = 3;
public final static int PT_NOTE = 4;
public final static int PT_SHLIB = 5;
public final static int PT_PHDR = 6;
public final static int PF_X = 1;
public final static int PF_W = 2;
public final static int PF_R = 4;
public long p_type;
public long p_offset;
public long p_vaddr;
public long p_paddr;
public long p_filesz;
public long p_memsz;
public long p_flags;
public long p_align;
}
public PHdr[] getPHdrs() throws IOException {
if ( ehdr.e_phnum == 0 ) {
return new PHdr[0];
}
efile.seek(ehdr.e_phoff);
PHdr phdrs[] = new PHdr[ehdr.e_phnum];
for( int i = 0; i < ehdr.e_phnum; i++ ) {
phdrs[i] = new PHdr();
phdrs[i].p_type = efile.readIntE();
phdrs[i].p_offset = efile.readIntE();
phdrs[i].p_vaddr = efile.readIntE();
phdrs[i].p_paddr = efile.readIntE();
phdrs[i].p_filesz = efile.readIntE();
phdrs[i].p_memsz = efile.readIntE();
phdrs[i].p_flags = efile.readIntE();
phdrs[i].p_align = efile.readIntE();
}
return phdrs;
}
public class Dynamic {
public final static int DYN_ENT_SIZE = 8;
public final static int DT_NULL = 0;
public final static int DT_NEEDED = 1;
public final static int DT_PLTRELSZ = 2;
public final static int DT_PLTGOT = 3;
public final static int DT_HASH = 4;
public final static int DT_STRTAB = 5;
public final static int DT_SYMTAB = 6;
public final static int DT_RELA = 7;
public final static int DT_RELASZ = 8;
public final static int DT_RELAENT = 9;
public final static int DT_STRSZ = 10;
public final static int DT_SYMENT = 11;
public final static int DT_INIT = 12;
public final static int DT_FINI = 13;
public final static int DT_SONAME = 14;
public final static int DT_RPATH = 15;
public long d_tag;
public long d_val;
private Section section;
private String name;
protected Dynamic(Section section, long tag, long val) {
this.section = section;
d_tag = tag;
d_val = val;
}
public String toString() {
if ( name == null ) {
switch ( (int)d_tag ) {
case DT_NEEDED:
case DT_SONAME:
case DT_RPATH:
try {
Section symstr = sections[(int)section.sh_link];
name = string_from_elf_section(symstr, (int)d_val);
} catch (IOException e) {
name = EMPTY_STRING;
}
break;
default:
name = EMPTY_STRING;
}
}
return name;
}
}
public Dynamic[] getDynamicSections(Section section) throws IOException {
if ( section.sh_type != Section.SHT_DYNAMIC ) {
return new Dynamic[0];
}
ArrayList dynList = new ArrayList();
efile.seek(section.sh_offset);
int off = 0;
// We must assume the section is a table ignoring the sh_entsize as it is not
// set for MIPS.
while( off < section.sh_size ) {
Dynamic dynEnt = new Dynamic(section, efile.readIntE(), efile.readIntE());
if ( dynEnt.d_tag == Dynamic.DT_NULL )
break;
dynList.add(dynEnt);
off+= Dynamic.DYN_ENT_SIZE;
}
return (Dynamic[])dynList.toArray(new Dynamic[0]);
}
private void commonSetup( String file, long offset, boolean filton )
throws IOException
{
this.cppFiltEnabled = filton;
try {
efile = new ERandomAccessFile(file, "r");
efile.setFileOffset( offset );
ehdr = new ELFhdr();
this.file = file;
} finally {
if ( ehdr == null ) {
dispose();
}
}
}
public Elf (String file, long offset) throws IOException {
commonSetup( file, offset, true );
}
public Elf (String file) throws IOException {
commonSetup( file, 0, true );
}
public Elf (String file, long offset, boolean filton) throws IOException {
commonSetup( file, offset, filton );
}
public Elf (String file, boolean filton) throws IOException {
commonSetup( file, 0, filton );
}
public boolean cppFilterEnabled() {
return cppFiltEnabled;
}
public void setCppFilter( boolean enabled ) {
cppFiltEnabled = enabled;
}
public ELFhdr getELFhdr() throws IOException {
return ehdr;
}
public class Attribute {
public static final int ELF_TYPE_EXE = 1;
public static final int ELF_TYPE_SHLIB = 2;
public static final int ELF_TYPE_OBJ = 3;
public static final int ELF_TYPE_CORE = 4;
public static final int DEBUG_TYPE_NONE = 0;
public static final int DEBUG_TYPE_STABS = 1;
public static final int DEBUG_TYPE_DWARF = 2;
String cpu;
int type;
int debugType;
boolean bDebug;
boolean isle;
public String getCPU() {
return cpu;
}
public int getType() {
return type;
}
public boolean hasDebug() {
return debugType != DEBUG_TYPE_NONE;
}
public int getDebugType() {
return debugType;
}
public boolean isLittleEndian() {
return isle;
}
}
public Attribute getAttributes() throws IOException {
Attribute attrib = new Attribute();
switch( ehdr.e_type ) {
case Elf.ELFhdr.ET_CORE:
attrib.type = Attribute.ELF_TYPE_CORE;
break;
case Elf.ELFhdr.ET_EXEC:
attrib.type = Attribute.ELF_TYPE_EXE;
break;
case Elf.ELFhdr.ET_REL:
attrib.type = Attribute.ELF_TYPE_OBJ;
break;
case Elf.ELFhdr.ET_DYN:
attrib.type = Attribute.ELF_TYPE_SHLIB;
break;
}
switch (ehdr.e_machine) {
case Elf.ELFhdr.EM_386 :
case Elf.ELFhdr.EM_486 :
attrib.cpu = new String("x86");
break;
case Elf.ELFhdr.EM_PPC :
attrib.cpu = new String("ppc");
break;
case Elf.ELFhdr.EM_SH :
attrib.cpu = new String("sh");
break;
case Elf.ELFhdr.EM_ARM :
attrib.cpu = new String("arm");
break;
case Elf.ELFhdr.EM_MIPS_RS3_LE :
case Elf.ELFhdr.EM_MIPS :
case Elf.ELFhdr.EM_RS6000 :
attrib.cpu = "mips";
break;
case Elf.ELFhdr.EM_SPARC32PLUS:
case Elf.ELFhdr.EM_SPARC:
attrib.cpu = "sparc";
break;
case Elf.ELFhdr.EM_68K:
attrib.cpu = "m68k";
break;
case Elf.ELFhdr.EM_NONE:
default:
attrib.cpu = "none";
}
switch (ehdr.e_ident[Elf.ELFhdr.EI_DATA]) {
case Elf.ELFhdr.ELFDATA2LSB :
attrib.isle = true;
break;
case Elf.ELFhdr.ELFDATA2MSB :
attrib.isle = false;
break;
}
// getSections
// find .debug using toString
Section [] sec = getSections();
for (int i = 0; i < sec.length; i++) {
String s = sec[i].toString();
if (s.equals(".debug_info")) {
attrib.debugType = Attribute.DEBUG_TYPE_DWARF;
break;
} else if (s.equals(".stab")) {
attrib.debugType = Attribute.DEBUG_TYPE_STABS;
break;
}
}
return attrib;
}
public static Attribute getAttributes(String file) throws IOException {
Elf elf = new Elf(file);
Attribute attrib = elf.getAttributes();
elf.dispose();
return attrib;
}
public static boolean isElfHeader(byte[] e_ident) {
if (e_ident.length < 4 || e_ident[ELFhdr.EI_MAG0] != 0x7f || e_ident[ELFhdr.EI_MAG1] != 'E' ||
e_ident[ELFhdr.EI_MAG2] != 'L' || e_ident[ELFhdr.EI_MAG3] != 'F')
return false;
return true;
}
public void dispose() {
if (addr2line != null) {
addr2line.dispose();
}
if (cppFilt != null) {
cppFilt.dispose();
}
try {
if (efile != null) {
efile.close();
efile = null;
}
} catch (IOException e) {
}
}
/**
* Make sure we do not leak the fds.
*/
protected void finalize() throws Throwable {
try {
dispose();
} finally {
super.finalize();
}
}
public Section getSectionByName(String name) throws IOException {
if ( sections == null )
getSections();
for( int i = 0; i < sections.length; i++) {
if ( sections[i].toString().equals(name)) {
return sections[i];
}
}
return null;
}
public Section[] getSections(int type) throws IOException {
if ( sections == null )
getSections();
ArrayList slist = new ArrayList();
for( int i = 0; i < sections.length; i++ ) {
if ( sections[i].sh_type == type)
slist.add(sections[i]);
}
return (Section[])slist.toArray(new Section[0]);
}
public Section[] getSections() throws IOException {
if ( sections == null ) {
if ( ehdr.e_shoff == 0 ) {
sections = new Section[0];
return sections;
}
efile.seek(ehdr.e_shoff);
sections = new Section[ehdr.e_shnum];
for ( int i = 0; i < ehdr.e_shnum; i++ ) {
sections[i] = new Section();
sections[i].sh_name = efile.readIntE();
sections[i].sh_type = efile.readIntE();
sections[i].sh_flags = efile.readIntE();
sections[i].sh_addr = efile.readIntE();
sections[i].sh_offset = efile.readIntE();
sections[i].sh_size = efile.readIntE();
sections[i].sh_link = efile.readIntE();
sections[i].sh_info = efile.readIntE();
sections[i].sh_addralign = efile.readIntE();
sections[i].sh_entsize = efile.readIntE();
if ( sections[i].sh_type == Section.SHT_SYMTAB )
syms = i;
if ( syms == 0 && sections[i].sh_type == Section.SHT_DYNSYM )
syms = i;
}
}
return sections;
}
private Symbol[] loadSymbolsBySection( Section section ) throws IOException {
int numSyms = 1;
if (section.sh_entsize != 0) {
numSyms = (int)section.sh_size / (int)section.sh_entsize;
}
ArrayList symList = new ArrayList(numSyms);
for( int c = 0; c < numSyms; c++) {
efile.seek(section.sh_offset + (section.sh_entsize * c));
Symbol symbol = new Symbol( section );
symbol.st_name = efile.readIntE();
symbol.st_value = efile.readIntE();
symbol.st_size = efile.readIntE();
symbol.st_info = efile.readByte();
symbol.st_other = efile.readByte();
symbol.st_shndx = efile.readShortE();
if ( symbol.st_info == 0 )
continue;
symList.add(symbol);
}
Symbol[] results = (Symbol[])symList.toArray(new Symbol[0]);
Arrays.sort(results);
return results;
}
public void loadSymbols() throws IOException {
if ( symbols == null ) {
Section section[] = getSections(Section.SHT_SYMTAB);
if( section.length > 0 ) {
symtab_sym = section[0];
symtab_symbols = loadSymbolsBySection( section[0] );
} else {
symtab_sym = null;
symtab_symbols = new Symbol[0];
}
section = getSections(Section.SHT_DYNSYM);
if( section.length > 0 ) {
dynsym_sym = section[0];
dynsym_symbols = loadSymbolsBySection( section[0] );
} else {
dynsym_sym = null;
dynsym_symbols = new Symbol[0];
}
if( symtab_sym != null ) {
// sym = symtab_sym;
symbols = symtab_symbols;
} else if( dynsym_sym != null ) {
// sym = dynsym_sym;
symbols = dynsym_symbols;
}
}
}
public Symbol[] getSymbols() {
return symbols;
}
public Symbol[] getDynamicSymbols() {
return dynsym_symbols;
}
public Symbol[] getSymtabSymbols() {
return symtab_symbols;
}
/* return the address of the function that address is in */
public Symbol getSymbol( long vma ) {
if ( symbols == null ) {
return null;
}
//@@@ If this works, move it to a single instance in this class.
SymbolComparator symbol_comparator = new SymbolComparator();
int ndx = Arrays.binarySearch(symbols, new Long(vma), symbol_comparator);
if ( ndx > 0 )
return symbols[ndx];
if ( ndx == -1 ) {
return null;
}
ndx = -ndx - 1;
return symbols[ndx-1];
}
public long swapInt( long val ) {
if ( ehdr.e_ident[ELFhdr.EI_DATA] == ELFhdr.ELFDATA2LSB ) {
short tmp[] = new short[4];
tmp[0] = (short)(val & 0x00ff);
tmp[1] = (short)((val >> 8) & 0x00ff);
tmp[2] = (short)((val >> 16) & 0x00ff);
tmp[3] = (short)((val >> 24) & 0x00ff);
return (long)((tmp[0] << 24) + (tmp[1] << 16) + (tmp[2] << 8) + tmp[3]);
}
return val;
}
public int swapShort( short val ) {
if ( ehdr.e_ident[ELFhdr.EI_DATA] == ELFhdr.ELFDATA2LSB ) {
short tmp[] = new short[2];
tmp[0] = (short)(val & 0x00ff);
tmp[1] = (short)((val >> 8) & 0x00ff);
return (short)((tmp[0] << 8) + tmp[1]);
}
return val;
}
public String getFilename() {
return file;
}
}