8 private void seek(long l) throws IOException {
9 if (image instanceof RandomAccessFile) {
10 ((RandomAccessFile)image).seek(l);
11 } else if (image instanceof byte[]) {
12 ByteArrayInputStream bais = new ByteArrayInputStream((byte[])image);
14 fd = new DataInputStream(bais);
18 public ELFHeader header;
19 public PHeader[] pheaders;
20 public SHeader[] sheaders;
22 private byte[] stringTable;
24 private boolean sectionReaderActive;
26 public class ELFHeader {
32 public static final short ET_EXEC = 2;
34 public static final short EM_MIPS = 8;
42 public short phentsize;
44 public short shentsize;
46 public short shstrndx;
48 private static final int ELF_MAGIC = 0x7f454c46; // '\177', 'E', 'L', 'F'
49 ELFHeader() throws IOException {
50 if(fd.readInt() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " );
51 klass = fd.readByte();
53 fd.skipBytes(1); // version
54 osabi = fd.readByte();
55 abiversion = fd.readByte();
57 type = fd.readShort();
58 machine = fd.readShort();
59 version = fd.readInt();
64 ehsize = fd.readShort();
65 phentsize = fd.readShort();
66 phnum = fd.readShort();
67 shentsize = fd.readShort();
68 shnum = fd.readShort();
69 shstrndx = fd.readShort();
73 public class PHeader {
83 public static final int PF_X = 0x1;
84 public static final int PF_W = 0x2;
85 public static final int PF_R = 0x4;
87 public static final int PT_LOAD = 1;
89 PHeader() throws IOException {
91 offset = fd.readInt();
94 filesz = fd.readInt();
98 if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz");
101 public boolean writable() { return (flags & PF_W) != 0; }
103 public InputStream getInputStream() throws IOException {
104 return new BufferedInputStream(new SectionInputStream(
105 offset,offset+filesz));
109 public class SHeader {
119 public int addralign;
122 public static final int SHT_SYMTAB = 2;
123 public static final int SHT_STRTAB = 3;
124 public static final int SHT_NOBITS = 8;
126 SHeader() throws IOException {
127 nameidx = fd.readInt();
129 flags = fd.readInt();
131 offset = fd.readInt();
135 addralign = fd.readInt();
136 entsize = fd.readInt();
139 public InputStream getInputStream() throws IOException {
140 return new BufferedInputStream(new SectionInputStream(
141 offset, type == SHT_NOBITS ? 0 : offset+size));
145 public ELF(Object img) throws IOException, ELFException {
146 if (img instanceof String) {
147 image = fd = new MyRandomAccessFile((String)img, "r");
152 header = new ELFHeader();
153 pheaders = new PHeader[header.phnum];
154 for(int i=0;i<header.phnum;i++) {
155 seek(header.phoff+i*header.phentsize);
156 pheaders[i] = new PHeader();
158 sheaders = new SHeader[header.shnum];
159 for(int i=0;i<header.shnum;i++) {
160 seek(header.shoff+i*header.shentsize);
161 sheaders[i] = new SHeader();
163 if(header.shstrndx < 0 || header.shstrndx >= header.shnum) throw new ELFException("Bad shstrndx");
164 seek(sheaders[header.shstrndx].offset);
165 stringTable = new byte[sheaders[header.shstrndx].size];
166 fd.readFully(stringTable);
168 for(int i=0;i<header.shnum;i++) {
169 SHeader s = sheaders[i];
170 s.name = getString(s.nameidx);
174 private String getString(int off) { return getString(off,stringTable); }
175 private String getString(int off,byte[] strtab) {
176 StringBuffer sb = new StringBuffer();
177 while(off < strtab.length && strtab[off] != 0) sb.append((char)strtab[off++]);
178 return sb.toString();
181 public SHeader sectionWithName(String name) {
182 for(int i=0;i<sheaders.length;i++)
183 if(sheaders[i].name.equals(name))
188 public class ELFException extends IOException { ELFException(String s) { super(s); } }
190 private class MyRandomAccessFile extends RandomAccessFile {
191 MyRandomAccessFile(String f,String m) throws IOException { super(f,m); }
194 private class SectionInputStream extends InputStream {
197 SectionInputStream(int start, int end) throws IOException {
198 if(sectionReaderActive)
199 throw new IOException("Section reader already active");
200 sectionReaderActive = true;
206 private int bytesLeft() { return maxpos - pos; }
207 public int read() throws IOException { if(bytesLeft()==0) return -1; int b = fd.readByte(); if(b >= 0) pos++; return b; }
208 public int read(byte[] b, int off, int len) throws IOException {
209 fd.readFully(b,off,Math.min(len,bytesLeft())); return len;
211 public void close() { sectionReaderActive = false; }
214 private Symtab _symtab;
215 public Symtab getSymtab() throws IOException {
216 if(_symtab != null) return _symtab;
218 SHeader sh = sectionWithName(".symtab");
219 if(sh == null || sh.type != SHeader.SHT_SYMTAB) return null;
221 SHeader sth = sectionWithName(".strtab");
222 if(sth == null || sth.type != SHeader.SHT_STRTAB) return null;
224 byte[] strtab = new byte[sth.size];
225 DataInputStream dis = new DataInputStream(sth.getInputStream());
226 dis.readFully(strtab);
229 return _symtab = new Symtab(sh.getInputStream(),sh.size,strtab);
232 public class Symtab {
233 public Symbol[] symbols;
235 Symtab(InputStream is, int size, byte[] strtab) throws IOException {
236 DataInputStream dis = new DataInputStream(is);
238 symbols = new Symbol[count];
239 for(int i=0;i<count;i++) symbols[i] = new Symbol(dis,strtab);
244 public class Symbol {
251 public SHeader sheader;
253 public final static int STT_FUNC = 2;
255 Symbol(DataInputStream dis, byte[] strtab) throws IOException {
256 name = getString(dis.readInt(),strtab);
257 addr = dis.readInt();
258 size = dis.readInt();
259 info = dis.readByte();
260 type = (byte)(info&0xf);
261 other = dis.readByte();
262 // FIXME: Find sheader entry
267 private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
269 public static void main(String[] args) throws IOException {
270 ELF elf = new ELF(args[0]);
271 System.out.println("Type: " + toHex(elf.header.type));
272 System.out.println("Machine: " + toHex(elf.header.machine));
273 System.out.println("Entry: " + toHex(elf.header.entry));
274 for(int i=0;i<elf.pheaders.length;i++) {
275 ELF.PHeader ph = elf.pheaders[i];
276 System.out.println("PHeader " + toHex(i));
277 System.out.println("\tOffset: " + ph.offset);
278 System.out.println("\tVaddr: " + toHex(ph.vaddr));
279 System.out.println("\tFile Size: " + ph.filesz);
280 System.out.println("\tMem Size: " + ph.memsz);
282 for(int i=0;i<elf.sheaders.length;i++) {
283 ELF.SHeader sh = elf.sheaders[i];
284 System.out.println("SHeader " + toHex(i));
285 System.out.println("\tName: " + sh.name);
286 System.out.println("\tOffset: " + sh.offset);
287 System.out.println("\tAddr: " + toHex(sh.addr));
288 System.out.println("\tSize: " + sh.size);
289 System.out.println("\tType: " + toHex(sh.type));
291 Symtab symtab = elf.getSymtab();