2003/09/20 05:03:47
[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         
105         public InputStream getInputStream() throws IOException {
106             return new BufferedInputStream(new SectionInputStream(
107                 offset,offset+filesz));
108         }
109     }
110     
111     public class SHeader {
112         int nameidx;
113         public String name;
114         public int type;
115         public int flags;
116         public int addr;
117         public int offset;
118         public int size;
119         public int link;
120         public int info;
121         public int addralign;
122         public int entsize;
123         
124         public static final int T_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 == T_NOBITS ? 0 : offset+size));
142         }
143     }
144     
145     public ELF(Object img) throws IOException, ELFException {
146         image = img;
147         seek(0);
148         header = new ELFHeader();
149         pheaders = new PHeader[header.phnum];
150         for(int i=0;i<header.phnum;i++) {
151             seek(header.phoff+i*header.phentsize);
152             pheaders[i] = new PHeader();
153         }
154         sheaders = new SHeader[header.shnum];
155         for(int i=0;i<header.shnum;i++) {
156             seek(header.shoff+i*header.shentsize);
157             sheaders[i] = new SHeader();
158         }
159         if(header.shstrndx < 0 || header.shstrndx >= header.shnum) throw new ELFException("Bad shstrndx");
160         seek(sheaders[header.shstrndx].offset);
161         byte[] a = new byte[sheaders[header.shstrndx].size];
162         fd.readFully(a);
163         for(int i=0;i<header.shnum;i++) {
164             SHeader s = sheaders[i];
165             StringBuffer sb = new StringBuffer();
166                for(int off = s.nameidx;off < a.length && a[off] != 0; off++) sb.append((char)a[off]);
167             s.name = sb.toString();
168         }            
169     }
170         
171     public SHeader sectionWithName(String name) {
172         for(int i=0;i<sheaders.length;i++)
173             if(sheaders[i].name.equals(name))
174                 return sheaders[i];
175         return null;
176     }
177     
178     public class ELFException extends IOException { ELFException(String s) { super(s); } }
179     
180     private class SectionInputStream extends InputStream {
181         private int pos;
182         private int maxpos;
183         SectionInputStream(int start, int end) throws IOException {
184             if(sectionReaderActive)
185                 throw new IOException("Section reader already active");
186             sectionReaderActive = true;
187             pos = start;
188             seek(pos);
189             maxpos = end;
190         }
191         
192         private int bytesLeft() { return maxpos - pos; }
193         public int read() throws IOException {
194             if(bytesLeft()==0) return -1;
195             try {
196                 byte b = fd.readByte();
197                 pos++;
198                 return b;
199             } catch (EOFException e) {
200                 return -1;
201             }
202         }
203         public int read(byte[] b, int off, int len) throws IOException {
204             fd.readFully(b, off, len);
205             return len;
206         }
207         public void close() { sectionReaderActive = false; }
208     }
209     
210     private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
211     
212     public static void main(String[] args) throws IOException {
213         ELF elf = new ELF(args[0]);
214         System.out.println("Type: " + toHex(elf.header.type));
215         System.out.println("Machine: " + toHex(elf.header.machine));
216         for(int i=0;i<elf.pheaders.length;i++) {
217             ELF.PHeader ph = elf.pheaders[i];
218             System.out.println("PHeader " + toHex(i));
219             System.out.println("\tOffset: " + ph.offset);
220             System.out.println("\tVaddr: " + toHex(ph.vaddr));
221             System.out.println("\tFile Size: " + ph.filesz);
222             System.out.println("\tMem Size: " + ph.memsz);
223         }
224         for(int i=0;i<elf.sheaders.length;i++) {
225             ELF.SHeader sh = elf.sheaders[i];
226             System.out.println("SHeader " + toHex(i));
227             System.out.println("\tName: " + sh.name);
228             System.out.println("\tOffset: " + sh.offset);
229             System.out.println("\tAddr: " + toHex(sh.addr));
230             System.out.println("\tSize: " + sh.size);
231             System.out.println("\tType: " + toHex(sh.type));
232         }
233     }
234 }