2003/11/16 09:03:16
[org.ibex.core.git] / src / org / xwt / mips / ELF.java
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; // '\177', 'E', 'L', 'F'
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); // version
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 FileNotFoundException { 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             // FIXME: Find sheader entry
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 }