X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fxwt%2Fmips%2FELF.java;fp=src%2Forg%2Fxwt%2Fmips%2FELF.java;h=18698f20e58776891d173469d2b928a7d072d3b7;hp=0000000000000000000000000000000000000000;hb=3eb15f58ca0911489d7d9bdc0ac2c575d27a68d8;hpb=a6ee28ca37621098ed040e6d1c4ae103934c3e97 diff --git a/src/org/xwt/mips/ELF.java b/src/org/xwt/mips/ELF.java new file mode 100644 index 0000000..18698f2 --- /dev/null +++ b/src/org/xwt/mips/ELF.java @@ -0,0 +1,381 @@ +package org.xwt.mips; + +import org.xwt.mips.util.*; +import java.io.*; + +public class ELF { + private SeekableData data; + + public ELFIdent ident; + public ELFHeader header; + public PHeader[] pheaders; + public SHeader[] sheaders; + + private byte[] stringTable; + + private boolean sectionReaderActive; + + + private void readFully(byte[] buf) throws IOException { + int len = buf.length; + int pos = 0; + while(len > 0) { + int n = data.read(buf,pos,len); + if(n == -1) throw new IOException("EOF"); + pos += n; + len -= n; + } + } + + private int readIntBE() throws IOException { + byte[] buf = new byte[4]; + readFully(buf); + return ((buf[0]&0xff)<<24)|((buf[1]&0xff)<<16)|((buf[2]&0xff)<<8)|((buf[3]&0xff)<<0); + } + private int readInt() throws IOException { + int x = readIntBE(); + if(ident!=null && ident.data == ELFIdent.ELFDATA2LSB) + x = ((x<<24)&0xff000000) | ((x<<8)&0xff0000) | ((x>>>8)&0xff00) | ((x>>24)&0xff); + return x; + } + + private short readShortBE() throws IOException { + byte[] buf = new byte[2]; + readFully(buf); + return (short)(((buf[0]&0xff)<<8)|((buf[1]&0xff)<<0)); + } + private short readShort() throws IOException { + short x = readShortBE(); + if(ident!=null && ident.data == ELFIdent.ELFDATA2LSB) + x = (short)((((x<<8)&0xff00) | ((x>>8)&0xff))&0xffff); + return x; + } + + private byte readByte() throws IOException { + byte[] buf = new byte[1]; + readFully(buf); + return buf[0]; + } + + public class ELFIdent { + private static final int ELF_MAGIC = 0x7f454c46; // '\177', 'E', 'L', 'F' + + public static final int ELFCLASSNONE = 0; + public static final int ELFCLASS32 = 1; + public static final int ELFCLASS64 = 2; + public byte klass; + + + public static final int ELFDATANONE = 0; + public static final int ELFDATA2LSB = 1; + public static final int ELFDATA2MSB = 2; + public byte data; + public byte osabi; + public byte abiversion; + + ELFIdent() throws IOException { + if(readIntBE() != ELF_MAGIC) throw new ELFException("Bad Magic (is: " ); + + klass = readByte(); + if(klass != ELFCLASS32) throw new ELFException("org.xwt.mips.ELF does not suport 64-bit binaries"); + + data = readByte(); + if(data != ELFDATA2LSB && data != ELFDATA2MSB) throw new ELFException("Unknown byte order"); + + readByte(); // version + osabi = readByte(); + abiversion = readByte(); + for(int i=0;i<7;i++) readByte(); // padding + } + } + + public class ELFHeader { + public static final short ET_EXEC = 2; + public short type; + + public static final short EM_MIPS = 8; + public short machine; + + public int version; + public int entry; + public int phoff; + public int shoff; + public int flags; + public short ehsize; + public short phentsize; + public short phnum; + public short shentsize; + public short shnum; + public short shstrndx; + + ELFHeader() throws IOException { + type = readShort(); + machine = readShort(); + version = readInt(); + if(version != 1) throw new ELFException("version != 1"); + entry = readInt(); + phoff = readInt(); + shoff = readInt(); + flags = readInt(); + ehsize = readShort(); + phentsize = readShort(); + phnum = readShort(); + shentsize = readShort(); + shnum = readShort(); + shstrndx = readShort(); + } + } + + public class PHeader { + public int type; + public int offset; + public int vaddr; + public int paddr; + public int filesz; + public int memsz; + public int flags; + public int align; + + public static final int PF_X = 0x1; + public static final int PF_W = 0x2; + public static final int PF_R = 0x4; + + public static final int PT_LOAD = 1; + + PHeader() throws IOException { + type = readInt(); + offset = readInt(); + vaddr = readInt(); + paddr = readInt(); + filesz = readInt(); + memsz = readInt(); + flags = readInt(); + align = readInt(); + if(filesz > memsz) throw new ELFException("ELF inconsistency: filesz > memsz (" + toHex(filesz) + " > " + toHex(memsz) + ")"); + } + + public boolean writable() { return (flags & PF_W) != 0; } + + public InputStream getInputStream() throws IOException { + return new BufferedInputStream(new SectionInputStream( + offset,offset+filesz)); + } + } + + public class SHeader { + int nameidx; + public String name; + public int type; + public int flags; + public int addr; + public int offset; + public int size; + public int link; + public int info; + public int addralign; + public int entsize; + + 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 = readInt(); + type = readInt(); + flags = readInt(); + addr = readInt(); + offset = readInt(); + size = readInt(); + link = readInt(); + info = readInt(); + addralign = readInt(); + entsize = readInt(); + } + + public InputStream getInputStream() throws IOException { + return new BufferedInputStream(new SectionInputStream( + offset, type == SHT_NOBITS ? 0 : offset+size)); + } + + public boolean isText() { return name.equals(".text"); } + public boolean isData() { return name.equals(".data") || name.equals(".sdata") || name.equals(".rodata") || name.equals(".ctors") || name.equals(".dtors"); } + public boolean isBSS() { return name.equals(".bss") || name.equals(".sbss"); } + } + + public ELF(String file) throws IOException, ELFException { this(new SeekableFile(file,false)); } + public ELF(SeekableData data) throws IOException, ELFException { + this.data = data; + ident = new ELFIdent(); + header = new ELFHeader(); + pheaders = new PHeader[header.phnum]; + for(int i=0;i= header.shnum) throw new ELFException("Bad shstrndx"); + data.seek(sheaders[header.shstrndx].offset); + stringTable = new byte[sheaders[header.shstrndx].size]; + readFully(stringTable); + + for(int i=0;i= strtab.length) return ""; + while(off >= 0 && off < strtab.length && strtab[off] != 0) sb.append((char)strtab[off++]); + return sb.toString(); + } + + public SHeader sectionWithName(String name) { + for(int i=0;i 0) pos += n; return n; + } + public void close() { sectionReaderActive = false; } + } + + private Symtab _symtab; + public Symtab getSymtab() throws IOException { + if(_symtab != null) return _symtab; + + if(sectionReaderActive) throw new ELFException("Can't read the symtab while a section reader is active"); + + 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.offset, sh.size,strtab); + } + + public class Symtab { + public Symbol[] symbols; + + Symtab(int off, int size, byte[] strtab) throws IOException { + data.seek(off); + int count = size/16; + symbols = new Symbol[count]; + for(int i=0;i>4); + other = readByte(); + // FEATURE: This should point to some other entry or something + 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(new SeekableInputStream(new FileInputStream(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 " + toHex(symtab.symbols[i].addr)); + } else { + System.out.println("Symbol table: None"); + } + } +}