91dd79d833d3cf6c963f15cc5cc1e8be6e1c4ee4
[org.ibex.core.git] / src / org / xwt / mips / ELF.java
1 package org.xwt.mips;
2 import java.io.*;
3
4 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 boolean sectionReaderActive;
23     
24     private static void skipFully(DataInput fd, int n) throws IOException {
25         while(n>0) n -= fd.skipBytes(n);
26     }
27
28     public class ELFHeader {
29         byte klass;
30         byte data;
31         byte osabi;
32         byte abiversion;
33         
34         public static final short ET_EXEC = 2;
35         public short type;
36         public static final short EM_MIPS = 8;
37         public short machine;
38         public int version;
39         public int entry;
40         public int phoff;
41         public int shoff;
42         public int flags;
43         public short ehsize;
44         public short phentsize;
45         public short phnum;
46         public short shentsize;
47         public short shnum;
48         public short shstrndx;
49
50         private static final int ELF_MAGIC = 0x7f454c46; // '\177', 'E', 'L', 'F'
51         ELFHeader() throws IOException {
52             if(fd.readInt() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " );
53             klass = fd.readByte();
54             data = fd.readByte();
55             skipFully(fd, 1); // version
56             osabi = fd.readByte();
57             abiversion = fd.readByte();
58             skipFully(fd, 7);
59             type = fd.readShort();
60             machine = fd.readShort();
61             version = fd.readInt();
62             entry = fd.readInt();
63             phoff = fd.readInt();
64             shoff = fd.readInt();
65             flags = fd.readInt();
66             ehsize = fd.readShort();
67             phentsize = fd.readShort();
68             phnum = fd.readShort();
69             shentsize = fd.readShort();
70             shnum = fd.readShort();
71             shstrndx = fd.readShort();
72         }
73     }
74     
75     public class PHeader {
76         public int type;
77         public int offset;
78         public int vaddr;
79         public int paddr;
80         public int filesz;
81         public int memsz;
82         public int flags;
83         public int align;
84         
85         public static final int PF_X = 0x1;
86         public static final int PF_W = 0x2;
87         public static final int PF_R = 0x4;
88         
89         public static final int PT_LOAD = 1;
90         
91         PHeader() throws IOException {
92             type = fd.readInt();
93             offset = fd.readInt();
94             vaddr = fd.readInt();
95             paddr = fd.readInt();
96             filesz = fd.readInt();
97             memsz = fd.readInt();
98             flags = fd.readInt();
99             align = fd.readInt();
100             if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz");
101         }
102         
103         public boolean writable() { return (flags & PF_W) != 0; }
104         public boolean executable() { return (flags & PF_X) != 0; }
105         
106         public InputStream getInputStream() throws IOException {
107             return new BufferedInputStream(new SectionInputStream(
108                 offset,offset+filesz));
109         }
110     }
111     
112     public class SHeader {
113         int nameidx;
114         public String name;
115         public int type;
116         public int flags;
117         public int addr;
118         public int offset;
119         public int size;
120         public int link;
121         public int info;
122         public int addralign;
123         public int entsize;
124         
125         public static final int T_NOBITS = 8;
126         
127         SHeader() throws IOException {
128             nameidx = fd.readInt();
129             type = fd.readInt();
130             flags = fd.readInt();
131             addr = fd.readInt();
132             offset = fd.readInt();
133             size = fd.readInt();
134             link = fd.readInt();
135             info = fd.readInt();
136             addralign = fd.readInt();
137             entsize = fd.readInt();
138         }
139         
140         public InputStream getInputStream() throws IOException {
141             return new BufferedInputStream(new SectionInputStream(
142                 offset, type == T_NOBITS ? 0 : offset+size));
143         }
144     }
145     
146     public ELF(Object img) throws IOException, ELFException {
147         image = img;
148         seek(0);
149         header = new ELFHeader();
150         pheaders = new PHeader[header.phnum];
151         for(int i=0;i<header.phnum;i++) {
152             seek(header.phoff+i*header.phentsize);
153             pheaders[i] = new PHeader();
154         }
155         sheaders = new SHeader[header.shnum];
156         for(int i=0;i<header.shnum;i++) {
157             seek(header.shoff+i*header.shentsize);
158             sheaders[i] = new SHeader();
159         }
160         if(header.shstrndx < 0 || header.shstrndx >= header.shnum) throw new ELFException("Bad shstrndx");
161         seek(sheaders[header.shstrndx].offset);
162         byte[] a = new byte[sheaders[header.shstrndx].size];
163         fd.readFully(a);
164         for(int i=0;i<header.shnum;i++) {
165             SHeader s = sheaders[i];
166             StringBuffer sb = new StringBuffer();
167                for(int off = s.nameidx;off < a.length && a[off] != 0; off++) sb.append((char)a[off]);
168             s.name = sb.toString();
169         }            
170     }
171         
172     public SHeader sectionWithName(String name) {
173         for(int i=0;i<sheaders.length;i++)
174             if(sheaders[i].name.equals(name))
175                 return sheaders[i];
176         return null;
177     }
178     
179     public class ELFException extends IOException { ELFException(String s) { super(s); } }
180     
181     private class SectionInputStream extends InputStream {
182         private int pos;
183         private int maxpos;
184         SectionInputStream(int start, int end) throws IOException {
185             if(sectionReaderActive)
186                 throw new IOException("Section reader already active");
187             sectionReaderActive = true;
188             pos = start;
189             seek(pos);
190             maxpos = end;
191         }
192         
193         private int bytesLeft() { return maxpos - pos; }
194         public int read() throws IOException {
195             if(bytesLeft()==0) return -1;
196             try {
197                 byte b = fd.readByte();
198                 pos++;
199                 return b;
200             } catch (EOFException e) {
201                 return -1;
202             }
203         }
204         public int read(byte[] b, int off, int len) throws IOException {
205             fd.readFully(b, off, len);
206             return len;
207         }
208         public void close() { sectionReaderActive = false; }
209     }
210     
211     private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
212     
213     public static void main(String[] args) throws IOException {
214         ELF elf = new ELF(args[0]);
215         System.out.println("Type: " + toHex(elf.header.type));
216         System.out.println("Machine: " + toHex(elf.header.machine));
217         for(int i=0;i<elf.pheaders.length;i++) {
218             ELF.PHeader ph = elf.pheaders[i];
219             System.out.println("PHeader " + toHex(i));
220             System.out.println("\tOffset: " + ph.offset);
221             System.out.println("\tVaddr: " + toHex(ph.vaddr));
222             System.out.println("\tFile Size: " + ph.filesz);
223             System.out.println("\tMem Size: " + ph.memsz);
224         }
225         for(int i=0;i<elf.sheaders.length;i++) {
226             ELF.SHeader sh = elf.sheaders[i];
227             System.out.println("SHeader " + toHex(i));
228             System.out.println("\tName: " + sh.name);
229             System.out.println("\tOffset: " + sh.offset);
230             System.out.println("\tAddr: " + toHex(sh.addr));
231             System.out.println("\tSize: " + sh.size);
232             System.out.println("\tType: " + toHex(sh.type));
233         }
234     }
235 }