2003/11/16 09:03:16
[org.ibex.core.git] / src / org / xwt / mips / ELF.java
index 91dd79d..2a9b611 100644 (file)
@@ -1,7 +1,7 @@
 package org.xwt.mips;
 import java.io.*;
 
-class ELF {
+public class ELF {
 
     private DataInput fd;
     private Object image;
@@ -19,12 +19,10 @@ class ELF {
     public PHeader[] pheaders;
     public SHeader[] sheaders;
     
+    private byte[] stringTable;
+    
     private boolean sectionReaderActive;
     
-    private static void skipFully(DataInput fd, int n) throws IOException {
-        while(n>0) n -= fd.skipBytes(n);
-    }
-
     public class ELFHeader {
         byte klass;
         byte data;
@@ -52,10 +50,10 @@ class ELF {
             if(fd.readInt() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " );
             klass = fd.readByte();
             data = fd.readByte();
-            skipFully(fd, 1); // version
+            fd.skipBytes(1); // version
             osabi = fd.readByte();
             abiversion = fd.readByte();
-            skipFully(fd, 7);
+            fd.skipBytes(7);
             type = fd.readShort();
             machine = fd.readShort();
             version = fd.readInt();
@@ -101,11 +99,10 @@ class ELF {
         }
         
         public boolean writable() { return (flags & PF_W) != 0; }
-        public boolean executable() { return (flags & PF_X) != 0; }
         
         public InputStream getInputStream() throws IOException {
-            return new BufferedInputStream(new SectionInputStream(
-                offset,offset+filesz));
+                return new BufferedInputStream(new SectionInputStream(
+                        offset,offset+filesz));
         }
     }
     
@@ -122,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();
@@ -138,13 +137,17 @@ 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(Object img) throws IOException, ELFException {
-        image = img;
+        if (img instanceof String) {
+            image = fd = new MyRandomAccessFile((String)img, "r");
+        } else {
+            image = img;
+        }
         seek(0);
         header = new ELFHeader();
         pheaders = new PHeader[header.phnum];
@@ -159,16 +162,22 @@ class ELF {
         }
         if(header.shstrndx < 0 || header.shstrndx >= header.shnum) throw new ELFException("Bad shstrndx");
         seek(sheaders[header.shstrndx].offset);
-        byte[] a = new byte[sheaders[header.shstrndx].size];
-        fd.readFully(a);
+        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))
@@ -178,6 +187,10 @@ class ELF {
     
     public class ELFException extends IOException { ELFException(String s) { super(s); } }
     
+    private class MyRandomAccessFile extends RandomAccessFile  {
+        MyRandomAccessFile(String f,String m) throws FileNotFoundException { super(f,m); }
+    }
+    
     private class SectionInputStream extends InputStream {
         private int pos;
         private int maxpos;
@@ -191,29 +204,73 @@ class ELF {
         }
         
         private int bytesLeft() { return maxpos - pos; }
-        public int read() throws IOException {
-            if(bytesLeft()==0) return -1;
-            try {
-                byte b = fd.readByte();
-                pos++;
-                return b;
-            } catch (EOFException e) {
-                return -1;
-            }
-        }
+        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 {
-            fd.readFully(b, off, len);
-            return len;
+            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));
@@ -231,5 +288,6 @@ class ELF {
             System.out.println("\tSize: " + sh.size);
             System.out.println("\tType: " + toHex(sh.type));
         }
+        Symtab symtab = elf.getSymtab();
     }
 }