1 package org.xwt.mips;
2 import java.io.*;
3
4 public class ELF {
5
6 private DataInput fd;
7 private Object image;
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);
13 bais.skip(l);
14 fd = new DataInputStream(bais);
15 }
16 }
17
18 public ELFHeader header;
19 public PHeader[] pheaders;
20 public SHeader[] sheaders;
21
22 private byte[] stringTable;
23
24 private boolean sectionReaderActive;
25
26 public class ELFHeader {
27 byte klass;
28 byte data;
29 byte osabi;
30 byte abiversion;
31
32 public static final short ET_EXEC = 2;
33 public short type;
34 public static final short EM_MIPS = 8;
35 public short machine;
36 public int version;
37 public int entry;
38 public int phoff;
39 public int shoff;
40 public int flags;
41 public short ehsize;
42 public short phentsize;
43 public short phnum;
44 public short shentsize;
45 public short shnum;
46 public short shstrndx;
47
48 private static final int ELF_MAGIC = 0x7f454c46;
49 ELFHeader() throws IOException {
50 if(fd.readInt() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " );
51 klass = fd.readByte();
52 data = fd.readByte();
53 fd.skipBytes(1);
54 osabi = fd.readByte();
55 abiversion = fd.readByte();
56 fd.skipBytes(7);
57 type = fd.readShort();
58 machine = fd.readShort();
59 version = fd.readInt();
60 entry = fd.readInt();
61 phoff = fd.readInt();
62 shoff = fd.readInt();
63 flags = 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();
70 }
71 }
72
73 public class PHeader {
74 public int type;
75 public int offset;
76 public int vaddr;
77 public int paddr;
78 public int filesz;
79 public int memsz;
80 public int flags;
81 public int align;
82
83 public static final int PF_X = 0x1;
84 public static final int PF_W = 0x2;
85 public static final int PF_R = 0x4;
86
87 public static final int PT_LOAD = 1;
88
89 PHeader() throws IOException {
90 type = fd.readInt();
91 offset = fd.readInt();
92 vaddr = fd.readInt();
93 paddr = fd.readInt();
94 filesz = fd.readInt();
95 memsz = fd.readInt();
96 flags = fd.readInt();
97 align = fd.readInt();
98 if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz");
99 }
100
101 public boolean writable() { return (flags & PF_W) != 0; }
102
103 public InputStream getInputStream() throws IOException {
104 return new BufferedInputStream(new SectionInputStream(
105 offset,offset+filesz));
106 }
107 }
108
109 public class SHeader {
110 int nameidx;
111 public String name;
112 public int type;
113 public int flags;
114 public int addr;
115 public int offset;
116 public int size;
117 public int link;
118 public int info;
119 public int addralign;
120 public int entsize;
121
122 public static final int SHT_SYMTAB = 2;
123 public static final int SHT_STRTAB = 3;
124 public static final int SHT_NOBITS = 8;
125
126 SHeader() throws IOException {
127 nameidx = fd.readInt();
128 type = fd.readInt();
129 flags = fd.readInt();
130 addr = fd.readInt();
131 offset = fd.readInt();
132 size = fd.readInt();
133 link = fd.readInt();
134 info = fd.readInt();
135 addralign = fd.readInt();
136 entsize = fd.readInt();
137 }
138
139 public InputStream getInputStream() throws IOException {
140 return new BufferedInputStream(new SectionInputStream(
141 offset, type == SHT_NOBITS ? 0 : offset+size));
142 }
143 }
144
145 public ELF(Object img) throws IOException, ELFException {
146 if (img instanceof String) {
147 image = fd = new MyRandomAccessFile((String)img, "r");
148 } else {
149 image = img;
150 }
151 seek(0);
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();
157 }
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();
162 }
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);
167
168 for(int i=0;i<header.shnum;i++) {
169 SHeader s = sheaders[i];
170 s.name = getString(s.nameidx);
171 }
172 }
173
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();
179 }
180
181 public SHeader sectionWithName(String name) {
182 for(int i=0;i<sheaders.length;i++)
183 if(sheaders[i].name.equals(name))
184 return sheaders[i];
185 return null;
186 }
187
188 public class ELFException extends IOException { ELFException(String s) { super(s); } }
189
190 private class MyRandomAccessFile extends RandomAccessFile {
191 MyRandomAccessFile(String f,String m) throws IOException { super(f,m); }
192 }
193
194 private class SectionInputStream extends InputStream {
195 private int pos;
196 private int maxpos;
197 SectionInputStream(int start, int end) throws IOException {
198 if(sectionReaderActive)
199 throw new IOException("Section reader already active");
200 sectionReaderActive = true;
201 pos = start;
202 seek(pos);
203 maxpos = end;
204 }
205
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;
210 }
211 public void close() { sectionReaderActive = false; }
212 }
213
214 private Symtab _symtab;
215 public Symtab getSymtab() throws IOException {
216 if(_symtab != null) return _symtab;
217
218 SHeader sh = sectionWithName(".symtab");
219 if(sh == null || sh.type != SHeader.SHT_SYMTAB) return null;
220
221 SHeader sth = sectionWithName(".strtab");
222 if(sth == null || sth.type != SHeader.SHT_STRTAB) return null;
223
224 byte[] strtab = new byte[sth.size];
225 DataInputStream dis = new DataInputStream(sth.getInputStream());
226 dis.readFully(strtab);
227 dis.close();
228
229 return _symtab = new Symtab(sh.getInputStream(),sh.size,strtab);
230 }
231
232 public class Symtab {
233 public Symbol[] symbols;
234
235 Symtab(InputStream is, int size, byte[] strtab) throws IOException {
236 DataInputStream dis = new DataInputStream(is);
237 int count = size/16;
238 symbols = new Symbol[count];
239 for(int i=0;i<count;i++) symbols[i] = new Symbol(dis,strtab);
240 dis.close();
241 }
242 }
243
244 public class Symbol {
245 public String name;
246 public int addr;
247 public int size;
248 public byte info;
249 public byte type;
250 public byte other;
251 public SHeader sheader;
252
253 public final static int STT_FUNC = 2;
254
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
263 dis.readShort();
264 }
265 }
266
267 private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
268
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);
281 }
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));
290 }
291 Symtab symtab = elf.getSymtab();
292 }
293 }
294