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