2003/11/16 09:03:16
[org.ibex.core.git] / src / org / xwt / mips / ELF.java
index 50f7ab3..2a9b611 100644 (file)
@@ -1,13 +1,26 @@
 package org.xwt.mips;
 import java.io.*;
 
-class ELF {
-    private MyRandomAccessFile fd;
+public class ELF {
+
+    private DataInput fd;
+    private Object image;
+    private void seek(long l) throws IOException {
+        if (image instanceof RandomAccessFile) {
+            ((RandomAccessFile)image).seek(l);
+        } else if (image instanceof byte[]) {
+            ByteArrayInputStream bais = new ByteArrayInputStream((byte[])image);
+            bais.skip(l);
+            fd = new DataInputStream(bais);
+        }
+    }
     
     public ELFHeader header;
     public PHeader[] pheaders;
     public SHeader[] sheaders;
     
+    private byte[] stringTable;
+    
     private boolean sectionReaderActive;
     
     public class ELFHeader {
@@ -37,10 +50,10 @@ class ELF {
             if(fd.readInt() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " );
             klass = fd.readByte();
             data = fd.readByte();
-            fd.skipFully(1); // version
+            fd.skipBytes(1); // version
             osabi = fd.readByte();
             abiversion = fd.readByte();
-            fd.skipFully(7);
+            fd.skipBytes(7);
             type = fd.readShort();
             machine = fd.readShort();
             version = fd.readInt();
@@ -88,8 +101,8 @@ class ELF {
         public boolean writable() { return (flags & PF_W) != 0; }
         
         public InputStream getInputStream() throws IOException {
-            return new BufferedInputStream(new SectionInputStream(
-                offset,offset+filesz));
+                return new BufferedInputStream(new SectionInputStream(
+                        offset,offset+filesz));
         }
     }
     
@@ -106,7 +119,9 @@ class ELF {
         public int addralign;
         public int entsize;
         
-        public static final int T_NOBITS = 8;
+        public static final int SHT_SYMTAB = 2;
+        public static final int SHT_STRTAB = 3;
+        public static final int SHT_NOBITS = 8;
         
         SHeader() throws IOException {
             nameidx = fd.readInt();
@@ -122,36 +137,47 @@ class ELF {
         }
         
         public InputStream getInputStream() throws IOException {
-            return new BufferedInputStream(new SectionInputStream(
-                offset, type == T_NOBITS ? 0 : offset+size));
+                return new BufferedInputStream(new SectionInputStream(
+                        offset, type == SHT_NOBITS ? 0 : offset+size));
         }
     }
     
-    public ELF(String file) throws IOException, ELFException {
-        fd = new MyRandomAccessFile(file,"r");
+    public ELF(Object img) throws IOException, ELFException {
+        if (img instanceof String) {
+            image = fd = new MyRandomAccessFile((String)img, "r");
+        } else {
+            image = img;
+        }
+        seek(0);
         header = new ELFHeader();
         pheaders = new PHeader[header.phnum];
         for(int i=0;i<header.phnum;i++) {
-            fd.seek(header.phoff+i*header.phentsize);
+            seek(header.phoff+i*header.phentsize);
             pheaders[i] = new PHeader();
         }
         sheaders = new SHeader[header.shnum];
         for(int i=0;i<header.shnum;i++) {
-            fd.seek(header.shoff+i*header.shentsize);
+            seek(header.shoff+i*header.shentsize);
             sheaders[i] = new SHeader();
         }
         if(header.shstrndx < 0 || header.shstrndx >= header.shnum) throw new ELFException("Bad shstrndx");
-        fd.seek(sheaders[header.shstrndx].offset);
-        byte[] a = new byte[sheaders[header.shstrndx].size];
-        fd.readFully(a);
+        seek(sheaders[header.shstrndx].offset);
+        stringTable = new byte[sheaders[header.shstrndx].size];
+        fd.readFully(stringTable);
+        
         for(int i=0;i<header.shnum;i++) {
             SHeader s = sheaders[i];
-            StringBuffer sb = new StringBuffer();
-               for(int off = s.nameidx;off < a.length && a[off] != 0; off++) sb.append((char)a[off]);
-            s.name = sb.toString();
-        }            
+            s.name = getString(s.nameidx);
+        }
     }
-        
+    
+    private String getString(int off) { return getString(off,stringTable); }
+    private String getString(int off,byte[] strtab) {
+        StringBuffer sb = new StringBuffer();
+        while(off < strtab.length && strtab[off] != 0) sb.append((char)strtab[off++]);
+        return sb.toString();
+    }
+    
     public SHeader sectionWithName(String name) {
         for(int i=0;i<sheaders.length;i++)
             if(sheaders[i].name.equals(name))
@@ -162,12 +188,9 @@ class ELF {
     public class ELFException extends IOException { ELFException(String s) { super(s); } }
     
     private class MyRandomAccessFile extends RandomAccessFile  {
-        MyRandomAccessFile(String f,String m) throws IOException { super(f,m); }
-        public void skipFully(int n) throws IOException {
-            while(n>0) n-= skipBytes(n);
-        }
+        MyRandomAccessFile(String f,String m) throws FileNotFoundException { super(f,m); }
     }
-
+    
     private class SectionInputStream extends InputStream {
         private int pos;
         private int maxpos;
@@ -176,24 +199,78 @@ class ELF {
                 throw new IOException("Section reader already active");
             sectionReaderActive = true;
             pos = start;
-            fd.seek(pos);
+            seek(pos);
             maxpos = end;
         }
         
         private int bytesLeft() { return maxpos - pos; }
-        public int read() throws IOException { if(bytesLeft()==0) return -1; int b = fd.read(); if(b >= 0) pos++; return b; }
+        public int read() throws IOException { if(bytesLeft()==0) return -1; int b = fd.readByte(); if(b >= 0) pos++; return b; }
         public int read(byte[] b, int off, int len) throws IOException {
-            int n = fd.read(b,off,Math.min(len,bytesLeft())); if(n > 0) pos += n; return n;
+            fd.readFully(b,off,Math.min(len,bytesLeft())); return len;
         }
         public void close() { sectionReaderActive = false; }
     }
     
+    private Symtab _symtab;
+    public Symtab getSymtab() throws IOException {
+        if(_symtab != null) return _symtab;
+        
+        SHeader sh = sectionWithName(".symtab");
+        if(sh == null || sh.type != SHeader.SHT_SYMTAB) return null;
+        
+        SHeader sth = sectionWithName(".strtab");
+        if(sth == null || sth.type != SHeader.SHT_STRTAB) return null;
+        
+        byte[] strtab = new byte[sth.size];
+        DataInputStream dis = new DataInputStream(sth.getInputStream());
+        dis.readFully(strtab);
+        dis.close();
+        
+        return _symtab = new Symtab(sh.getInputStream(),sh.size,strtab);
+    }
+    
+    public class  Symtab {
+        public Symbol[] symbols;
+        
+        Symtab(InputStream is, int size, byte[] strtab) throws IOException {
+            DataInputStream dis = new DataInputStream(is);
+            int count = size/16;
+            symbols = new Symbol[count];
+            for(int i=0;i<count;i++) symbols[i] = new Symbol(dis,strtab);
+            dis.close();
+        }
+    }
+    
+    public class Symbol {
+        public String name;
+        public int addr;
+        public int size;
+        public byte info;
+        public byte type;
+        public byte other;
+        public SHeader sheader;
+        
+        public final static int STT_FUNC = 2;
+        
+        Symbol(DataInputStream dis, byte[] strtab) throws IOException {
+            name = getString(dis.readInt(),strtab);
+            addr = dis.readInt();
+            size = dis.readInt();
+            info = dis.readByte();
+            type = (byte)(info&0xf);
+            other = dis.readByte();
+            // FIXME: Find sheader entry
+            dis.readShort();
+        }
+    }
+    
     private static String toHex(int n) { return "0x" + Long.toString(n & 0xffffffffL, 16); }
     
     public static void main(String[] args) throws IOException {
         ELF elf = new ELF(args[0]);
         System.out.println("Type: " + toHex(elf.header.type));
         System.out.println("Machine: " + toHex(elf.header.machine));
+        System.out.println("Entry: " + toHex(elf.header.entry));
         for(int i=0;i<elf.pheaders.length;i++) {
             ELF.PHeader ph = elf.pheaders[i];
             System.out.println("PHeader " + toHex(i));
@@ -211,5 +288,6 @@ class ELF {
             System.out.println("\tSize: " + sh.size);
             System.out.println("\tType: " + toHex(sh.type));
         }
+        Symtab symtab = elf.getSymtab();
     }
 }